1
Nuvoton new board models, and some more minor stuff. I also put
1
Hi; here's the latest round of arm patches. I have included also
2
in the deprecation patches for unicore32 and lm32.
2
my patchset for the RTC devices to avoid keeping time_t and
3
time_t diffs in 32-bit variables.
3
4
4
thanks
5
thanks
5
-- PMM
6
-- PMM
6
7
7
The following changes since commit a68694cd1f3e5448cca814ff39b871f9ebd71ed5:
8
The following changes since commit 156618d9ea67f2f2e31d9dedd97f2dcccbe6808c:
8
9
9
Merge remote-tracking branch 'remotes/philmd-gitlab/tags/edk2-next-20200914' into staging (2020-09-14 12:18:58 +0100)
10
Merge tag 'block-pull-request' of https://gitlab.com/stefanha/qemu into staging (2023-08-30 09:20:27 -0400)
10
11
11
are available in the Git repository at:
12
are available in the Git repository at:
12
13
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200914
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20230831
14
15
15
for you to fetch changes up to dd44ae00fc5342ed99acb68ec3508f76a71d523a:
16
for you to fetch changes up to e73b8bb8a3e9a162f70e9ffbf922d4fafc96bbfb:
16
17
17
MAINTAINERS: Add maintainer entry for Xilinx ZynqMP CAN controller (2020-09-14 14:27:08 +0100)
18
hw/arm: Set number of MPU regions correctly for an505, an521, an524 (2023-08-31 11:07:02 +0100)
18
19
19
----------------------------------------------------------------
20
----------------------------------------------------------------
20
target-arm queue:
21
target-arm queue:
21
* hw/misc/a9scu: Do not allow invalid CPU count
22
* Some of the preliminary patches for Cortex-A710 support
22
* hw/misc/a9scu: Minor cleanups
23
* i.MX7 and i.MX6UL refactoring
23
* hw/timer/armv7m_systick: assert that board code set system_clock_scale
24
* Implement SRC device for i.MX7
24
* decodetree: Improve identifier matching
25
* Catch illegal-exception-return from EL3 with bad NSE/NS
25
* target/arm: Clean up neon fp insn size field decode
26
* Use 64-bit offsets for holding time_t differences in RTC devices
26
* target/arm: Remove KVM support for 32-bit Arm hosts
27
* Model correct number of MPU regions for an505, an521, an524 boards
27
* hw/arm/mps2: New board models mps2-an386, mps2-an500
28
* Deprecate Unicore32 port
29
* Deprecate lm32 port
30
* target/arm: Count PMU events when MDCR.SPME is set
31
* hw/arm: versal-virt: Correct the tx/rx GEM clocks
32
* New Nuvoton iBMC board models npcm750-evb, quanta-gsj
33
* xlnx-zynqmp: implement ZynqMP CAN controllers
34
28
35
----------------------------------------------------------------
29
----------------------------------------------------------------
36
Aaron Lindsay (1):
30
Alex Bennée (1):
37
target/arm: Count PMU events when MDCR.SPME is set
31
target/arm: properly document FEAT_CRC32
38
32
39
Edgar E. Iglesias (1):
33
Jean-Christophe Dubois (6):
40
hw/arm: versal-virt: Correct the tx/rx GEM clocks
34
Remove i.MX7 IOMUX GPR device from i.MX6UL
35
Refactor i.MX6UL processor code
36
Add i.MX6UL missing devices.
37
Refactor i.MX7 processor code
38
Add i.MX7 missing TZ devices and memory regions
39
Add i.MX7 SRC device implementation
41
40
42
Havard Skinnemoen (14):
41
Peter Maydell (8):
43
hw/misc: Add NPCM7xx System Global Control Registers device model
42
target/arm: Catch illegal-exception-return from EL3 with bad NSE/NS
44
hw/misc: Add NPCM7xx Clock Controller device model
43
hw/rtc/m48t59: Use 64-bit arithmetic in set_alarm()
45
hw/timer: Add NPCM7xx Timer device model
44
hw/rtc/twl92230: Use int64_t for sec_offset and alm_sec
46
hw/arm: Add NPCM730 and NPCM750 SoC models
45
hw/rtc/aspeed_rtc: Use 64-bit offset for holding time_t difference
47
hw/arm: Add two NPCM7xx-based machines
46
rtc: Use time_t for passing and returning time offsets
48
roms: Add virtual Boot ROM for NPCM7xx SoCs
47
target/arm: Do all "ARM_FEATURE_X implies Y" checks in post_init
49
hw/arm: Load -bios image as a boot ROM for npcm7xx
48
hw/arm/armv7m: Add mpu-ns-regions and mpu-s-regions properties
50
hw/nvram: NPCM7xx OTP device model
49
hw/arm: Set number of MPU regions correctly for an505, an521, an524
51
hw/mem: Stubbed out NPCM7xx Memory Controller model
52
hw/ssi: NPCM7xx Flash Interface Unit device model
53
hw/arm: Wire up BMC boot flash for npcm750-evb and quanta-gsj
54
hw/arm/npcm7xx: add board setup stub for CPU and UART clocks
55
docs/system: Add Nuvoton machine documentation
56
tests/acceptance: console boot tests for quanta-gsj
57
50
58
Peter Maydell (11):
51
Richard Henderson (9):
59
hw/timer/armv7m_systick: assert that board code set system_clock_scale
52
target/arm: Reduce dcz_blocksize to uint8_t
60
target/arm: Convert Neon 3-same-fp size field to MO_* in decode
53
target/arm: Allow cpu to configure GM blocksize
61
target/arm: Convert Neon VCVT fp size field to MO_* in decode
54
target/arm: Support more GM blocksizes
62
target/arm: Convert VCMLA, VCADD size field to MO_* in decode
55
target/arm: When tag memory is not present, set MTE=1
63
target/arm: Remove KVM support for 32-bit Arm hosts
56
target/arm: Introduce make_ccsidr64
64
target/arm: Remove no-longer-reachable 32-bit KVM code
57
target/arm: Apply access checks to neoverse-n1 special registers
65
hw/arm/mps2: New board model mps2-an386
58
target/arm: Apply access checks to neoverse-v1 special registers
66
hw/arm/mps2: New board model mps2-an500
59
target/arm: Suppress FEAT_TRBE (Trace Buffer Extension)
67
docs/system/arm/mps2.rst: Make board list consistent
60
target/arm: Implement FEAT_HPDS2 as a no-op
68
Deprecate Unicore32 port
69
Deprecate lm32 port
70
61
71
Philippe Mathieu-Daudé (4):
62
docs/system/arm/emulation.rst | 2 +
72
hw/misc/a9scu: Do not allow invalid CPU count
63
include/hw/arm/armsse.h | 5 +
73
hw/misc/a9scu: Simplify setting MemoryRegionOps::valid fields
64
include/hw/arm/armv7m.h | 8 +
74
hw/misc/a9scu: Simplify setting MemoryRegionOps::impl fields
65
include/hw/arm/fsl-imx6ul.h | 158 ++++++++++++++++---
75
hw/misc/a9scu: Report unimplemented accesses with qemu_log_mask(UNIMP)
66
include/hw/arm/fsl-imx7.h | 338 ++++++++++++++++++++++++++++++-----------
67
include/hw/misc/imx7_src.h | 66 ++++++++
68
include/hw/rtc/aspeed_rtc.h | 2 +-
69
include/sysemu/rtc.h | 4 +-
70
target/arm/cpregs.h | 2 +
71
target/arm/cpu.h | 5 +-
72
target/arm/internals.h | 6 -
73
target/arm/tcg/translate.h | 2 +
74
hw/arm/armsse.c | 16 ++
75
hw/arm/armv7m.c | 21 +++
76
hw/arm/fsl-imx6ul.c | 174 +++++++++++++--------
77
hw/arm/fsl-imx7.c | 201 +++++++++++++++++++-----
78
hw/arm/mps2-tz.c | 29 ++++
79
hw/misc/imx7_src.c | 276 +++++++++++++++++++++++++++++++++
80
hw/rtc/aspeed_rtc.c | 5 +-
81
hw/rtc/m48t59.c | 2 +-
82
hw/rtc/twl92230.c | 4 +-
83
softmmu/rtc.c | 4 +-
84
target/arm/cpu.c | 207 ++++++++++++++-----------
85
target/arm/helper.c | 15 +-
86
target/arm/tcg/cpu32.c | 2 +-
87
target/arm/tcg/cpu64.c | 102 +++++++++----
88
target/arm/tcg/helper-a64.c | 9 ++
89
target/arm/tcg/mte_helper.c | 90 ++++++++---
90
target/arm/tcg/translate-a64.c | 5 +-
91
hw/misc/meson.build | 1 +
92
hw/misc/trace-events | 4 +
93
31 files changed, 1393 insertions(+), 372 deletions(-)
94
create mode 100644 include/hw/misc/imx7_src.h
95
create mode 100644 hw/misc/imx7_src.c
76
96
77
Richard Henderson (1):
78
decodetree: Improve identifier matching
79
80
Vikram Garhwal (4):
81
hw/net/can: Introduce Xilinx ZynqMP CAN controller
82
xlnx-zynqmp: Connect Xilinx ZynqMP CAN controllers
83
tests/qtest: Introduce tests for Xilinx ZynqMP CAN controller
84
MAINTAINERS: Add maintainer entry for Xilinx ZynqMP CAN controller
85
86
docs/system/arm/mps2.rst | 20 +-
87
docs/system/arm/nuvoton.rst | 92 +++
88
docs/system/deprecated.rst | 32 +-
89
docs/system/target-arm.rst | 1 +
90
configure | 2 +-
91
default-configs/arm-softmmu.mak | 1 +
92
include/hw/arm/npcm7xx.h | 112 +++
93
include/hw/arm/xlnx-zynqmp.h | 8 +
94
include/hw/mem/npcm7xx_mc.h | 36 +
95
include/hw/misc/npcm7xx_clk.h | 48 ++
96
include/hw/misc/npcm7xx_gcr.h | 43 ++
97
include/hw/net/xlnx-zynqmp-can.h | 78 +++
98
include/hw/nvram/npcm7xx_otp.h | 79 +++
99
include/hw/ssi/npcm7xx_fiu.h | 73 ++
100
include/hw/timer/npcm7xx_timer.h | 78 +++
101
target/arm/kvm-consts.h | 7 -
102
target/arm/kvm_arm.h | 6 -
103
target/arm/neon-dp.decode | 18 +-
104
target/arm/neon-shared.decode | 18 +-
105
tests/decode/succ_ident1.decode | 7 +
106
hw/arm/mps2.c | 97 ++-
107
hw/arm/npcm7xx.c | 532 +++++++++++++++
108
hw/arm/npcm7xx_boards.c | 197 ++++++
109
hw/arm/xlnx-versal-virt.c | 2 +-
110
hw/arm/xlnx-zcu102.c | 20 +
111
hw/arm/xlnx-zynqmp.c | 34 +
112
hw/mem/npcm7xx_mc.c | 84 +++
113
hw/misc/a9scu.c | 59 +-
114
hw/misc/npcm7xx_clk.c | 266 ++++++++
115
hw/misc/npcm7xx_gcr.c | 269 ++++++++
116
hw/net/can/xlnx-zynqmp-can.c | 1165 ++++++++++++++++++++++++++++++++
117
hw/nvram/npcm7xx_otp.c | 440 ++++++++++++
118
hw/ssi/npcm7xx_fiu.c | 572 ++++++++++++++++
119
hw/timer/armv7m_systick.c | 8 +
120
hw/timer/npcm7xx_timer.c | 543 +++++++++++++++
121
target/arm/cpu.c | 101 ++-
122
target/arm/helper.c | 2 +-
123
target/arm/kvm.c | 7 -
124
target/arm/kvm32.c | 595 ----------------
125
tests/qtest/xlnx-can-test.c | 359 ++++++++++
126
.gitmodules | 3 +
127
MAINTAINERS | 18 +
128
hw/arm/Kconfig | 9 +
129
hw/arm/meson.build | 1 +
130
hw/mem/meson.build | 1 +
131
hw/misc/meson.build | 4 +
132
hw/misc/trace-events | 8 +
133
hw/net/can/meson.build | 1 +
134
hw/nvram/meson.build | 1 +
135
hw/ssi/meson.build | 1 +
136
hw/ssi/trace-events | 11 +
137
hw/timer/meson.build | 1 +
138
hw/timer/trace-events | 5 +
139
pc-bios/README | 6 +
140
pc-bios/meson.build | 1 +
141
pc-bios/npcm7xx_bootrom.bin | Bin 0 -> 768 bytes
142
roms/Makefile | 7 +
143
roms/vbootrom | 1 +
144
scripts/decodetree.py | 46 +-
145
target/arm/meson.build | 5 +-
146
target/arm/translate-neon.c.inc | 42 +-
147
tests/acceptance/boot_linux_console.py | 83 +++
148
tests/qtest/meson.build | 1 +
149
63 files changed, 5584 insertions(+), 783 deletions(-)
150
create mode 100644 docs/system/arm/nuvoton.rst
151
create mode 100644 include/hw/arm/npcm7xx.h
152
create mode 100644 include/hw/mem/npcm7xx_mc.h
153
create mode 100644 include/hw/misc/npcm7xx_clk.h
154
create mode 100644 include/hw/misc/npcm7xx_gcr.h
155
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
156
create mode 100644 include/hw/nvram/npcm7xx_otp.h
157
create mode 100644 include/hw/ssi/npcm7xx_fiu.h
158
create mode 100644 include/hw/timer/npcm7xx_timer.h
159
create mode 100644 tests/decode/succ_ident1.decode
160
create mode 100644 hw/arm/npcm7xx.c
161
create mode 100644 hw/arm/npcm7xx_boards.c
162
create mode 100644 hw/mem/npcm7xx_mc.c
163
create mode 100644 hw/misc/npcm7xx_clk.c
164
create mode 100644 hw/misc/npcm7xx_gcr.c
165
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
166
create mode 100644 hw/nvram/npcm7xx_otp.c
167
create mode 100644 hw/ssi/npcm7xx_fiu.c
168
create mode 100644 hw/timer/npcm7xx_timer.c
169
delete mode 100644 target/arm/kvm32.c
170
create mode 100644 tests/qtest/xlnx-can-test.c
171
create mode 100644 pc-bios/npcm7xx_bootrom.bin
172
create mode 160000 roms/vbootrom
173
diff view generated by jsdifflib
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
3
This value is only 4 bits wide.
4
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
4
5
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Message-id: 1597278668-339715-5-git-send-email-fnu.vikram@xilinx.com
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20230811214031.171020-2-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
10
---
9
MAINTAINERS | 8 ++++++++
11
target/arm/cpu.h | 3 ++-
10
1 file changed, 8 insertions(+)
12
1 file changed, 2 insertions(+), 1 deletion(-)
11
13
12
diff --git a/MAINTAINERS b/MAINTAINERS
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/MAINTAINERS
16
--- a/target/arm/cpu.h
15
+++ b/MAINTAINERS
17
+++ b/target/arm/cpu.h
16
@@ -XXX,XX +XXX,XX @@ F: hw/net/opencores_eth.c
18
@@ -XXX,XX +XXX,XX @@ struct ArchCPU {
17
19
bool prop_lpa2;
18
Devices
20
19
-------
21
/* DCZ blocksize, in log_2(words), ie low 4 bits of DCZID_EL0 */
20
+Xilinx CAN
22
- uint32_t dcz_blocksize;
21
+M: Vikram Garhwal <fnu.vikram@xilinx.com>
23
+ uint8_t dcz_blocksize;
22
+M: Francisco Iglesias <francisco.iglesias@xilinx.com>
23
+S: Maintained
24
+F: hw/net/can/xlnx-*
25
+F: include/hw/net/xlnx-*
26
+F: tests/qtest/xlnx-can-test*
27
+
24
+
28
EDU
25
uint64_t rvbar_prop; /* Property/input signals. */
29
M: Jiri Slaby <jslaby@suse.cz>
26
30
S: Maintained
27
/* Configurable aspects of GIC cpu interface (which is part of the CPU) */
31
--
28
--
32
2.20.1
29
2.34.1
33
30
34
31
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This allows these NPCM7xx-based boards to boot from a flash image, e.g.
3
Previously we hard-coded the blocksize with GMID_EL1_BS.
4
one built with OpenBMC. For example like this:
4
But the value we choose for -cpu max does not match the
5
5
value that cortex-a710 uses.
6
IMAGE=${OPENBMC}/build/tmp/deploy/images/gsj/image-bmc
6
7
qemu-system-arm -machine quanta-gsj -nographic \
7
Mirror the way we handle dcz_blocksize.
8
    -drive file=${IMAGE},if=mtd,bus=0,unit=0,format=raw,snapshot=on
8
9
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Cédric Le Goater <clg@kaod.org>
11
Message-id: 20230811214031.171020-3-richard.henderson@linaro.org
12
Tested-by: Cédric Le Goater <clg@kaod.org>
13
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Message-id: 20200911052101.2602693-12-hskinnemoen@google.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
13
---
19
hw/arm/npcm7xx_boards.c | 20 ++++++++++++++++++++
14
target/arm/cpu.h | 2 ++
20
1 file changed, 20 insertions(+)
15
target/arm/internals.h | 6 -----
21
16
target/arm/tcg/translate.h | 2 ++
22
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
17
target/arm/helper.c | 11 +++++---
23
index XXXXXXX..XXXXXXX 100644
18
target/arm/tcg/cpu64.c | 1 +
24
--- a/hw/arm/npcm7xx_boards.c
19
target/arm/tcg/mte_helper.c | 46 ++++++++++++++++++++++------------
25
+++ b/hw/arm/npcm7xx_boards.c
20
target/arm/tcg/translate-a64.c | 5 ++--
26
@@ -XXX,XX +XXX,XX @@
21
7 files changed, 45 insertions(+), 28 deletions(-)
27
#include "hw/arm/npcm7xx.h"
22
28
#include "hw/core/cpu.h"
23
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
29
#include "hw/loader.h"
24
index XXXXXXX..XXXXXXX 100644
30
+#include "hw/qdev-properties.h"
25
--- a/target/arm/cpu.h
31
#include "qapi/error.h"
26
+++ b/target/arm/cpu.h
32
#include "qemu-common.h"
27
@@ -XXX,XX +XXX,XX @@ struct ArchCPU {
33
#include "qemu/units.h"
28
34
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_load_bootrom(MachineState *machine, NPCM7xxState *soc)
29
/* DCZ blocksize, in log_2(words), ie low 4 bits of DCZID_EL0 */
30
uint8_t dcz_blocksize;
31
+ /* GM blocksize, in log_2(words), ie low 4 bits of GMID_EL0 */
32
+ uint8_t gm_blocksize;
33
34
uint64_t rvbar_prop; /* Property/input signals. */
35
36
diff --git a/target/arm/internals.h b/target/arm/internals.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/internals.h
39
+++ b/target/arm/internals.h
40
@@ -XXX,XX +XXX,XX @@ void arm_log_exception(CPUState *cs);
41
42
#endif /* !CONFIG_USER_ONLY */
43
44
-/*
45
- * The log2 of the words in the tag block, for GMID_EL1.BS.
46
- * The is the maximum, 256 bytes, which manipulates 64-bits of tags.
47
- */
48
-#define GMID_EL1_BS 6
49
-
50
/*
51
* SVE predicates are 1/8 the size of SVE vectors, and cannot use
52
* the same simd_desc() encoding due to restrictions on size.
53
diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h
54
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/tcg/translate.h
56
+++ b/target/arm/tcg/translate.h
57
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
58
int8_t btype;
59
/* A copy of cpu->dcz_blocksize. */
60
uint8_t dcz_blocksize;
61
+ /* A copy of cpu->gm_blocksize. */
62
+ uint8_t gm_blocksize;
63
/* True if this page is guarded. */
64
bool guarded_page;
65
/* Bottom two bits of XScale c15_cpar coprocessor access control reg */
66
diff --git a/target/arm/helper.c b/target/arm/helper.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/helper.c
69
+++ b/target/arm/helper.c
70
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo mte_reginfo[] = {
71
.opc0 = 3, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 6,
72
.access = PL1_RW, .accessfn = access_mte,
73
.fieldoffset = offsetof(CPUARMState, cp15.gcr_el1) },
74
- { .name = "GMID_EL1", .state = ARM_CP_STATE_AA64,
75
- .opc0 = 3, .opc1 = 1, .crn = 0, .crm = 0, .opc2 = 4,
76
- .access = PL1_R, .accessfn = access_aa64_tid5,
77
- .type = ARM_CP_CONST, .resetvalue = GMID_EL1_BS },
78
{ .name = "TCO", .state = ARM_CP_STATE_AA64,
79
.opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 7,
80
.type = ARM_CP_NO_RAW,
81
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
82
* then define only a RAZ/WI version of PSTATE.TCO.
83
*/
84
if (cpu_isar_feature(aa64_mte, cpu)) {
85
+ ARMCPRegInfo gmid_reginfo = {
86
+ .name = "GMID_EL1", .state = ARM_CP_STATE_AA64,
87
+ .opc0 = 3, .opc1 = 1, .crn = 0, .crm = 0, .opc2 = 4,
88
+ .access = PL1_R, .accessfn = access_aa64_tid5,
89
+ .type = ARM_CP_CONST, .resetvalue = cpu->gm_blocksize,
90
+ };
91
+ define_one_arm_cp_reg(cpu, &gmid_reginfo);
92
define_arm_cp_regs(cpu, mte_reginfo);
93
define_arm_cp_regs(cpu, mte_el0_cacheop_reginfo);
94
} else if (cpu_isar_feature(aa64_mte_insn_reg, cpu)) {
95
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
96
index XXXXXXX..XXXXXXX 100644
97
--- a/target/arm/tcg/cpu64.c
98
+++ b/target/arm/tcg/cpu64.c
99
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
100
cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
101
cpu->dcz_blocksize = 7; /* 512 bytes */
102
#endif
103
+ cpu->gm_blocksize = 6; /* 256 bytes */
104
105
cpu->sve_vq.supported = MAKE_64BIT_MASK(0, ARM_MAX_VQ);
106
cpu->sme_vq.supported = SVE_VQ_POW2_MAP;
107
diff --git a/target/arm/tcg/mte_helper.c b/target/arm/tcg/mte_helper.c
108
index XXXXXXX..XXXXXXX 100644
109
--- a/target/arm/tcg/mte_helper.c
110
+++ b/target/arm/tcg/mte_helper.c
111
@@ -XXX,XX +XXX,XX @@ void HELPER(st2g_stub)(CPUARMState *env, uint64_t ptr)
35
}
112
}
36
}
113
}
37
114
38
+static void npcm7xx_connect_flash(NPCM7xxFIUState *fiu, int cs_no,
115
-#define LDGM_STGM_SIZE (4 << GMID_EL1_BS)
39
+ const char *flash_type, DriveInfo *dinfo)
116
-
40
+{
117
uint64_t HELPER(ldgm)(CPUARMState *env, uint64_t ptr)
41
+ DeviceState *flash;
118
{
42
+ qemu_irq flash_cs;
119
int mmu_idx = cpu_mmu_index(env, false);
43
+
120
uintptr_t ra = GETPC();
44
+ flash = qdev_new(flash_type);
121
+ int gm_bs = env_archcpu(env)->gm_blocksize;
45
+ if (dinfo) {
122
+ int gm_bs_bytes = 4 << gm_bs;
46
+ qdev_prop_set_drive(flash, "drive", blk_by_legacy_dinfo(dinfo));
123
void *tag_mem;
124
125
- ptr = QEMU_ALIGN_DOWN(ptr, LDGM_STGM_SIZE);
126
+ ptr = QEMU_ALIGN_DOWN(ptr, gm_bs_bytes);
127
128
/* Trap if accessing an invalid page. */
129
tag_mem = allocation_tag_mem(env, mmu_idx, ptr, MMU_DATA_LOAD,
130
- LDGM_STGM_SIZE, MMU_DATA_LOAD,
131
- LDGM_STGM_SIZE / (2 * TAG_GRANULE), ra);
132
+ gm_bs_bytes, MMU_DATA_LOAD,
133
+ gm_bs_bytes / (2 * TAG_GRANULE), ra);
134
135
/* The tag is squashed to zero if the page does not support tags. */
136
if (!tag_mem) {
137
return 0;
138
}
139
140
- QEMU_BUILD_BUG_ON(GMID_EL1_BS != 6);
141
/*
142
- * We are loading 64-bits worth of tags. The ordering of elements
143
- * within the word corresponds to a 64-bit little-endian operation.
144
+ * The ordering of elements within the word corresponds to
145
+ * a little-endian operation.
146
*/
147
- return ldq_le_p(tag_mem);
148
+ switch (gm_bs) {
149
+ case 6:
150
+ /* 256 bytes -> 16 tags -> 64 result bits */
151
+ return ldq_le_p(tag_mem);
152
+ default:
153
+ /* cpu configured with unsupported gm blocksize. */
154
+ g_assert_not_reached();
47
+ }
155
+ }
48
+ qdev_realize_and_unref(flash, BUS(fiu->spi), &error_fatal);
156
}
49
+
157
50
+ flash_cs = qdev_get_gpio_in_named(flash, SSI_GPIO_CS, 0);
158
void HELPER(stgm)(CPUARMState *env, uint64_t ptr, uint64_t val)
51
+ qdev_connect_gpio_out_named(DEVICE(fiu), "cs", cs_no, flash_cs);
52
+}
53
+
54
static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
55
{
159
{
56
memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, dram);
160
int mmu_idx = cpu_mmu_index(env, false);
57
@@ -XXX,XX +XXX,XX @@ static void npcm750_evb_init(MachineState *machine)
161
uintptr_t ra = GETPC();
58
qdev_realize(DEVICE(soc), NULL, &error_fatal);
162
+ int gm_bs = env_archcpu(env)->gm_blocksize;
59
163
+ int gm_bs_bytes = 4 << gm_bs;
60
npcm7xx_load_bootrom(machine, soc);
164
void *tag_mem;
61
+ npcm7xx_connect_flash(&soc->fiu[0], 0, "w25q256", drive_get(IF_MTD, 0, 0));
165
62
npcm7xx_load_kernel(machine, soc);
166
- ptr = QEMU_ALIGN_DOWN(ptr, LDGM_STGM_SIZE);
167
+ ptr = QEMU_ALIGN_DOWN(ptr, gm_bs_bytes);
168
169
/* Trap if accessing an invalid page. */
170
tag_mem = allocation_tag_mem(env, mmu_idx, ptr, MMU_DATA_STORE,
171
- LDGM_STGM_SIZE, MMU_DATA_LOAD,
172
- LDGM_STGM_SIZE / (2 * TAG_GRANULE), ra);
173
+ gm_bs_bytes, MMU_DATA_LOAD,
174
+ gm_bs_bytes / (2 * TAG_GRANULE), ra);
175
176
/*
177
* Tag store only happens if the page support tags,
178
@@ -XXX,XX +XXX,XX @@ void HELPER(stgm)(CPUARMState *env, uint64_t ptr, uint64_t val)
179
return;
180
}
181
182
- QEMU_BUILD_BUG_ON(GMID_EL1_BS != 6);
183
/*
184
- * We are storing 64-bits worth of tags. The ordering of elements
185
- * within the word corresponds to a 64-bit little-endian operation.
186
+ * The ordering of elements within the word corresponds to
187
+ * a little-endian operation.
188
*/
189
- stq_le_p(tag_mem, val);
190
+ switch (gm_bs) {
191
+ case 6:
192
+ stq_le_p(tag_mem, val);
193
+ break;
194
+ default:
195
+ /* cpu configured with unsupported gm blocksize. */
196
+ g_assert_not_reached();
197
+ }
63
}
198
}
64
199
65
@@ -XXX,XX +XXX,XX @@ static void quanta_gsj_init(MachineState *machine)
200
void HELPER(stzgm_tags)(CPUARMState *env, uint64_t ptr, uint64_t val)
66
qdev_realize(DEVICE(soc), NULL, &error_fatal);
201
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
67
202
index XXXXXXX..XXXXXXX 100644
68
npcm7xx_load_bootrom(machine, soc);
203
--- a/target/arm/tcg/translate-a64.c
69
+ npcm7xx_connect_flash(&soc->fiu[0], 0, "mx25l25635e",
204
+++ b/target/arm/tcg/translate-a64.c
70
+ drive_get(IF_MTD, 0, 0));
205
@@ -XXX,XX +XXX,XX @@ static bool trans_STGM(DisasContext *s, arg_ldst_tag *a)
71
npcm7xx_load_kernel(machine, soc);
206
gen_helper_stgm(cpu_env, addr, tcg_rt);
72
}
207
} else {
73
208
MMUAccessType acc = MMU_DATA_STORE;
209
- int size = 4 << GMID_EL1_BS;
210
+ int size = 4 << s->gm_blocksize;
211
212
clean_addr = clean_data_tbi(s, addr);
213
tcg_gen_andi_i64(clean_addr, clean_addr, -size);
214
@@ -XXX,XX +XXX,XX @@ static bool trans_LDGM(DisasContext *s, arg_ldst_tag *a)
215
gen_helper_ldgm(tcg_rt, cpu_env, addr);
216
} else {
217
MMUAccessType acc = MMU_DATA_LOAD;
218
- int size = 4 << GMID_EL1_BS;
219
+ int size = 4 << s->gm_blocksize;
220
221
clean_addr = clean_data_tbi(s, addr);
222
tcg_gen_andi_i64(clean_addr, clean_addr, -size);
223
@@ -XXX,XX +XXX,XX @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
224
dc->cp_regs = arm_cpu->cp_regs;
225
dc->features = env->features;
226
dc->dcz_blocksize = arm_cpu->dcz_blocksize;
227
+ dc->gm_blocksize = arm_cpu->gm_blocksize;
228
229
#ifdef CONFIG_USER_ONLY
230
/* In sve_probe_page, we assume TBI is enabled. */
74
--
231
--
75
2.20.1
232
2.34.1
76
77
diff view generated by jsdifflib
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The QTests perform five tests on the Xilinx ZynqMP CAN controller:
3
Support all of the easy GM block sizes.
4
Tests the CAN controller in loopback, sleep and snoop mode.
4
Use direct memory operations, since the pointers are aligned.
5
Tests filtering of incoming CAN messages.
6
5
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
6
While BS=2 (16 bytes, 1 tag) is a legal setting, that requires
8
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
7
an atomic store of one nibble. This is not difficult, but there
9
Message-id: 1597278668-339715-4-git-send-email-fnu.vikram@xilinx.com
8
is also no point in supporting it until required.
10
[PMM: updated to meson build system]
9
10
Note that cortex-a710 sets GM blocksize to match its cacheline
11
size of 64 bytes. I expect many implementations will also
12
match the cacheline, which makes 16 bytes very unlikely.
13
14
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Message-id: 20230811214031.171020-4-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
18
---
13
tests/qtest/xlnx-can-test.c | 359 ++++++++++++++++++++++++++++++++++++
19
target/arm/cpu.c | 18 +++++++++---
14
tests/qtest/meson.build | 1 +
20
target/arm/tcg/mte_helper.c | 56 +++++++++++++++++++++++++++++++------
15
2 files changed, 360 insertions(+)
21
2 files changed, 62 insertions(+), 12 deletions(-)
16
create mode 100644 tests/qtest/xlnx-can-test.c
17
22
18
diff --git a/tests/qtest/xlnx-can-test.c b/tests/qtest/xlnx-can-test.c
23
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
19
new file mode 100644
24
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX
25
--- a/target/arm/cpu.c
21
--- /dev/null
26
+++ b/target/arm/cpu.c
22
+++ b/tests/qtest/xlnx-can-test.c
27
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
23
@@ -XXX,XX +XXX,XX @@
28
ID_PFR1, VIRTUALIZATION, 0);
24
+/*
29
}
25
+ * QTests for the Xilinx ZynqMP CAN controller.
30
26
+ *
31
+ if (cpu_isar_feature(aa64_mte, cpu)) {
27
+ * Copyright (c) 2020 Xilinx Inc.
32
+ /*
28
+ *
33
+ * The architectural range of GM blocksize is 2-6, however qemu
29
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
34
+ * doesn't support blocksize of 2 (see HELPER(ldgm)).
30
+ *
35
+ */
31
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
36
+ if (tcg_enabled()) {
32
+ * of this software and associated documentation files (the "Software"), to deal
37
+ assert(cpu->gm_blocksize >= 3 && cpu->gm_blocksize <= 6);
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
+ */
49
+
50
+#include "qemu/osdep.h"
51
+#include "libqos/libqtest.h"
52
+
53
+/* Base address. */
54
+#define CAN0_BASE_ADDR 0xFF060000
55
+#define CAN1_BASE_ADDR 0xFF070000
56
+
57
+/* Register addresses. */
58
+#define R_SRR_OFFSET 0x00
59
+#define R_MSR_OFFSET 0x04
60
+#define R_SR_OFFSET 0x18
61
+#define R_ISR_OFFSET 0x1C
62
+#define R_ICR_OFFSET 0x24
63
+#define R_TXID_OFFSET 0x30
64
+#define R_TXDLC_OFFSET 0x34
65
+#define R_TXDATA1_OFFSET 0x38
66
+#define R_TXDATA2_OFFSET 0x3C
67
+#define R_RXID_OFFSET 0x50
68
+#define R_RXDLC_OFFSET 0x54
69
+#define R_RXDATA1_OFFSET 0x58
70
+#define R_RXDATA2_OFFSET 0x5C
71
+#define R_AFR 0x60
72
+#define R_AFMR1 0x64
73
+#define R_AFIR1 0x68
74
+#define R_AFMR2 0x6C
75
+#define R_AFIR2 0x70
76
+#define R_AFMR3 0x74
77
+#define R_AFIR3 0x78
78
+#define R_AFMR4 0x7C
79
+#define R_AFIR4 0x80
80
+
81
+/* CAN modes. */
82
+#define CONFIG_MODE 0x00
83
+#define NORMAL_MODE 0x00
84
+#define LOOPBACK_MODE 0x02
85
+#define SNOOP_MODE 0x04
86
+#define SLEEP_MODE 0x01
87
+#define ENABLE_CAN (1 << 1)
88
+#define STATUS_NORMAL_MODE (1 << 3)
89
+#define STATUS_LOOPBACK_MODE (1 << 1)
90
+#define STATUS_SNOOP_MODE (1 << 12)
91
+#define STATUS_SLEEP_MODE (1 << 2)
92
+#define ISR_TXOK (1 << 1)
93
+#define ISR_RXOK (1 << 4)
94
+
95
+static void match_rx_tx_data(uint32_t *buf_tx, uint32_t *buf_rx,
96
+ uint8_t can_timestamp)
97
+{
98
+ uint16_t size = 0;
99
+ uint8_t len = 4;
100
+
101
+ while (size < len) {
102
+ if (R_RXID_OFFSET + 4 * size == R_RXDLC_OFFSET) {
103
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size] + can_timestamp);
104
+ } else {
105
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size]);
106
+ }
38
+ }
107
+
39
+
108
+ size++;
40
#ifndef CONFIG_USER_ONLY
41
- if (cpu->tag_memory == NULL && cpu_isar_feature(aa64_mte, cpu)) {
42
/*
43
* Disable the MTE feature bits if we do not have tag-memory
44
* provided by the machine.
45
*/
46
- cpu->isar.id_aa64pfr1 =
47
- FIELD_DP64(cpu->isar.id_aa64pfr1, ID_AA64PFR1, MTE, 0);
48
- }
49
+ if (cpu->tag_memory == NULL) {
50
+ cpu->isar.id_aa64pfr1 =
51
+ FIELD_DP64(cpu->isar.id_aa64pfr1, ID_AA64PFR1, MTE, 0);
52
+ }
53
#endif
109
+ }
54
+ }
110
+}
55
111
+
56
if (tcg_enabled()) {
112
+static void read_data(QTestState *qts, uint64_t can_base_addr, uint32_t *buf_rx)
57
/*
113
+{
58
diff --git a/target/arm/tcg/mte_helper.c b/target/arm/tcg/mte_helper.c
114
+ uint32_t int_status;
115
+
116
+ /* Read the interrupt on CAN rx. */
117
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_RXOK;
118
+
119
+ g_assert_cmpint(int_status, ==, ISR_RXOK);
120
+
121
+ /* Read the RX register data for CAN. */
122
+ buf_rx[0] = qtest_readl(qts, can_base_addr + R_RXID_OFFSET);
123
+ buf_rx[1] = qtest_readl(qts, can_base_addr + R_RXDLC_OFFSET);
124
+ buf_rx[2] = qtest_readl(qts, can_base_addr + R_RXDATA1_OFFSET);
125
+ buf_rx[3] = qtest_readl(qts, can_base_addr + R_RXDATA2_OFFSET);
126
+
127
+ /* Clear the RX interrupt. */
128
+ qtest_writel(qts, CAN1_BASE_ADDR + R_ICR_OFFSET, ISR_RXOK);
129
+}
130
+
131
+static void send_data(QTestState *qts, uint64_t can_base_addr, uint32_t *buf_tx)
132
+{
133
+ uint32_t int_status;
134
+
135
+ /* Write the TX register data for CAN. */
136
+ qtest_writel(qts, can_base_addr + R_TXID_OFFSET, buf_tx[0]);
137
+ qtest_writel(qts, can_base_addr + R_TXDLC_OFFSET, buf_tx[1]);
138
+ qtest_writel(qts, can_base_addr + R_TXDATA1_OFFSET, buf_tx[2]);
139
+ qtest_writel(qts, can_base_addr + R_TXDATA2_OFFSET, buf_tx[3]);
140
+
141
+ /* Read the interrupt on CAN for tx. */
142
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_TXOK;
143
+
144
+ g_assert_cmpint(int_status, ==, ISR_TXOK);
145
+
146
+ /* Clear the interrupt for tx. */
147
+ qtest_writel(qts, CAN0_BASE_ADDR + R_ICR_OFFSET, ISR_TXOK);
148
+}
149
+
150
+/*
151
+ * This test will be transferring data from CAN0 and CAN1 through canbus. CAN0
152
+ * initiate the data transfer to can-bus, CAN1 receives the data. Test compares
153
+ * the data sent from CAN0 with received on CAN1.
154
+ */
155
+static void test_can_bus(void)
156
+{
157
+ uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
158
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
159
+ uint32_t status = 0;
160
+ uint8_t can_timestamp = 1;
161
+
162
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
163
+ " -object can-bus,id=canbus0"
164
+ " -machine xlnx-zcu102.canbus0=canbus0"
165
+ " -machine xlnx-zcu102.canbus1=canbus0"
166
+ );
167
+
168
+ /* Configure the CAN0 and CAN1. */
169
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
170
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
171
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
172
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
173
+
174
+ /* Check here if CAN0 and CAN1 are in normal mode. */
175
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
176
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
177
+
178
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
179
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
180
+
181
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
182
+
183
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
184
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
185
+
186
+ qtest_quit(qts);
187
+}
188
+
189
+/*
190
+ * This test is performing loopback mode on CAN0 and CAN1. Data sent from TX of
191
+ * each CAN0 and CAN1 are compared with RX register data for respective CAN.
192
+ */
193
+static void test_can_loopback(void)
194
+{
195
+ uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
196
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
197
+ uint32_t status = 0;
198
+
199
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
200
+ " -object can-bus,id=canbus0"
201
+ " -machine xlnx-zcu102.canbus0=canbus0"
202
+ " -machine xlnx-zcu102.canbus1=canbus0"
203
+ );
204
+
205
+ /* Configure the CAN0 in loopback mode. */
206
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
207
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
208
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
209
+
210
+ /* Check here if CAN0 is set in loopback mode. */
211
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
212
+
213
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
214
+
215
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
216
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
217
+ match_rx_tx_data(buf_tx, buf_rx, 0);
218
+
219
+ /* Configure the CAN1 in loopback mode. */
220
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
221
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
222
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
223
+
224
+ /* Check here if CAN1 is set in loopback mode. */
225
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
226
+
227
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
228
+
229
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
230
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
231
+ match_rx_tx_data(buf_tx, buf_rx, 0);
232
+
233
+ qtest_quit(qts);
234
+}
235
+
236
+/*
237
+ * Enable filters for CAN1. This will filter incoming messages with ID. In this
238
+ * test message will pass through filter 2.
239
+ */
240
+static void test_can_filter(void)
241
+{
242
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
243
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
244
+ uint32_t status = 0;
245
+ uint8_t can_timestamp = 1;
246
+
247
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
248
+ " -object can-bus,id=canbus0"
249
+ " -machine xlnx-zcu102.canbus0=canbus0"
250
+ " -machine xlnx-zcu102.canbus1=canbus0"
251
+ );
252
+
253
+ /* Configure the CAN0 and CAN1. */
254
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
255
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
256
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
257
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
258
+
259
+ /* Check here if CAN0 and CAN1 are in normal mode. */
260
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
261
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
262
+
263
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
264
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
265
+
266
+ /* Set filter for CAN1 for incoming messages. */
267
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0x0);
268
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR1, 0xF7);
269
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR1, 0x121F);
270
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR2, 0x5431);
271
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR2, 0x14);
272
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR3, 0x1234);
273
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR3, 0x5431);
274
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR4, 0xFFF);
275
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR4, 0x1234);
276
+
277
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0xF);
278
+
279
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
280
+
281
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
282
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
283
+
284
+ qtest_quit(qts);
285
+}
286
+
287
+/* Testing sleep mode on CAN0 while CAN1 is in normal mode. */
288
+static void test_can_sleepmode(void)
289
+{
290
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
291
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
292
+ uint32_t status = 0;
293
+ uint8_t can_timestamp = 1;
294
+
295
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
296
+ " -object can-bus,id=canbus0"
297
+ " -machine xlnx-zcu102.canbus0=canbus0"
298
+ " -machine xlnx-zcu102.canbus1=canbus0"
299
+ );
300
+
301
+ /* Configure the CAN0. */
302
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
303
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SLEEP_MODE);
304
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
305
+
306
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
307
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
308
+
309
+ /* Check here if CAN0 is in SLEEP mode and CAN1 in normal mode. */
310
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
311
+ g_assert_cmpint(status, ==, STATUS_SLEEP_MODE);
312
+
313
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
314
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
315
+
316
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
317
+
318
+ /*
319
+ * Once CAN1 sends data on can-bus. CAN0 should exit sleep mode.
320
+ * Check the CAN0 status now. It should exit the sleep mode and receive the
321
+ * incoming data.
322
+ */
323
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
324
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
325
+
326
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
327
+
328
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
329
+
330
+ qtest_quit(qts);
331
+}
332
+
333
+/* Testing Snoop mode on CAN0 while CAN1 is in normal mode. */
334
+static void test_can_snoopmode(void)
335
+{
336
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
337
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
338
+ uint32_t status = 0;
339
+ uint8_t can_timestamp = 1;
340
+
341
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
342
+ " -object can-bus,id=canbus0"
343
+ " -machine xlnx-zcu102.canbus0=canbus0"
344
+ " -machine xlnx-zcu102.canbus1=canbus0"
345
+ );
346
+
347
+ /* Configure the CAN0. */
348
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
349
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SNOOP_MODE);
350
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
351
+
352
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
353
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
354
+
355
+ /* Check here if CAN0 is in SNOOP mode and CAN1 in normal mode. */
356
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
357
+ g_assert_cmpint(status, ==, STATUS_SNOOP_MODE);
358
+
359
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
360
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
361
+
362
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
363
+
364
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
365
+
366
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
367
+
368
+ qtest_quit(qts);
369
+}
370
+
371
+int main(int argc, char **argv)
372
+{
373
+ g_test_init(&argc, &argv, NULL);
374
+
375
+ qtest_add_func("/net/can/can_bus", test_can_bus);
376
+ qtest_add_func("/net/can/can_loopback", test_can_loopback);
377
+ qtest_add_func("/net/can/can_filter", test_can_filter);
378
+ qtest_add_func("/net/can/can_test_snoopmode", test_can_snoopmode);
379
+ qtest_add_func("/net/can/can_test_sleepmode", test_can_sleepmode);
380
+
381
+ return g_test_run();
382
+}
383
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
384
index XXXXXXX..XXXXXXX 100644
59
index XXXXXXX..XXXXXXX 100644
385
--- a/tests/qtest/meson.build
60
--- a/target/arm/tcg/mte_helper.c
386
+++ b/tests/qtest/meson.build
61
+++ b/target/arm/tcg/mte_helper.c
387
@@ -XXX,XX +XXX,XX @@ qtests_aarch64 = \
62
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(ldgm)(CPUARMState *env, uint64_t ptr)
388
(config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ? ['tpm-tis-device-swtpm-test'] : []) + \
63
int gm_bs = env_archcpu(env)->gm_blocksize;
389
['numa-test',
64
int gm_bs_bytes = 4 << gm_bs;
390
'boot-serial-test',
65
void *tag_mem;
391
+ 'xlnx-can-test',
66
+ uint64_t ret;
392
'migration-test']
67
+ int shift;
393
68
394
qtests_s390x = \
69
ptr = QEMU_ALIGN_DOWN(ptr, gm_bs_bytes);
70
71
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(ldgm)(CPUARMState *env, uint64_t ptr)
72
73
/*
74
* The ordering of elements within the word corresponds to
75
- * a little-endian operation.
76
+ * a little-endian operation. Computation of shift comes from
77
+ *
78
+ * index = address<LOG2_TAG_GRANULE+3:LOG2_TAG_GRANULE>
79
+ * data<index*4+3:index*4> = tag
80
+ *
81
+ * Because of the alignment of ptr above, BS=6 has shift=0.
82
+ * All memory operations are aligned. Defer support for BS=2,
83
+ * requiring insertion or extraction of a nibble, until we
84
+ * support a cpu that requires it.
85
*/
86
switch (gm_bs) {
87
+ case 3:
88
+ /* 32 bytes -> 2 tags -> 8 result bits */
89
+ ret = *(uint8_t *)tag_mem;
90
+ break;
91
+ case 4:
92
+ /* 64 bytes -> 4 tags -> 16 result bits */
93
+ ret = cpu_to_le16(*(uint16_t *)tag_mem);
94
+ break;
95
+ case 5:
96
+ /* 128 bytes -> 8 tags -> 32 result bits */
97
+ ret = cpu_to_le32(*(uint32_t *)tag_mem);
98
+ break;
99
case 6:
100
/* 256 bytes -> 16 tags -> 64 result bits */
101
- return ldq_le_p(tag_mem);
102
+ return cpu_to_le64(*(uint64_t *)tag_mem);
103
default:
104
- /* cpu configured with unsupported gm blocksize. */
105
+ /*
106
+ * CPU configured with unsupported/invalid gm blocksize.
107
+ * This is detected early in arm_cpu_realizefn.
108
+ */
109
g_assert_not_reached();
110
}
111
+ shift = extract64(ptr, LOG2_TAG_GRANULE, 4) * 4;
112
+ return ret << shift;
113
}
114
115
void HELPER(stgm)(CPUARMState *env, uint64_t ptr, uint64_t val)
116
@@ -XXX,XX +XXX,XX @@ void HELPER(stgm)(CPUARMState *env, uint64_t ptr, uint64_t val)
117
int gm_bs = env_archcpu(env)->gm_blocksize;
118
int gm_bs_bytes = 4 << gm_bs;
119
void *tag_mem;
120
+ int shift;
121
122
ptr = QEMU_ALIGN_DOWN(ptr, gm_bs_bytes);
123
124
@@ -XXX,XX +XXX,XX @@ void HELPER(stgm)(CPUARMState *env, uint64_t ptr, uint64_t val)
125
return;
126
}
127
128
- /*
129
- * The ordering of elements within the word corresponds to
130
- * a little-endian operation.
131
- */
132
+ /* See LDGM for comments on BS and on shift. */
133
+ shift = extract64(ptr, LOG2_TAG_GRANULE, 4) * 4;
134
+ val >>= shift;
135
switch (gm_bs) {
136
+ case 3:
137
+ /* 32 bytes -> 2 tags -> 8 result bits */
138
+ *(uint8_t *)tag_mem = val;
139
+ break;
140
+ case 4:
141
+ /* 64 bytes -> 4 tags -> 16 result bits */
142
+ *(uint16_t *)tag_mem = cpu_to_le16(val);
143
+ break;
144
+ case 5:
145
+ /* 128 bytes -> 8 tags -> 32 result bits */
146
+ *(uint32_t *)tag_mem = cpu_to_le32(val);
147
+ break;
148
case 6:
149
- stq_le_p(tag_mem, val);
150
+ /* 256 bytes -> 16 tags -> 64 result bits */
151
+ *(uint64_t *)tag_mem = cpu_to_le64(val);
152
break;
153
default:
154
/* cpu configured with unsupported gm blocksize. */
395
--
155
--
396
2.20.1
156
2.34.1
397
398
diff view generated by jsdifflib
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The Xilinx ZynqMP CAN controller is developed based on SocketCAN, QEMU CAN bus
3
When the cpu support MTE, but the system does not, reduce cpu
4
implementation. Bus connection and socketCAN connection for each CAN module
4
support to user instructions at EL0 instead of completely
5
can be set through command lines.
5
disabling MTE. If we encounter a cpu implementation which does
6
something else, we can revisit this setting.
6
7
7
Example for using single CAN:
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
-object can-bus,id=canbus0 \
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
-machine xlnx-zcu102.canbus0=canbus0 \
10
Message-id: 20230811214031.171020-5-richard.henderson@linaro.org
10
-object can-host-socketcan,id=socketcan0,if=vcan0,canbus=canbus0
11
12
Example for connecting both CAN to same virtual CAN on host machine:
13
-object can-bus,id=canbus0 -object can-bus,id=canbus1 \
14
-machine xlnx-zcu102.canbus0=canbus0 \
15
-machine xlnx-zcu102.canbus1=canbus1 \
16
-object can-host-socketcan,id=socketcan0,if=vcan0,canbus=canbus0 \
17
-object can-host-socketcan,id=socketcan1,if=vcan0,canbus=canbus1
18
19
To create virtual CAN on the host machine, please check the QEMU CAN docs:
20
https://github.com/qemu/qemu/blob/master/docs/can.txt
21
22
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
23
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
24
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
25
Message-id: 1597278668-339715-2-git-send-email-fnu.vikram@xilinx.com
26
[PMM: updated to meson build system]
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
---
12
---
29
include/hw/net/xlnx-zynqmp-can.h | 78 ++
13
target/arm/cpu.c | 7 ++++---
30
hw/net/can/xlnx-zynqmp-can.c | 1165 ++++++++++++++++++++++++++++++
14
1 file changed, 4 insertions(+), 3 deletions(-)
31
hw/net/can/meson.build | 1 +
32
3 files changed, 1244 insertions(+)
33
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
34
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
35
15
36
diff --git a/include/hw/net/xlnx-zynqmp-can.h b/include/hw/net/xlnx-zynqmp-can.h
16
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
37
new file mode 100644
38
index XXXXXXX..XXXXXXX
39
--- /dev/null
40
+++ b/include/hw/net/xlnx-zynqmp-can.h
41
@@ -XXX,XX +XXX,XX @@
42
+/*
43
+ * QEMU model of the Xilinx ZynqMP CAN controller.
44
+ *
45
+ * Copyright (c) 2020 Xilinx Inc.
46
+ *
47
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
48
+ *
49
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
50
+ * Pavel Pisa.
51
+ *
52
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
53
+ * of this software and associated documentation files (the "Software"), to deal
54
+ * in the Software without restriction, including without limitation the rights
55
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
56
+ * copies of the Software, and to permit persons to whom the Software is
57
+ * furnished to do so, subject to the following conditions:
58
+ *
59
+ * The above copyright notice and this permission notice shall be included in
60
+ * all copies or substantial portions of the Software.
61
+ *
62
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
63
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
64
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
65
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
66
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
67
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
68
+ * THE SOFTWARE.
69
+ */
70
+
71
+#ifndef XLNX_ZYNQMP_CAN_H
72
+#define XLNX_ZYNQMP_CAN_H
73
+
74
+#include "hw/register.h"
75
+#include "net/can_emu.h"
76
+#include "net/can_host.h"
77
+#include "qemu/fifo32.h"
78
+#include "hw/ptimer.h"
79
+#include "hw/qdev-clock.h"
80
+
81
+#define TYPE_XLNX_ZYNQMP_CAN "xlnx.zynqmp-can"
82
+
83
+#define XLNX_ZYNQMP_CAN(obj) \
84
+ OBJECT_CHECK(XlnxZynqMPCANState, (obj), TYPE_XLNX_ZYNQMP_CAN)
85
+
86
+#define MAX_CAN_CTRLS 2
87
+#define XLNX_ZYNQMP_CAN_R_MAX (0x84 / 4)
88
+#define MAILBOX_CAPACITY 64
89
+#define CAN_TIMER_MAX 0XFFFFUL
90
+#define CAN_DEFAULT_CLOCK (24 * 1000 * 1000)
91
+
92
+/* Each CAN_FRAME will have 4 * 32bit size. */
93
+#define CAN_FRAME_SIZE 4
94
+#define RXFIFO_SIZE (MAILBOX_CAPACITY * CAN_FRAME_SIZE)
95
+
96
+typedef struct XlnxZynqMPCANState {
97
+ SysBusDevice parent_obj;
98
+ MemoryRegion iomem;
99
+
100
+ qemu_irq irq;
101
+
102
+ CanBusClientState bus_client;
103
+ CanBusState *canbus;
104
+
105
+ struct {
106
+ uint32_t ext_clk_freq;
107
+ } cfg;
108
+
109
+ RegisterInfo reg_info[XLNX_ZYNQMP_CAN_R_MAX];
110
+ uint32_t regs[XLNX_ZYNQMP_CAN_R_MAX];
111
+
112
+ Fifo32 rx_fifo;
113
+ Fifo32 tx_fifo;
114
+ Fifo32 txhpb_fifo;
115
+
116
+ ptimer_state *can_timer;
117
+} XlnxZynqMPCANState;
118
+
119
+#endif
120
diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
121
new file mode 100644
122
index XXXXXXX..XXXXXXX
123
--- /dev/null
124
+++ b/hw/net/can/xlnx-zynqmp-can.c
125
@@ -XXX,XX +XXX,XX @@
126
+/*
127
+ * QEMU model of the Xilinx ZynqMP CAN controller.
128
+ * This implementation is based on the following datasheet:
129
+ * https://www.xilinx.com/support/documentation/user_guides/ug1085-zynq-ultrascale-trm.pdf
130
+ *
131
+ * Copyright (c) 2020 Xilinx Inc.
132
+ *
133
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
134
+ *
135
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
136
+ * Pavel Pisa
137
+ *
138
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
139
+ * of this software and associated documentation files (the "Software"), to deal
140
+ * in the Software without restriction, including without limitation the rights
141
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
142
+ * copies of the Software, and to permit persons to whom the Software is
143
+ * furnished to do so, subject to the following conditions:
144
+ *
145
+ * The above copyright notice and this permission notice shall be included in
146
+ * all copies or substantial portions of the Software.
147
+ *
148
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
149
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
150
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
151
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
152
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
153
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
154
+ * THE SOFTWARE.
155
+ */
156
+
157
+#include "qemu/osdep.h"
158
+#include "hw/sysbus.h"
159
+#include "hw/register.h"
160
+#include "hw/irq.h"
161
+#include "qapi/error.h"
162
+#include "qemu/bitops.h"
163
+#include "qemu/log.h"
164
+#include "qemu/cutils.h"
165
+#include "sysemu/sysemu.h"
166
+#include "migration/vmstate.h"
167
+#include "hw/qdev-properties.h"
168
+#include "net/can_emu.h"
169
+#include "net/can_host.h"
170
+#include "qemu/event_notifier.h"
171
+#include "qom/object_interfaces.h"
172
+#include "hw/net/xlnx-zynqmp-can.h"
173
+
174
+#ifndef XLNX_ZYNQMP_CAN_ERR_DEBUG
175
+#define XLNX_ZYNQMP_CAN_ERR_DEBUG 0
176
+#endif
177
+
178
+#define DB_PRINT(dev, ...) do { \
179
+ if (XLNX_ZYNQMP_CAN_ERR_DEBUG) { \
180
+ g_autofree char *path = object_get_canonical_path(OBJECT(dev)); \
181
+ qemu_log("%s: %s", path, ## __VA_ARGS__); \
182
+ } \
183
+} while (0)
184
+
185
+#define MAX_DLC 8
186
+#undef ERROR
187
+
188
+REG32(SOFTWARE_RESET_REGISTER, 0x0)
189
+ FIELD(SOFTWARE_RESET_REGISTER, CEN, 1, 1)
190
+ FIELD(SOFTWARE_RESET_REGISTER, SRST, 0, 1)
191
+REG32(MODE_SELECT_REGISTER, 0x4)
192
+ FIELD(MODE_SELECT_REGISTER, SNOOP, 2, 1)
193
+ FIELD(MODE_SELECT_REGISTER, LBACK, 1, 1)
194
+ FIELD(MODE_SELECT_REGISTER, SLEEP, 0, 1)
195
+REG32(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, 0x8)
196
+ FIELD(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, BRP, 0, 8)
197
+REG32(ARBITRATION_PHASE_BIT_TIMING_REGISTER, 0xc)
198
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, SJW, 7, 2)
199
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS2, 4, 3)
200
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS1, 0, 4)
201
+REG32(ERROR_COUNTER_REGISTER, 0x10)
202
+ FIELD(ERROR_COUNTER_REGISTER, REC, 8, 8)
203
+ FIELD(ERROR_COUNTER_REGISTER, TEC, 0, 8)
204
+REG32(ERROR_STATUS_REGISTER, 0x14)
205
+ FIELD(ERROR_STATUS_REGISTER, ACKER, 4, 1)
206
+ FIELD(ERROR_STATUS_REGISTER, BERR, 3, 1)
207
+ FIELD(ERROR_STATUS_REGISTER, STER, 2, 1)
208
+ FIELD(ERROR_STATUS_REGISTER, FMER, 1, 1)
209
+ FIELD(ERROR_STATUS_REGISTER, CRCER, 0, 1)
210
+REG32(STATUS_REGISTER, 0x18)
211
+ FIELD(STATUS_REGISTER, SNOOP, 12, 1)
212
+ FIELD(STATUS_REGISTER, ACFBSY, 11, 1)
213
+ FIELD(STATUS_REGISTER, TXFLL, 10, 1)
214
+ FIELD(STATUS_REGISTER, TXBFLL, 9, 1)
215
+ FIELD(STATUS_REGISTER, ESTAT, 7, 2)
216
+ FIELD(STATUS_REGISTER, ERRWRN, 6, 1)
217
+ FIELD(STATUS_REGISTER, BBSY, 5, 1)
218
+ FIELD(STATUS_REGISTER, BIDLE, 4, 1)
219
+ FIELD(STATUS_REGISTER, NORMAL, 3, 1)
220
+ FIELD(STATUS_REGISTER, SLEEP, 2, 1)
221
+ FIELD(STATUS_REGISTER, LBACK, 1, 1)
222
+ FIELD(STATUS_REGISTER, CONFIG, 0, 1)
223
+REG32(INTERRUPT_STATUS_REGISTER, 0x1c)
224
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFEMP, 14, 1)
225
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFWMEMP, 13, 1)
226
+ FIELD(INTERRUPT_STATUS_REGISTER, RXFWMFLL, 12, 1)
227
+ FIELD(INTERRUPT_STATUS_REGISTER, WKUP, 11, 1)
228
+ FIELD(INTERRUPT_STATUS_REGISTER, SLP, 10, 1)
229
+ FIELD(INTERRUPT_STATUS_REGISTER, BSOFF, 9, 1)
230
+ FIELD(INTERRUPT_STATUS_REGISTER, ERROR, 8, 1)
231
+ FIELD(INTERRUPT_STATUS_REGISTER, RXNEMP, 7, 1)
232
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOFLW, 6, 1)
233
+ FIELD(INTERRUPT_STATUS_REGISTER, RXUFLW, 5, 1)
234
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOK, 4, 1)
235
+ FIELD(INTERRUPT_STATUS_REGISTER, TXBFLL, 3, 1)
236
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFLL, 2, 1)
237
+ FIELD(INTERRUPT_STATUS_REGISTER, TXOK, 1, 1)
238
+ FIELD(INTERRUPT_STATUS_REGISTER, ARBLST, 0, 1)
239
+REG32(INTERRUPT_ENABLE_REGISTER, 0x20)
240
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFEMP, 14, 1)
241
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFWMEMP, 13, 1)
242
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXFWMFLL, 12, 1)
243
+ FIELD(INTERRUPT_ENABLE_REGISTER, EWKUP, 11, 1)
244
+ FIELD(INTERRUPT_ENABLE_REGISTER, ESLP, 10, 1)
245
+ FIELD(INTERRUPT_ENABLE_REGISTER, EBSOFF, 9, 1)
246
+ FIELD(INTERRUPT_ENABLE_REGISTER, EERROR, 8, 1)
247
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXNEMP, 7, 1)
248
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOFLW, 6, 1)
249
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXUFLW, 5, 1)
250
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOK, 4, 1)
251
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXBFLL, 3, 1)
252
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFLL, 2, 1)
253
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXOK, 1, 1)
254
+ FIELD(INTERRUPT_ENABLE_REGISTER, EARBLST, 0, 1)
255
+REG32(INTERRUPT_CLEAR_REGISTER, 0x24)
256
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFEMP, 14, 1)
257
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFWMEMP, 13, 1)
258
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXFWMFLL, 12, 1)
259
+ FIELD(INTERRUPT_CLEAR_REGISTER, CWKUP, 11, 1)
260
+ FIELD(INTERRUPT_CLEAR_REGISTER, CSLP, 10, 1)
261
+ FIELD(INTERRUPT_CLEAR_REGISTER, CBSOFF, 9, 1)
262
+ FIELD(INTERRUPT_CLEAR_REGISTER, CERROR, 8, 1)
263
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXNEMP, 7, 1)
264
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOFLW, 6, 1)
265
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXUFLW, 5, 1)
266
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOK, 4, 1)
267
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXBFLL, 3, 1)
268
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFLL, 2, 1)
269
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXOK, 1, 1)
270
+ FIELD(INTERRUPT_CLEAR_REGISTER, CARBLST, 0, 1)
271
+REG32(TIMESTAMP_REGISTER, 0x28)
272
+ FIELD(TIMESTAMP_REGISTER, CTS, 0, 1)
273
+REG32(WIR, 0x2c)
274
+ FIELD(WIR, EW, 8, 8)
275
+ FIELD(WIR, FW, 0, 8)
276
+REG32(TXFIFO_ID, 0x30)
277
+ FIELD(TXFIFO_ID, IDH, 21, 11)
278
+ FIELD(TXFIFO_ID, SRRRTR, 20, 1)
279
+ FIELD(TXFIFO_ID, IDE, 19, 1)
280
+ FIELD(TXFIFO_ID, IDL, 1, 18)
281
+ FIELD(TXFIFO_ID, RTR, 0, 1)
282
+REG32(TXFIFO_DLC, 0x34)
283
+ FIELD(TXFIFO_DLC, DLC, 28, 4)
284
+REG32(TXFIFO_DATA1, 0x38)
285
+ FIELD(TXFIFO_DATA1, DB0, 24, 8)
286
+ FIELD(TXFIFO_DATA1, DB1, 16, 8)
287
+ FIELD(TXFIFO_DATA1, DB2, 8, 8)
288
+ FIELD(TXFIFO_DATA1, DB3, 0, 8)
289
+REG32(TXFIFO_DATA2, 0x3c)
290
+ FIELD(TXFIFO_DATA2, DB4, 24, 8)
291
+ FIELD(TXFIFO_DATA2, DB5, 16, 8)
292
+ FIELD(TXFIFO_DATA2, DB6, 8, 8)
293
+ FIELD(TXFIFO_DATA2, DB7, 0, 8)
294
+REG32(TXHPB_ID, 0x40)
295
+ FIELD(TXHPB_ID, IDH, 21, 11)
296
+ FIELD(TXHPB_ID, SRRRTR, 20, 1)
297
+ FIELD(TXHPB_ID, IDE, 19, 1)
298
+ FIELD(TXHPB_ID, IDL, 1, 18)
299
+ FIELD(TXHPB_ID, RTR, 0, 1)
300
+REG32(TXHPB_DLC, 0x44)
301
+ FIELD(TXHPB_DLC, DLC, 28, 4)
302
+REG32(TXHPB_DATA1, 0x48)
303
+ FIELD(TXHPB_DATA1, DB0, 24, 8)
304
+ FIELD(TXHPB_DATA1, DB1, 16, 8)
305
+ FIELD(TXHPB_DATA1, DB2, 8, 8)
306
+ FIELD(TXHPB_DATA1, DB3, 0, 8)
307
+REG32(TXHPB_DATA2, 0x4c)
308
+ FIELD(TXHPB_DATA2, DB4, 24, 8)
309
+ FIELD(TXHPB_DATA2, DB5, 16, 8)
310
+ FIELD(TXHPB_DATA2, DB6, 8, 8)
311
+ FIELD(TXHPB_DATA2, DB7, 0, 8)
312
+REG32(RXFIFO_ID, 0x50)
313
+ FIELD(RXFIFO_ID, IDH, 21, 11)
314
+ FIELD(RXFIFO_ID, SRRRTR, 20, 1)
315
+ FIELD(RXFIFO_ID, IDE, 19, 1)
316
+ FIELD(RXFIFO_ID, IDL, 1, 18)
317
+ FIELD(RXFIFO_ID, RTR, 0, 1)
318
+REG32(RXFIFO_DLC, 0x54)
319
+ FIELD(RXFIFO_DLC, DLC, 28, 4)
320
+ FIELD(RXFIFO_DLC, RXT, 0, 16)
321
+REG32(RXFIFO_DATA1, 0x58)
322
+ FIELD(RXFIFO_DATA1, DB0, 24, 8)
323
+ FIELD(RXFIFO_DATA1, DB1, 16, 8)
324
+ FIELD(RXFIFO_DATA1, DB2, 8, 8)
325
+ FIELD(RXFIFO_DATA1, DB3, 0, 8)
326
+REG32(RXFIFO_DATA2, 0x5c)
327
+ FIELD(RXFIFO_DATA2, DB4, 24, 8)
328
+ FIELD(RXFIFO_DATA2, DB5, 16, 8)
329
+ FIELD(RXFIFO_DATA2, DB6, 8, 8)
330
+ FIELD(RXFIFO_DATA2, DB7, 0, 8)
331
+REG32(AFR, 0x60)
332
+ FIELD(AFR, UAF4, 3, 1)
333
+ FIELD(AFR, UAF3, 2, 1)
334
+ FIELD(AFR, UAF2, 1, 1)
335
+ FIELD(AFR, UAF1, 0, 1)
336
+REG32(AFMR1, 0x64)
337
+ FIELD(AFMR1, AMIDH, 21, 11)
338
+ FIELD(AFMR1, AMSRR, 20, 1)
339
+ FIELD(AFMR1, AMIDE, 19, 1)
340
+ FIELD(AFMR1, AMIDL, 1, 18)
341
+ FIELD(AFMR1, AMRTR, 0, 1)
342
+REG32(AFIR1, 0x68)
343
+ FIELD(AFIR1, AIIDH, 21, 11)
344
+ FIELD(AFIR1, AISRR, 20, 1)
345
+ FIELD(AFIR1, AIIDE, 19, 1)
346
+ FIELD(AFIR1, AIIDL, 1, 18)
347
+ FIELD(AFIR1, AIRTR, 0, 1)
348
+REG32(AFMR2, 0x6c)
349
+ FIELD(AFMR2, AMIDH, 21, 11)
350
+ FIELD(AFMR2, AMSRR, 20, 1)
351
+ FIELD(AFMR2, AMIDE, 19, 1)
352
+ FIELD(AFMR2, AMIDL, 1, 18)
353
+ FIELD(AFMR2, AMRTR, 0, 1)
354
+REG32(AFIR2, 0x70)
355
+ FIELD(AFIR2, AIIDH, 21, 11)
356
+ FIELD(AFIR2, AISRR, 20, 1)
357
+ FIELD(AFIR2, AIIDE, 19, 1)
358
+ FIELD(AFIR2, AIIDL, 1, 18)
359
+ FIELD(AFIR2, AIRTR, 0, 1)
360
+REG32(AFMR3, 0x74)
361
+ FIELD(AFMR3, AMIDH, 21, 11)
362
+ FIELD(AFMR3, AMSRR, 20, 1)
363
+ FIELD(AFMR3, AMIDE, 19, 1)
364
+ FIELD(AFMR3, AMIDL, 1, 18)
365
+ FIELD(AFMR3, AMRTR, 0, 1)
366
+REG32(AFIR3, 0x78)
367
+ FIELD(AFIR3, AIIDH, 21, 11)
368
+ FIELD(AFIR3, AISRR, 20, 1)
369
+ FIELD(AFIR3, AIIDE, 19, 1)
370
+ FIELD(AFIR3, AIIDL, 1, 18)
371
+ FIELD(AFIR3, AIRTR, 0, 1)
372
+REG32(AFMR4, 0x7c)
373
+ FIELD(AFMR4, AMIDH, 21, 11)
374
+ FIELD(AFMR4, AMSRR, 20, 1)
375
+ FIELD(AFMR4, AMIDE, 19, 1)
376
+ FIELD(AFMR4, AMIDL, 1, 18)
377
+ FIELD(AFMR4, AMRTR, 0, 1)
378
+REG32(AFIR4, 0x80)
379
+ FIELD(AFIR4, AIIDH, 21, 11)
380
+ FIELD(AFIR4, AISRR, 20, 1)
381
+ FIELD(AFIR4, AIIDE, 19, 1)
382
+ FIELD(AFIR4, AIIDL, 1, 18)
383
+ FIELD(AFIR4, AIRTR, 0, 1)
384
+
385
+static void can_update_irq(XlnxZynqMPCANState *s)
386
+{
387
+ uint32_t irq;
388
+
389
+ /* Watermark register interrupts. */
390
+ if ((fifo32_num_free(&s->tx_fifo) / CAN_FRAME_SIZE) >
391
+ ARRAY_FIELD_EX32(s->regs, WIR, EW)) {
392
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFWMEMP, 1);
393
+ }
394
+
395
+ if ((fifo32_num_used(&s->rx_fifo) / CAN_FRAME_SIZE) >
396
+ ARRAY_FIELD_EX32(s->regs, WIR, FW)) {
397
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFWMFLL, 1);
398
+ }
399
+
400
+ /* RX Interrupts. */
401
+ if (fifo32_num_used(&s->rx_fifo) >= CAN_FRAME_SIZE) {
402
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXNEMP, 1);
403
+ }
404
+
405
+ /* TX interrupts. */
406
+ if (fifo32_is_empty(&s->tx_fifo)) {
407
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFEMP, 1);
408
+ }
409
+
410
+ if (fifo32_is_full(&s->tx_fifo)) {
411
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFLL, 1);
412
+ }
413
+
414
+ if (fifo32_is_full(&s->txhpb_fifo)) {
415
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXBFLL, 1);
416
+ }
417
+
418
+ irq = s->regs[R_INTERRUPT_STATUS_REGISTER];
419
+ irq &= s->regs[R_INTERRUPT_ENABLE_REGISTER];
420
+
421
+ qemu_set_irq(s->irq, irq);
422
+}
423
+
424
+static void can_ier_post_write(RegisterInfo *reg, uint64_t val64)
425
+{
426
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
427
+
428
+ can_update_irq(s);
429
+}
430
+
431
+static uint64_t can_icr_pre_write(RegisterInfo *reg, uint64_t val64)
432
+{
433
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
434
+ uint32_t val = val64;
435
+
436
+ s->regs[R_INTERRUPT_STATUS_REGISTER] &= ~val;
437
+ can_update_irq(s);
438
+
439
+ return 0;
440
+}
441
+
442
+static void can_config_reset(XlnxZynqMPCANState *s)
443
+{
444
+ /* Reset all the configuration registers. */
445
+ register_reset(&s->reg_info[R_SOFTWARE_RESET_REGISTER]);
446
+ register_reset(&s->reg_info[R_MODE_SELECT_REGISTER]);
447
+ register_reset(
448
+ &s->reg_info[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER]);
449
+ register_reset(&s->reg_info[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER]);
450
+ register_reset(&s->reg_info[R_STATUS_REGISTER]);
451
+ register_reset(&s->reg_info[R_INTERRUPT_STATUS_REGISTER]);
452
+ register_reset(&s->reg_info[R_INTERRUPT_ENABLE_REGISTER]);
453
+ register_reset(&s->reg_info[R_INTERRUPT_CLEAR_REGISTER]);
454
+ register_reset(&s->reg_info[R_WIR]);
455
+}
456
+
457
+static void can_config_mode(XlnxZynqMPCANState *s)
458
+{
459
+ register_reset(&s->reg_info[R_ERROR_COUNTER_REGISTER]);
460
+ register_reset(&s->reg_info[R_ERROR_STATUS_REGISTER]);
461
+
462
+ /* Put XlnxZynqMPCAN in configuration mode. */
463
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 1);
464
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP, 0);
465
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP, 0);
466
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, BSOFF, 0);
467
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ERROR, 0);
468
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 0);
469
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 0);
470
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 0);
471
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ARBLST, 0);
472
+
473
+ can_update_irq(s);
474
+}
475
+
476
+static void update_status_register_mode_bits(XlnxZynqMPCANState *s)
477
+{
478
+ bool sleep_status = ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP);
479
+ bool sleep_mode = ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP);
480
+ /* Wake up interrupt bit. */
481
+ bool wakeup_irq_val = sleep_status && (sleep_mode == 0);
482
+ /* Sleep interrupt bit. */
483
+ bool sleep_irq_val = sleep_mode && (sleep_status == 0);
484
+
485
+ /* Clear previous core mode status bits. */
486
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 0);
487
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 0);
488
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 0);
489
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 0);
490
+
491
+ /* set current mode bit and generate irqs accordingly. */
492
+ if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, LBACK)) {
493
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 1);
494
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP)) {
495
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 1);
496
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP,
497
+ sleep_irq_val);
498
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SNOOP)) {
499
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 1);
500
+ } else {
501
+ /*
502
+ * If all bits are zero then XlnxZynqMPCAN is set in normal mode.
503
+ */
504
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 1);
505
+ /* Set wakeup interrupt bit. */
506
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP,
507
+ wakeup_irq_val);
508
+ }
509
+
510
+ can_update_irq(s);
511
+}
512
+
513
+static void can_exit_sleep_mode(XlnxZynqMPCANState *s)
514
+{
515
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, 0);
516
+ update_status_register_mode_bits(s);
517
+}
518
+
519
+static void generate_frame(qemu_can_frame *frame, uint32_t *data)
520
+{
521
+ frame->can_id = data[0];
522
+ frame->can_dlc = FIELD_EX32(data[1], TXFIFO_DLC, DLC);
523
+
524
+ frame->data[0] = FIELD_EX32(data[2], TXFIFO_DATA1, DB3);
525
+ frame->data[1] = FIELD_EX32(data[2], TXFIFO_DATA1, DB2);
526
+ frame->data[2] = FIELD_EX32(data[2], TXFIFO_DATA1, DB1);
527
+ frame->data[3] = FIELD_EX32(data[2], TXFIFO_DATA1, DB0);
528
+
529
+ frame->data[4] = FIELD_EX32(data[3], TXFIFO_DATA2, DB7);
530
+ frame->data[5] = FIELD_EX32(data[3], TXFIFO_DATA2, DB6);
531
+ frame->data[6] = FIELD_EX32(data[3], TXFIFO_DATA2, DB5);
532
+ frame->data[7] = FIELD_EX32(data[3], TXFIFO_DATA2, DB4);
533
+}
534
+
535
+static bool tx_ready_check(XlnxZynqMPCANState *s)
536
+{
537
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
538
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
539
+
540
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer data while"
541
+ " data while controller is in reset mode.\n",
542
+ path);
543
+ return false;
544
+ }
545
+
546
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
547
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
548
+
549
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
550
+ " data while controller is in configuration mode. Reset"
551
+ " the core so operations can start fresh.\n",
552
+ path);
553
+ return false;
554
+ }
555
+
556
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
557
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
558
+
559
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
560
+ " data while controller is in SNOOP MODE.\n",
561
+ path);
562
+ return false;
563
+ }
564
+
565
+ return true;
566
+}
567
+
568
+static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
569
+{
570
+ qemu_can_frame frame;
571
+ uint32_t data[CAN_FRAME_SIZE];
572
+ int i;
573
+ bool can_tx = tx_ready_check(s);
574
+
575
+ if (can_tx) {
576
+ while (!fifo32_is_empty(fifo)) {
577
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
578
+ data[i] = fifo32_pop(fifo);
579
+ }
580
+
581
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
582
+ /*
583
+ * Controller is in loopback. In Loopback mode, the CAN core
584
+ * transmits a recessive bitstream on to the XlnxZynqMPCAN Bus.
585
+ * Any message transmitted is looped back to the RX line and
586
+ * acknowledged. The XlnxZynqMPCAN core receives any message
587
+ * that it transmits.
588
+ */
589
+ if (fifo32_is_full(&s->rx_fifo)) {
590
+ DB_PRINT(s, "Loopback: RX FIFO is full."
591
+ " TX FIFO will be flushed.\n");
592
+
593
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER,
594
+ RXOFLW, 1);
595
+ } else {
596
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
597
+ fifo32_push(&s->rx_fifo, data[i]);
598
+ }
599
+
600
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER,
601
+ RXOK, 1);
602
+ }
603
+ } else {
604
+ /* Normal mode Tx. */
605
+ generate_frame(&frame, data);
606
+
607
+ can_bus_client_send(&s->bus_client, &frame, 1);
608
+ }
609
+ }
610
+
611
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 1);
612
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, TXBFLL, 0);
613
+
614
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) {
615
+ can_exit_sleep_mode(s);
616
+ }
617
+ } else {
618
+ DB_PRINT(s, "Not enabled for data transfer.\n");
619
+ }
620
+
621
+ can_update_irq(s);
622
+}
623
+
624
+static uint64_t can_srr_pre_write(RegisterInfo *reg, uint64_t val64)
625
+{
626
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
627
+ uint32_t val = val64;
628
+
629
+ ARRAY_FIELD_DP32(s->regs, SOFTWARE_RESET_REGISTER, CEN,
630
+ FIELD_EX32(val, SOFTWARE_RESET_REGISTER, CEN));
631
+
632
+ if (FIELD_EX32(val, SOFTWARE_RESET_REGISTER, SRST)) {
633
+ DB_PRINT(s, "Resetting controller.\n");
634
+
635
+ /* First, core will do software reset then will enter in config mode. */
636
+ can_config_reset(s);
637
+ }
638
+
639
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
640
+ can_config_mode(s);
641
+ } else {
642
+ /*
643
+ * Leave config mode. Now XlnxZynqMPCAN core will enter normal,
644
+ * sleep, snoop or loopback mode depending upon LBACK, SLEEP, SNOOP
645
+ * register states.
646
+ */
647
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 0);
648
+
649
+ ptimer_transaction_begin(s->can_timer);
650
+ ptimer_set_count(s->can_timer, 0);
651
+ ptimer_transaction_commit(s->can_timer);
652
+
653
+ /* XlnxZynqMPCAN is out of config mode. It will send pending data. */
654
+ transfer_fifo(s, &s->txhpb_fifo);
655
+ transfer_fifo(s, &s->tx_fifo);
656
+ }
657
+
658
+ update_status_register_mode_bits(s);
659
+
660
+ return s->regs[R_SOFTWARE_RESET_REGISTER];
661
+}
662
+
663
+static uint64_t can_msr_pre_write(RegisterInfo *reg, uint64_t val64)
664
+{
665
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
666
+ uint32_t val = val64;
667
+ uint8_t multi_mode;
668
+
669
+ /*
670
+ * Multiple mode set check. This is done to make sure user doesn't set
671
+ * multiple modes.
672
+ */
673
+ multi_mode = FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK) +
674
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP) +
675
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP);
676
+
677
+ if (multi_mode > 1) {
678
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
679
+
680
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to config"
681
+ " several modes simultaneously. One mode will be selected"
682
+ " according to their priority: LBACK > SLEEP > SNOOP.\n",
683
+ path);
684
+ }
685
+
686
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
687
+ /* We are in configuration mode, any mode can be selected. */
688
+ s->regs[R_MODE_SELECT_REGISTER] = val;
689
+ } else {
690
+ bool sleep_mode_bit = FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP);
691
+
692
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, sleep_mode_bit);
693
+
694
+ if (FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK)) {
695
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
696
+
697
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
698
+ " LBACK mode without setting CEN bit as 0.\n",
699
+ path);
700
+ } else if (FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP)) {
701
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
702
+
703
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
704
+ " SNOOP mode without setting CEN bit as 0.\n",
705
+ path);
706
+ }
707
+
708
+ update_status_register_mode_bits(s);
709
+ }
710
+
711
+ return s->regs[R_MODE_SELECT_REGISTER];
712
+}
713
+
714
+static uint64_t can_brpr_pre_write(RegisterInfo *reg, uint64_t val64)
715
+{
716
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
717
+ uint32_t val = val64;
718
+
719
+ /* Only allow writes when in config mode. */
720
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
721
+ val = s->regs[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER];
722
+ }
723
+
724
+ return val;
725
+}
726
+
727
+static uint64_t can_btr_pre_write(RegisterInfo *reg, uint64_t val64)
728
+{
729
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
730
+ uint32_t val = val64;
731
+
732
+ /* Only allow writes when in config mode. */
733
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
734
+ val = s->regs[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER];
735
+ }
736
+
737
+ return val;
738
+}
739
+
740
+static uint64_t can_tcr_pre_write(RegisterInfo *reg, uint64_t val64)
741
+{
742
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
743
+ uint32_t val = val64;
744
+
745
+ if (FIELD_EX32(val, TIMESTAMP_REGISTER, CTS)) {
746
+ ptimer_transaction_begin(s->can_timer);
747
+ ptimer_set_count(s->can_timer, 0);
748
+ ptimer_transaction_commit(s->can_timer);
749
+ }
750
+
751
+ return 0;
752
+}
753
+
754
+static void update_rx_fifo(XlnxZynqMPCANState *s, const qemu_can_frame *frame)
755
+{
756
+ bool filter_pass = false;
757
+ uint16_t timestamp = 0;
758
+
759
+ /* If no filter is enabled. Message will be stored in FIFO. */
760
+ if (!((ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) |
761
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) |
762
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) |
763
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)))) {
764
+ filter_pass = true;
765
+ }
766
+
767
+ /*
768
+ * Messages that pass any of the acceptance filters will be stored in
769
+ * the RX FIFO.
770
+ */
771
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) {
772
+ uint32_t id_masked = s->regs[R_AFMR1] & frame->can_id;
773
+ uint32_t filter_id_masked = s->regs[R_AFMR1] & s->regs[R_AFIR1];
774
+
775
+ if (filter_id_masked == id_masked) {
776
+ filter_pass = true;
777
+ }
778
+ }
779
+
780
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) {
781
+ uint32_t id_masked = s->regs[R_AFMR2] & frame->can_id;
782
+ uint32_t filter_id_masked = s->regs[R_AFMR2] & s->regs[R_AFIR2];
783
+
784
+ if (filter_id_masked == id_masked) {
785
+ filter_pass = true;
786
+ }
787
+ }
788
+
789
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) {
790
+ uint32_t id_masked = s->regs[R_AFMR3] & frame->can_id;
791
+ uint32_t filter_id_masked = s->regs[R_AFMR3] & s->regs[R_AFIR3];
792
+
793
+ if (filter_id_masked == id_masked) {
794
+ filter_pass = true;
795
+ }
796
+ }
797
+
798
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
799
+ uint32_t id_masked = s->regs[R_AFMR4] & frame->can_id;
800
+ uint32_t filter_id_masked = s->regs[R_AFMR4] & s->regs[R_AFIR4];
801
+
802
+ if (filter_id_masked == id_masked) {
803
+ filter_pass = true;
804
+ }
805
+ }
806
+
807
+ /* Store the message in fifo if it passed through any of the filters. */
808
+ if (filter_pass && frame->can_dlc <= MAX_DLC) {
809
+
810
+ if (fifo32_is_full(&s->rx_fifo)) {
811
+ DB_PRINT(s, "RX FIFO is full.\n");
812
+
813
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1);
814
+ } else {
815
+ timestamp = CAN_TIMER_MAX - ptimer_get_count(s->can_timer);
816
+
817
+ fifo32_push(&s->rx_fifo, frame->can_id);
818
+
819
+ fifo32_push(&s->rx_fifo, deposit32(0, R_RXFIFO_DLC_DLC_SHIFT,
820
+ R_RXFIFO_DLC_DLC_LENGTH,
821
+ frame->can_dlc) |
822
+ deposit32(0, R_RXFIFO_DLC_RXT_SHIFT,
823
+ R_RXFIFO_DLC_RXT_LENGTH,
824
+ timestamp));
825
+
826
+ /* First 32 bit of the data. */
827
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA1_DB3_SHIFT,
828
+ R_TXFIFO_DATA1_DB3_LENGTH,
829
+ frame->data[0]) |
830
+ deposit32(0, R_TXFIFO_DATA1_DB2_SHIFT,
831
+ R_TXFIFO_DATA1_DB2_LENGTH,
832
+ frame->data[1]) |
833
+ deposit32(0, R_TXFIFO_DATA1_DB1_SHIFT,
834
+ R_TXFIFO_DATA1_DB1_LENGTH,
835
+ frame->data[2]) |
836
+ deposit32(0, R_TXFIFO_DATA1_DB0_SHIFT,
837
+ R_TXFIFO_DATA1_DB0_LENGTH,
838
+ frame->data[3]));
839
+ /* Last 32 bit of the data. */
840
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA2_DB7_SHIFT,
841
+ R_TXFIFO_DATA2_DB7_LENGTH,
842
+ frame->data[4]) |
843
+ deposit32(0, R_TXFIFO_DATA2_DB6_SHIFT,
844
+ R_TXFIFO_DATA2_DB6_LENGTH,
845
+ frame->data[5]) |
846
+ deposit32(0, R_TXFIFO_DATA2_DB5_SHIFT,
847
+ R_TXFIFO_DATA2_DB5_LENGTH,
848
+ frame->data[6]) |
849
+ deposit32(0, R_TXFIFO_DATA2_DB4_SHIFT,
850
+ R_TXFIFO_DATA2_DB4_LENGTH,
851
+ frame->data[7]));
852
+
853
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
854
+ }
855
+
856
+ can_update_irq(s);
857
+ } else {
858
+ DB_PRINT(s, "Message didn't pass through any filter or dlc"
859
+ " is not in range.\n");
860
+ }
861
+}
862
+
863
+static uint64_t can_rxfifo_pre_read(RegisterInfo *reg, uint64_t val64)
864
+{
865
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
866
+ uint32_t r = 0;
867
+
868
+ if (!fifo32_is_empty(&s->rx_fifo)) {
869
+ r = fifo32_pop(&s->rx_fifo);
870
+ } else {
871
+ DB_PRINT(s, "No message in RXFIFO.\n");
872
+
873
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXUFLW, 1);
874
+ }
875
+
876
+ can_update_irq(s);
877
+ return r;
878
+}
879
+
880
+static void can_filter_enable_post_write(RegisterInfo *reg, uint64_t val64)
881
+{
882
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
883
+
884
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1) &&
885
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF2) &&
886
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF3) &&
887
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
888
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 1);
889
+ } else {
890
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 0);
891
+ }
892
+}
893
+
894
+static uint64_t can_filter_mask_pre_write(RegisterInfo *reg, uint64_t val64)
895
+{
896
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
897
+ uint32_t reg_idx = (reg->access->addr) / 4;
898
+ uint32_t val = val64;
899
+ uint32_t filter_number = (reg_idx - R_AFMR1) / 2;
900
+
901
+ /* modify an acceptance filter, the corresponding UAF bit should be '0.' */
902
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
903
+ s->regs[reg_idx] = val;
904
+ } else {
905
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
906
+
907
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
908
+ " mask is not set as corresponding UAF bit is not 0.\n",
909
+ path, filter_number + 1);
910
+ }
911
+
912
+ return s->regs[reg_idx];
913
+}
914
+
915
+static uint64_t can_filter_id_pre_write(RegisterInfo *reg, uint64_t val64)
916
+{
917
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
918
+ uint32_t reg_idx = (reg->access->addr) / 4;
919
+ uint32_t val = val64;
920
+ uint32_t filter_number = (reg_idx - R_AFIR1) / 2;
921
+
922
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
923
+ s->regs[reg_idx] = val;
924
+ } else {
925
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
926
+
927
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
928
+ " id is not set as corresponding UAF bit is not 0.\n",
929
+ path, filter_number + 1);
930
+ }
931
+
932
+ return s->regs[reg_idx];
933
+}
934
+
935
+static void can_tx_post_write(RegisterInfo *reg, uint64_t val64)
936
+{
937
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
938
+ uint32_t val = val64;
939
+
940
+ bool is_txhpb = reg->access->addr > A_TXFIFO_DATA2;
941
+
942
+ bool initiate_transfer = (reg->access->addr == A_TXFIFO_DATA2) ||
943
+ (reg->access->addr == A_TXHPB_DATA2);
944
+
945
+ Fifo32 *f = is_txhpb ? &s->txhpb_fifo : &s->tx_fifo;
946
+
947
+ DB_PRINT(s, "TX FIFO write.\n");
948
+
949
+ if (!fifo32_is_full(f)) {
950
+ fifo32_push(f, val);
951
+ } else {
952
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
953
+
954
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: TX FIFO is full.\n", path);
955
+ }
956
+
957
+ /* Initiate the message send if TX register is written. */
958
+ if (initiate_transfer &&
959
+ ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
960
+ transfer_fifo(s, f);
961
+ }
962
+
963
+ can_update_irq(s);
964
+}
965
+
966
+static const RegisterAccessInfo can_regs_info[] = {
967
+ { .name = "SOFTWARE_RESET_REGISTER",
968
+ .addr = A_SOFTWARE_RESET_REGISTER,
969
+ .rsvd = 0xfffffffc,
970
+ .pre_write = can_srr_pre_write,
971
+ },{ .name = "MODE_SELECT_REGISTER",
972
+ .addr = A_MODE_SELECT_REGISTER,
973
+ .rsvd = 0xfffffff8,
974
+ .pre_write = can_msr_pre_write,
975
+ },{ .name = "ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER",
976
+ .addr = A_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER,
977
+ .rsvd = 0xffffff00,
978
+ .pre_write = can_brpr_pre_write,
979
+ },{ .name = "ARBITRATION_PHASE_BIT_TIMING_REGISTER",
980
+ .addr = A_ARBITRATION_PHASE_BIT_TIMING_REGISTER,
981
+ .rsvd = 0xfffffe00,
982
+ .pre_write = can_btr_pre_write,
983
+ },{ .name = "ERROR_COUNTER_REGISTER",
984
+ .addr = A_ERROR_COUNTER_REGISTER,
985
+ .rsvd = 0xffff0000,
986
+ .ro = 0xffffffff,
987
+ },{ .name = "ERROR_STATUS_REGISTER",
988
+ .addr = A_ERROR_STATUS_REGISTER,
989
+ .rsvd = 0xffffffe0,
990
+ .w1c = 0x1f,
991
+ },{ .name = "STATUS_REGISTER", .addr = A_STATUS_REGISTER,
992
+ .reset = 0x1,
993
+ .rsvd = 0xffffe000,
994
+ .ro = 0x1fff,
995
+ },{ .name = "INTERRUPT_STATUS_REGISTER",
996
+ .addr = A_INTERRUPT_STATUS_REGISTER,
997
+ .reset = 0x6000,
998
+ .rsvd = 0xffff8000,
999
+ .ro = 0x7fff,
1000
+ },{ .name = "INTERRUPT_ENABLE_REGISTER",
1001
+ .addr = A_INTERRUPT_ENABLE_REGISTER,
1002
+ .rsvd = 0xffff8000,
1003
+ .post_write = can_ier_post_write,
1004
+ },{ .name = "INTERRUPT_CLEAR_REGISTER",
1005
+ .addr = A_INTERRUPT_CLEAR_REGISTER,
1006
+ .rsvd = 0xffff8000,
1007
+ .pre_write = can_icr_pre_write,
1008
+ },{ .name = "TIMESTAMP_REGISTER",
1009
+ .addr = A_TIMESTAMP_REGISTER,
1010
+ .rsvd = 0xfffffffe,
1011
+ .pre_write = can_tcr_pre_write,
1012
+ },{ .name = "WIR", .addr = A_WIR,
1013
+ .reset = 0x3f3f,
1014
+ .rsvd = 0xffff0000,
1015
+ },{ .name = "TXFIFO_ID", .addr = A_TXFIFO_ID,
1016
+ .post_write = can_tx_post_write,
1017
+ },{ .name = "TXFIFO_DLC", .addr = A_TXFIFO_DLC,
1018
+ .rsvd = 0xfffffff,
1019
+ .post_write = can_tx_post_write,
1020
+ },{ .name = "TXFIFO_DATA1", .addr = A_TXFIFO_DATA1,
1021
+ .post_write = can_tx_post_write,
1022
+ },{ .name = "TXFIFO_DATA2", .addr = A_TXFIFO_DATA2,
1023
+ .post_write = can_tx_post_write,
1024
+ },{ .name = "TXHPB_ID", .addr = A_TXHPB_ID,
1025
+ .post_write = can_tx_post_write,
1026
+ },{ .name = "TXHPB_DLC", .addr = A_TXHPB_DLC,
1027
+ .rsvd = 0xfffffff,
1028
+ .post_write = can_tx_post_write,
1029
+ },{ .name = "TXHPB_DATA1", .addr = A_TXHPB_DATA1,
1030
+ .post_write = can_tx_post_write,
1031
+ },{ .name = "TXHPB_DATA2", .addr = A_TXHPB_DATA2,
1032
+ .post_write = can_tx_post_write,
1033
+ },{ .name = "RXFIFO_ID", .addr = A_RXFIFO_ID,
1034
+ .ro = 0xffffffff,
1035
+ .post_read = can_rxfifo_pre_read,
1036
+ },{ .name = "RXFIFO_DLC", .addr = A_RXFIFO_DLC,
1037
+ .rsvd = 0xfff0000,
1038
+ .post_read = can_rxfifo_pre_read,
1039
+ },{ .name = "RXFIFO_DATA1", .addr = A_RXFIFO_DATA1,
1040
+ .post_read = can_rxfifo_pre_read,
1041
+ },{ .name = "RXFIFO_DATA2", .addr = A_RXFIFO_DATA2,
1042
+ .post_read = can_rxfifo_pre_read,
1043
+ },{ .name = "AFR", .addr = A_AFR,
1044
+ .rsvd = 0xfffffff0,
1045
+ .post_write = can_filter_enable_post_write,
1046
+ },{ .name = "AFMR1", .addr = A_AFMR1,
1047
+ .pre_write = can_filter_mask_pre_write,
1048
+ },{ .name = "AFIR1", .addr = A_AFIR1,
1049
+ .pre_write = can_filter_id_pre_write,
1050
+ },{ .name = "AFMR2", .addr = A_AFMR2,
1051
+ .pre_write = can_filter_mask_pre_write,
1052
+ },{ .name = "AFIR2", .addr = A_AFIR2,
1053
+ .pre_write = can_filter_id_pre_write,
1054
+ },{ .name = "AFMR3", .addr = A_AFMR3,
1055
+ .pre_write = can_filter_mask_pre_write,
1056
+ },{ .name = "AFIR3", .addr = A_AFIR3,
1057
+ .pre_write = can_filter_id_pre_write,
1058
+ },{ .name = "AFMR4", .addr = A_AFMR4,
1059
+ .pre_write = can_filter_mask_pre_write,
1060
+ },{ .name = "AFIR4", .addr = A_AFIR4,
1061
+ .pre_write = can_filter_id_pre_write,
1062
+ }
1063
+};
1064
+
1065
+static void xlnx_zynqmp_can_ptimer_cb(void *opaque)
1066
+{
1067
+ /* No action required on the timer rollover. */
1068
+}
1069
+
1070
+static const MemoryRegionOps can_ops = {
1071
+ .read = register_read_memory,
1072
+ .write = register_write_memory,
1073
+ .endianness = DEVICE_LITTLE_ENDIAN,
1074
+ .valid = {
1075
+ .min_access_size = 4,
1076
+ .max_access_size = 4,
1077
+ },
1078
+};
1079
+
1080
+static void xlnx_zynqmp_can_reset_init(Object *obj, ResetType type)
1081
+{
1082
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1083
+ unsigned int i;
1084
+
1085
+ for (i = R_RXFIFO_ID; i < ARRAY_SIZE(s->reg_info); ++i) {
1086
+ register_reset(&s->reg_info[i]);
1087
+ }
1088
+
1089
+ ptimer_transaction_begin(s->can_timer);
1090
+ ptimer_set_count(s->can_timer, 0);
1091
+ ptimer_transaction_commit(s->can_timer);
1092
+}
1093
+
1094
+static void xlnx_zynqmp_can_reset_hold(Object *obj)
1095
+{
1096
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1097
+ unsigned int i;
1098
+
1099
+ for (i = 0; i < R_RXFIFO_ID; ++i) {
1100
+ register_reset(&s->reg_info[i]);
1101
+ }
1102
+
1103
+ /*
1104
+ * Reset FIFOs when CAN model is reset. This will clear the fifo writes
1105
+ * done by post_write which gets called from register_reset function,
1106
+ * post_write handle will not be able to trigger tx because CAN will be
1107
+ * disabled when software_reset_register is cleared first.
1108
+ */
1109
+ fifo32_reset(&s->rx_fifo);
1110
+ fifo32_reset(&s->tx_fifo);
1111
+ fifo32_reset(&s->txhpb_fifo);
1112
+}
1113
+
1114
+static bool xlnx_zynqmp_can_can_receive(CanBusClientState *client)
1115
+{
1116
+ XlnxZynqMPCANState *s = container_of(client, XlnxZynqMPCANState,
1117
+ bus_client);
1118
+
1119
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
1120
+ DB_PRINT(s, "Controller is in reset.\n");
1121
+ return false;
1122
+ } else if ((ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) == 0) {
1123
+ DB_PRINT(s, "Controller is disabled. Incoming messages"
1124
+ " will be discarded.\n");
1125
+ return false;
1126
+ } else {
1127
+ return true;
1128
+ }
1129
+}
1130
+
1131
+static ssize_t xlnx_zynqmp_can_receive(CanBusClientState *client,
1132
+ const qemu_can_frame *buf, size_t buf_size) {
1133
+ XlnxZynqMPCANState *s = container_of(client, XlnxZynqMPCANState,
1134
+ bus_client);
1135
+ const qemu_can_frame *frame = buf;
1136
+
1137
+ DB_PRINT(s, "Incoming data.\n");
1138
+
1139
+ if (buf_size <= 0) {
1140
+ DB_PRINT(s, "Junk data received.\n");
1141
+ return 0;
1142
+ }
1143
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
1144
+ /*
1145
+ * XlnxZynqMPCAN will not participate in normal bus communication
1146
+ * and will not receive any messages transmitted by other CAN nodes.
1147
+ */
1148
+ DB_PRINT(s, "Controller is in loopback mode. It will not"
1149
+ " receive data.\n");
1150
+
1151
+ } else if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
1152
+ /* Snoop Mode: Just keep the data. no response back. */
1153
+ update_rx_fifo(s, frame);
1154
+ } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP))) {
1155
+ /*
1156
+ * XlnxZynqMPCAN is in sleep mode. Any data on bus will bring it to wake
1157
+ * up state.
1158
+ */
1159
+ can_exit_sleep_mode(s);
1160
+ update_rx_fifo(s, frame);
1161
+ } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) == 0) {
1162
+ update_rx_fifo(s, frame);
1163
+ } else {
1164
+ DB_PRINT(s, "Cannot receive data as controller is not configured"
1165
+ " correctly.\n");
1166
+ }
1167
+
1168
+ return 1;
1169
+}
1170
+
1171
+static CanBusClientInfo can_xilinx_bus_client_info = {
1172
+ .can_receive = xlnx_zynqmp_can_can_receive,
1173
+ .receive = xlnx_zynqmp_can_receive,
1174
+};
1175
+
1176
+static int xlnx_zynqmp_can_connect_to_bus(XlnxZynqMPCANState *s,
1177
+ CanBusState *bus)
1178
+{
1179
+ s->bus_client.info = &can_xilinx_bus_client_info;
1180
+
1181
+ if (can_bus_insert_client(bus, &s->bus_client) < 0) {
1182
+ return -1;
1183
+ }
1184
+ return 0;
1185
+}
1186
+
1187
+static void xlnx_zynqmp_can_realize(DeviceState *dev, Error **errp)
1188
+{
1189
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(dev);
1190
+
1191
+ if (s->canbus) {
1192
+ if (xlnx_zynqmp_can_connect_to_bus(s, s->canbus) < 0) {
1193
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1194
+
1195
+ error_setg(errp, "%s: xlnx_zynqmp_can_connect_to_bus"
1196
+ " failed.", path);
1197
+ return;
1198
+ }
1199
+
1200
+ } else {
1201
+ /* If no bus is set. */
1202
+ DB_PRINT(s, "Canbus property is not set.\n");
1203
+ }
1204
+
1205
+ /* Create RX FIFO, TXFIFO, TXHPB storage. */
1206
+ fifo32_create(&s->rx_fifo, RXFIFO_SIZE);
1207
+ fifo32_create(&s->tx_fifo, RXFIFO_SIZE);
1208
+ fifo32_create(&s->txhpb_fifo, CAN_FRAME_SIZE);
1209
+
1210
+ /* Allocate a new timer. */
1211
+ s->can_timer = ptimer_init(xlnx_zynqmp_can_ptimer_cb, s,
1212
+ PTIMER_POLICY_DEFAULT);
1213
+
1214
+ ptimer_transaction_begin(s->can_timer);
1215
+
1216
+ ptimer_set_freq(s->can_timer, s->cfg.ext_clk_freq);
1217
+ ptimer_set_limit(s->can_timer, CAN_TIMER_MAX, 1);
1218
+ ptimer_run(s->can_timer, 0);
1219
+ ptimer_transaction_commit(s->can_timer);
1220
+}
1221
+
1222
+static void xlnx_zynqmp_can_init(Object *obj)
1223
+{
1224
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1225
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1226
+
1227
+ RegisterInfoArray *reg_array;
1228
+
1229
+ memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_CAN,
1230
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
1231
+ reg_array = register_init_block32(DEVICE(obj), can_regs_info,
1232
+ ARRAY_SIZE(can_regs_info),
1233
+ s->reg_info, s->regs,
1234
+ &can_ops,
1235
+ XLNX_ZYNQMP_CAN_ERR_DEBUG,
1236
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
1237
+
1238
+ memory_region_add_subregion(&s->iomem, 0x00, &reg_array->mem);
1239
+ sysbus_init_mmio(sbd, &s->iomem);
1240
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
1241
+}
1242
+
1243
+static const VMStateDescription vmstate_can = {
1244
+ .name = TYPE_XLNX_ZYNQMP_CAN,
1245
+ .version_id = 1,
1246
+ .minimum_version_id = 1,
1247
+ .fields = (VMStateField[]) {
1248
+ VMSTATE_FIFO32(rx_fifo, XlnxZynqMPCANState),
1249
+ VMSTATE_FIFO32(tx_fifo, XlnxZynqMPCANState),
1250
+ VMSTATE_FIFO32(txhpb_fifo, XlnxZynqMPCANState),
1251
+ VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPCANState, XLNX_ZYNQMP_CAN_R_MAX),
1252
+ VMSTATE_PTIMER(can_timer, XlnxZynqMPCANState),
1253
+ VMSTATE_END_OF_LIST(),
1254
+ }
1255
+};
1256
+
1257
+static Property xlnx_zynqmp_can_properties[] = {
1258
+ DEFINE_PROP_UINT32("ext_clk_freq", XlnxZynqMPCANState, cfg.ext_clk_freq,
1259
+ CAN_DEFAULT_CLOCK),
1260
+ DEFINE_PROP_LINK("canbus", XlnxZynqMPCANState, canbus, TYPE_CAN_BUS,
1261
+ CanBusState *),
1262
+ DEFINE_PROP_END_OF_LIST(),
1263
+};
1264
+
1265
+static void xlnx_zynqmp_can_class_init(ObjectClass *klass, void *data)
1266
+{
1267
+ DeviceClass *dc = DEVICE_CLASS(klass);
1268
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
1269
+
1270
+ rc->phases.enter = xlnx_zynqmp_can_reset_init;
1271
+ rc->phases.hold = xlnx_zynqmp_can_reset_hold;
1272
+ dc->realize = xlnx_zynqmp_can_realize;
1273
+ device_class_set_props(dc, xlnx_zynqmp_can_properties);
1274
+ dc->vmsd = &vmstate_can;
1275
+}
1276
+
1277
+static const TypeInfo can_info = {
1278
+ .name = TYPE_XLNX_ZYNQMP_CAN,
1279
+ .parent = TYPE_SYS_BUS_DEVICE,
1280
+ .instance_size = sizeof(XlnxZynqMPCANState),
1281
+ .class_init = xlnx_zynqmp_can_class_init,
1282
+ .instance_init = xlnx_zynqmp_can_init,
1283
+};
1284
+
1285
+static void can_register_types(void)
1286
+{
1287
+ type_register_static(&can_info);
1288
+}
1289
+
1290
+type_init(can_register_types)
1291
diff --git a/hw/net/can/meson.build b/hw/net/can/meson.build
1292
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
1293
--- a/hw/net/can/meson.build
18
--- a/target/arm/cpu.c
1294
+++ b/hw/net/can/meson.build
19
+++ b/target/arm/cpu.c
1295
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_CAN_SJA1000', if_true: files('can_sja1000.c'))
20
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
1296
softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_kvaser_pci.c'))
21
1297
softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_pcm3680_pci.c'))
22
#ifndef CONFIG_USER_ONLY
1298
softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_mioe3680_pci.c'))
23
/*
1299
+softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP', if_true: files('xlnx-zynqmp-can.c'))
24
- * Disable the MTE feature bits if we do not have tag-memory
25
- * provided by the machine.
26
+ * If we do not have tag-memory provided by the machine,
27
+ * reduce MTE support to instructions enabled at EL0.
28
+ * This matches Cortex-A710 BROADCASTMTE input being LOW.
29
*/
30
if (cpu->tag_memory == NULL) {
31
cpu->isar.id_aa64pfr1 =
32
- FIELD_DP64(cpu->isar.id_aa64pfr1, ID_AA64PFR1, MTE, 0);
33
+ FIELD_DP64(cpu->isar.id_aa64pfr1, ID_AA64PFR1, MTE, 1);
34
}
35
#endif
36
}
1300
--
37
--
1301
2.20.1
38
2.34.1
1302
1303
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
When booting directly into a kernel, bypassing the boot loader, the CPU and
3
Do not hard-code the constants for Neoverse V1.
4
UART clocks are not set up correctly. This makes the system appear very
5
slow, and causes the initrd boot test to fail when optimization is off.
6
4
7
The UART clock must run at 24 MHz. The default 25 MHz reference clock
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
cannot achieve this, so switch to PLL2/2 @ 480 MHz, which works
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
perfectly with the default /20 divider.
7
Message-id: 20230811214031.171020-6-richard.henderson@linaro.org
10
11
The CPU clock should run at 800 MHz, so switch it to PLL1/2. PLL1 runs
12
at 800 MHz by default, so we need to double the feedback divider as well
13
to make it run at 1600 MHz (so PLL1/2 runs at 800 MHz).
14
15
We don't bother checking for PLL lock because we know our emulated PLLs
16
lock instantly.
17
18
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
21
Message-id: 20200911052101.2602693-13-hskinnemoen@google.com
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
---
9
---
24
include/hw/arm/npcm7xx.h | 1 +
10
target/arm/tcg/cpu64.c | 48 ++++++++++++++++++++++++++++--------------
25
hw/arm/npcm7xx.c | 32 ++++++++++++++++++++++++++++++++
11
1 file changed, 32 insertions(+), 16 deletions(-)
26
2 files changed, 33 insertions(+)
27
12
28
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
13
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
29
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
30
--- a/include/hw/arm/npcm7xx.h
15
--- a/target/arm/tcg/cpu64.c
31
+++ b/include/hw/arm/npcm7xx.h
16
+++ b/target/arm/tcg/cpu64.c
32
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@
33
#define NPCM7XX_SMP_LOADER_START (0xffff0000) /* Boot ROM */
18
#include "qemu/module.h"
34
#define NPCM7XX_SMP_BOOTREG_ADDR (0xf080013c) /* GCR.SCRPAD */
19
#include "qapi/visitor.h"
35
#define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100) /* GIC within A9 */
20
#include "hw/qdev-properties.h"
36
+#define NPCM7XX_BOARD_SETUP_ADDR (0xffff1000) /* Boot ROM */
21
+#include "qemu/units.h"
37
22
#include "internals.h"
38
typedef struct NPCM7xxMachine {
23
#include "cpregs.h"
39
MachineState parent;
24
40
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
25
+static uint64_t make_ccsidr64(unsigned assoc, unsigned linesize,
41
index XXXXXXX..XXXXXXX 100644
26
+ unsigned cachesize)
42
--- a/hw/arm/npcm7xx.c
27
+{
43
+++ b/hw/arm/npcm7xx.c
28
+ unsigned lg_linesize = ctz32(linesize);
44
@@ -XXX,XX +XXX,XX @@
29
+ unsigned sets;
45
#define NPCM7XX_ROM_BA (0xffff0000)
46
#define NPCM7XX_ROM_SZ (64 * KiB)
47
48
+/* Clock configuration values to be fixed up when bypassing bootloader */
49
+
30
+
50
+/* Run PLL1 at 1600 MHz */
31
+ /*
51
+#define NPCM7XX_PLLCON1_FIXUP_VAL (0x00402101)
32
+ * The 64-bit CCSIDR_EL1 format is:
52
+/* Run the CPU from PLL1 and UART from PLL2 */
33
+ * [55:32] number of sets - 1
53
+#define NPCM7XX_CLKSEL_FIXUP_VAL (0x004aaba9)
34
+ * [23:3] associativity - 1
35
+ * [2:0] log2(linesize) - 4
36
+ * so 0 == 16 bytes, 1 == 32 bytes, 2 == 64 bytes, etc
37
+ */
38
+ assert(assoc != 0);
39
+ assert(is_power_of_2(linesize));
40
+ assert(lg_linesize >= 4 && lg_linesize <= 7 + 4);
54
+
41
+
55
/*
42
+ /* sets * associativity * linesize == cachesize. */
56
* Interrupt lines going into the GIC. This does not include internal Cortex-A9
43
+ sets = cachesize / (assoc * linesize);
57
* interrupts.
44
+ assert(cachesize % (assoc * linesize) == 0);
58
@@ -XXX,XX +XXX,XX @@ static const struct {
59
},
60
};
61
62
+static void npcm7xx_write_board_setup(ARMCPU *cpu,
63
+ const struct arm_boot_info *info)
64
+{
65
+ uint32_t board_setup[] = {
66
+ 0xe59f0010, /* ldr r0, clk_base_addr */
67
+ 0xe59f1010, /* ldr r1, pllcon1_value */
68
+ 0xe5801010, /* str r1, [r0, #16] */
69
+ 0xe59f100c, /* ldr r1, clksel_value */
70
+ 0xe5801004, /* str r1, [r0, #4] */
71
+ 0xe12fff1e, /* bx lr */
72
+ NPCM7XX_CLK_BA,
73
+ NPCM7XX_PLLCON1_FIXUP_VAL,
74
+ NPCM7XX_CLKSEL_FIXUP_VAL,
75
+ };
76
+ int i;
77
+
45
+
78
+ for (i = 0; i < ARRAY_SIZE(board_setup); i++) {
46
+ return ((uint64_t)(sets - 1) << 32)
79
+ board_setup[i] = tswap32(board_setup[i]);
47
+ | ((assoc - 1) << 3)
80
+ }
48
+ | (lg_linesize - 4);
81
+ rom_add_blob_fixed("board-setup", board_setup, sizeof(board_setup),
82
+ info->board_setup_addr);
83
+}
49
+}
84
+
50
+
85
static void npcm7xx_write_secondary_boot(ARMCPU *cpu,
51
static void aarch64_a35_initfn(Object *obj)
86
const struct arm_boot_info *info)
87
{
52
{
88
@@ -XXX,XX +XXX,XX @@ static struct arm_boot_info npcm7xx_binfo = {
53
ARMCPU *cpu = ARM_CPU(obj);
89
.gic_cpu_if_addr = NPCM7XX_GIC_CPU_IF_ADDR,
54
@@ -XXX,XX +XXX,XX @@ static void aarch64_neoverse_v1_initfn(Object *obj)
90
.write_secondary_boot = npcm7xx_write_secondary_boot,
55
* The Neoverse-V1 r1p2 TRM lists 32-bit format CCSIDR_EL1 values,
91
.board_id = -1,
56
* but also says it implements CCIDX, which means they should be
92
+ .board_setup_addr = NPCM7XX_BOARD_SETUP_ADDR,
57
* 64-bit format. So we here use values which are based on the textual
93
+ .write_board_setup = npcm7xx_write_board_setup,
58
- * information in chapter 2 of the TRM (and on the fact that
94
};
59
- * sets * associativity * linesize == cachesize).
95
60
- *
96
void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
61
- * The 64-bit CCSIDR_EL1 format is:
62
- * [55:32] number of sets - 1
63
- * [23:3] associativity - 1
64
- * [2:0] log2(linesize) - 4
65
- * so 0 == 16 bytes, 1 == 32 bytes, 2 == 64 bytes, etc
66
- *
67
- * L1: 4-way set associative 64-byte line size, total size 64K,
68
- * so sets is 256.
69
+ * information in chapter 2 of the TRM:
70
*
71
+ * L1: 4-way set associative 64-byte line size, total size 64K.
72
* L2: 8-way set associative, 64 byte line size, either 512K or 1MB.
73
- * We pick 1MB, so this has 2048 sets.
74
- *
75
* L3: No L3 (this matches the CLIDR_EL1 value).
76
*/
77
- cpu->ccsidr[0] = 0x000000ff0000001aull; /* 64KB L1 dcache */
78
- cpu->ccsidr[1] = 0x000000ff0000001aull; /* 64KB L1 icache */
79
- cpu->ccsidr[2] = 0x000007ff0000003aull; /* 1MB L2 cache */
80
+ cpu->ccsidr[0] = make_ccsidr64(4, 64, 64 * KiB); /* L1 dcache */
81
+ cpu->ccsidr[1] = cpu->ccsidr[0]; /* L1 icache */
82
+ cpu->ccsidr[2] = make_ccsidr64(8, 64, 1 * MiB); /* L2 cache */
83
84
/* From 3.2.115 SCTLR_EL3 */
85
cpu->reset_sctlr = 0x30c50838;
97
--
86
--
98
2.20.1
87
2.34.1
99
100
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Per the datasheet (DDI0407 r2p0):
3
Access to many of the special registers is enabled or disabled
4
by ACTLR_EL[23], which we implement as constant 0, which means
5
that all writes outside EL3 should trap.
4
6
5
"The SCU connects one to four Cortex-A9 processors to
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
the memory system through the AXI interfaces."
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
9
Message-id: 20230811214031.171020-7-richard.henderson@linaro.org
8
Change the instance_init() handler to a device_realize()
9
one so we can verify the property is in range, and return
10
an error to the caller if not.
11
12
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20200901144100.116742-2-f4bug@amsat.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
11
---
17
hw/misc/a9scu.c | 18 +++++++++++++-----
12
target/arm/cpregs.h | 2 ++
18
1 file changed, 13 insertions(+), 5 deletions(-)
13
target/arm/helper.c | 4 ++--
14
target/arm/tcg/cpu64.c | 46 +++++++++++++++++++++++++++++++++---------
15
3 files changed, 41 insertions(+), 11 deletions(-)
19
16
20
diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c
17
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
21
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/misc/a9scu.c
19
--- a/target/arm/cpregs.h
23
+++ b/hw/misc/a9scu.c
20
+++ b/target/arm/cpregs.h
24
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ static inline void define_cortex_a72_a57_a53_cp_reginfo(ARMCPU *cpu) { }
25
#include "hw/misc/a9scu.h"
22
void define_cortex_a72_a57_a53_cp_reginfo(ARMCPU *cpu);
26
#include "hw/qdev-properties.h"
23
#endif
27
#include "migration/vmstate.h"
24
28
+#include "qapi/error.h"
25
+CPAccessResult access_tvm_trvm(CPUARMState *, const ARMCPRegInfo *, bool);
29
#include "qemu/module.h"
30
31
+#define A9_SCU_CPU_MAX 4
32
+
26
+
33
static uint64_t a9_scu_read(void *opaque, hwaddr offset,
27
#endif /* TARGET_ARM_CPREGS_H */
34
unsigned size)
28
diff --git a/target/arm/helper.c b/target/arm/helper.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/helper.c
31
+++ b/target/arm/helper.c
32
@@ -XXX,XX +XXX,XX @@ static CPAccessResult access_tpm(CPUARMState *env, const ARMCPRegInfo *ri,
33
}
34
35
/* Check for traps from EL1 due to HCR_EL2.TVM and HCR_EL2.TRVM. */
36
-static CPAccessResult access_tvm_trvm(CPUARMState *env, const ARMCPRegInfo *ri,
37
- bool isread)
38
+CPAccessResult access_tvm_trvm(CPUARMState *env, const ARMCPRegInfo *ri,
39
+ bool isread)
35
{
40
{
36
@@ -XXX,XX +XXX,XX @@ static void a9_scu_reset(DeviceState *dev)
41
if (arm_current_el(env) == 1) {
37
s->control = 0;
42
uint64_t trap = isread ? HCR_TRVM : HCR_TVM;
43
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/tcg/cpu64.c
46
+++ b/target/arm/tcg/cpu64.c
47
@@ -XXX,XX +XXX,XX @@ static void aarch64_a64fx_initfn(Object *obj)
48
/* TODO: Add A64FX specific HPC extension registers */
38
}
49
}
39
50
40
-static void a9_scu_init(Object *obj)
51
+static CPAccessResult access_actlr_w(CPUARMState *env, const ARMCPRegInfo *r,
41
+static void a9_scu_realize(DeviceState *dev, Error **errp)
52
+ bool read)
42
{
53
+{
43
- A9SCUState *s = A9_SCU(obj);
54
+ if (!read) {
44
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
55
+ int el = arm_current_el(env);
45
+ A9SCUState *s = A9_SCU(dev);
56
+
46
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
57
+ /* Because ACTLR_EL2 is constant 0, writes below EL2 trap to EL2. */
47
58
+ if (el < 2 && arm_is_el2_enabled(env)) {
48
- memory_region_init_io(&s->iomem, obj, &a9_scu_ops, s,
59
+ return CP_ACCESS_TRAP_EL2;
49
+ if (!s->num_cpu || s->num_cpu > A9_SCU_CPU_MAX) {
60
+ }
50
+ error_setg(errp, "Illegal CPU count: %u", s->num_cpu);
61
+ /* Because ACTLR_EL3 is constant 0, writes below EL3 trap to EL3. */
51
+ return;
62
+ if (el < 3 && arm_feature(env, ARM_FEATURE_EL3)) {
63
+ return CP_ACCESS_TRAP_EL3;
64
+ }
52
+ }
65
+ }
66
+ return CP_ACCESS_OK;
67
+}
53
+
68
+
54
+ memory_region_init_io(&s->iomem, OBJECT(s), &a9_scu_ops, s,
69
static const ARMCPRegInfo neoverse_n1_cp_reginfo[] = {
55
"a9-scu", 0x100);
70
{ .name = "ATCR_EL1", .state = ARM_CP_STATE_AA64,
56
sysbus_init_mmio(sbd, &s->iomem);
71
.opc0 = 3, .opc1 = 0, .crn = 15, .crm = 7, .opc2 = 0,
57
}
72
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
58
@@ -XXX,XX +XXX,XX @@ static void a9_scu_class_init(ObjectClass *klass, void *data)
73
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
59
device_class_set_props(dc, a9_scu_properties);
74
+ /* Traps and enables are the same as for TCR_EL1. */
60
dc->vmsd = &vmstate_a9_scu;
75
+ .accessfn = access_tvm_trvm, .fgt = FGT_TCR_EL1, },
61
dc->reset = a9_scu_reset;
76
{ .name = "ATCR_EL2", .state = ARM_CP_STATE_AA64,
62
+ dc->realize = a9_scu_realize;
77
.opc0 = 3, .opc1 = 4, .crn = 15, .crm = 7, .opc2 = 0,
63
}
78
.access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
64
79
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo neoverse_n1_cp_reginfo[] = {
65
static const TypeInfo a9_scu_info = {
80
.access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
66
.name = TYPE_A9_SCU,
81
{ .name = "CPUACTLR_EL1", .state = ARM_CP_STATE_AA64,
67
.parent = TYPE_SYS_BUS_DEVICE,
82
.opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 0,
68
.instance_size = sizeof(A9SCUState),
83
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
69
- .instance_init = a9_scu_init,
84
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
70
.class_init = a9_scu_class_init,
85
+ .accessfn = access_actlr_w },
86
{ .name = "CPUACTLR2_EL1", .state = ARM_CP_STATE_AA64,
87
.opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 1,
88
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
89
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
90
+ .accessfn = access_actlr_w },
91
{ .name = "CPUACTLR3_EL1", .state = ARM_CP_STATE_AA64,
92
.opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 2,
93
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
94
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
95
+ .accessfn = access_actlr_w },
96
/*
97
* Report CPUCFR_EL1.SCU as 1, as we do not implement the DSU
98
* (and in particular its system registers).
99
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo neoverse_n1_cp_reginfo[] = {
100
.access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 4 },
101
{ .name = "CPUECTLR_EL1", .state = ARM_CP_STATE_AA64,
102
.opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 4,
103
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0x961563010 },
104
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0x961563010,
105
+ .accessfn = access_actlr_w },
106
{ .name = "CPUPCR_EL3", .state = ARM_CP_STATE_AA64,
107
.opc0 = 3, .opc1 = 6, .crn = 15, .crm = 8, .opc2 = 1,
108
.access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
109
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo neoverse_n1_cp_reginfo[] = {
110
.access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
111
{ .name = "CPUPWRCTLR_EL1", .state = ARM_CP_STATE_AA64,
112
.opc0 = 3, .opc1 = 0, .crn = 15, .crm = 2, .opc2 = 7,
113
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
114
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
115
+ .accessfn = access_actlr_w },
116
{ .name = "ERXPFGCDN_EL1", .state = ARM_CP_STATE_AA64,
117
.opc0 = 3, .opc1 = 0, .crn = 15, .crm = 2, .opc2 = 2,
118
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
119
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
120
+ .accessfn = access_actlr_w },
121
{ .name = "ERXPFGCTL_EL1", .state = ARM_CP_STATE_AA64,
122
.opc0 = 3, .opc1 = 0, .crn = 15, .crm = 2, .opc2 = 1,
123
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
124
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
125
+ .accessfn = access_actlr_w },
126
{ .name = "ERXPFGF_EL1", .state = ARM_CP_STATE_AA64,
127
.opc0 = 3, .opc1 = 0, .crn = 15, .crm = 2, .opc2 = 0,
128
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
129
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
130
+ .accessfn = access_actlr_w },
71
};
131
};
72
132
133
static void define_neoverse_n1_cp_reginfo(ARMCPU *cpu)
73
--
134
--
74
2.20.1
135
2.34.1
75
76
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
Per the datasheet (DDI0407 r2p0):
4
5
"All SCU registers are byte accessible" and are 32-bit aligned.
6
7
Set MemoryRegionOps::valid min/max fields and simplify the write()
8
handler.
9
10
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20200901144100.116742-3-f4bug@amsat.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
hw/misc/a9scu.c | 21 +++++----------------
16
1 file changed, 5 insertions(+), 16 deletions(-)
17
18
diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/misc/a9scu.c
21
+++ b/hw/misc/a9scu.c
22
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
23
uint64_t value, unsigned size)
24
{
25
A9SCUState *s = (A9SCUState *)opaque;
26
- uint32_t mask;
27
+ uint32_t mask = MAKE_64BIT_MASK(0, size * 8);
28
uint32_t shift;
29
- switch (size) {
30
- case 1:
31
- mask = 0xff;
32
- break;
33
- case 2:
34
- mask = 0xffff;
35
- break;
36
- case 4:
37
- mask = 0xffffffff;
38
- break;
39
- default:
40
- fprintf(stderr, "Invalid size %u in write to a9 scu register %x\n",
41
- size, (unsigned)offset);
42
- return;
43
- }
44
45
switch (offset) {
46
case 0x00: /* Control */
47
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
48
static const MemoryRegionOps a9_scu_ops = {
49
.read = a9_scu_read,
50
.write = a9_scu_write,
51
+ .valid = {
52
+ .min_access_size = 1,
53
+ .max_access_size = 4,
54
+ },
55
.endianness = DEVICE_NATIVE_ENDIAN,
56
};
57
58
--
59
2.20.1
60
61
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
This model implementation is designed for 32-bit accesses.
4
We can simplify setting the MemoryRegionOps::impl min/max
5
fields to 32-bit (memory::access_with_adjusted_size() will
6
take care of the 8/16-bit accesses).
7
8
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20200901144100.116742-4-f4bug@amsat.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/misc/a9scu.c | 16 +++++-----------
14
1 file changed, 5 insertions(+), 11 deletions(-)
15
16
diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/misc/a9scu.c
19
+++ b/hw/misc/a9scu.c
20
@@ -XXX,XX +XXX,XX @@ static uint64_t a9_scu_read(void *opaque, hwaddr offset,
21
return (((1 << s->num_cpu) - 1) << 4) | (s->num_cpu - 1);
22
case 0x08: /* CPU Power Status */
23
return s->status;
24
- case 0x09: /* CPU status. */
25
- return s->status >> 8;
26
- case 0x0a: /* CPU status. */
27
- return s->status >> 16;
28
- case 0x0b: /* CPU status. */
29
- return s->status >> 24;
30
case 0x0c: /* Invalidate All Registers In Secure State */
31
return 0;
32
case 0x40: /* Filtering Start Address Register */
33
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
34
uint64_t value, unsigned size)
35
{
36
A9SCUState *s = (A9SCUState *)opaque;
37
- uint32_t mask = MAKE_64BIT_MASK(0, size * 8);
38
- uint32_t shift;
39
40
switch (offset) {
41
case 0x00: /* Control */
42
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
43
case 0x4: /* Configuration: RO */
44
break;
45
case 0x08: case 0x09: case 0x0A: case 0x0B: /* Power Control */
46
- shift = (offset - 0x8) * 8;
47
- s->status &= ~(mask << shift);
48
- s->status |= ((value & mask) << shift);
49
+ s->status = value;
50
break;
51
case 0x0c: /* Invalidate All Registers In Secure State */
52
/* no-op as we do not implement caches */
53
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
54
static const MemoryRegionOps a9_scu_ops = {
55
.read = a9_scu_read,
56
.write = a9_scu_write,
57
+ .impl = {
58
+ .min_access_size = 4,
59
+ .max_access_size = 4,
60
+ },
61
.valid = {
62
.min_access_size = 1,
63
.max_access_size = 4,
64
--
65
2.20.1
66
67
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
Report unimplemented register accesses using qemu_log_mask(UNIMP).
4
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200901144100.116742-5-f4bug@amsat.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
hw/misc/a9scu.c | 6 ++++++
11
1 file changed, 6 insertions(+)
12
13
diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/misc/a9scu.c
16
+++ b/hw/misc/a9scu.c
17
@@ -XXX,XX +XXX,XX @@
18
#include "hw/qdev-properties.h"
19
#include "migration/vmstate.h"
20
#include "qapi/error.h"
21
+#include "qemu/log.h"
22
#include "qemu/module.h"
23
24
#define A9_SCU_CPU_MAX 4
25
@@ -XXX,XX +XXX,XX @@ static uint64_t a9_scu_read(void *opaque, hwaddr offset,
26
case 0x54: /* SCU Non-secure Access Control Register */
27
/* unimplemented, fall through */
28
default:
29
+ qemu_log_mask(LOG_UNIMP, "%s: Unsupported offset 0x%"HWADDR_PRIx"\n",
30
+ __func__, offset);
31
return 0;
32
}
33
}
34
@@ -XXX,XX +XXX,XX @@ static void a9_scu_write(void *opaque, hwaddr offset,
35
case 0x54: /* SCU Non-secure Access Control Register */
36
/* unimplemented, fall through */
37
default:
38
+ qemu_log_mask(LOG_UNIMP, "%s: Unsupported offset 0x%"HWADDR_PRIx
39
+ " value 0x%"PRIx64"\n",
40
+ __func__, offset, value);
41
break;
42
}
43
}
44
--
45
2.20.1
46
47
diff view generated by jsdifflib
Deleted patch
1
It is the responsibility of board code for an armv7m system to set
2
system_clock_scale appropriately for the CPU speed of the core.
3
If it forgets to do this, then QEMU will hang if the guest tries
4
to use the systick timer in the "tick at the CPU clock frequency" mode.
5
1
6
We forgot that in a couple of our boards (see commits ce4f70e81ed23c93f,
7
e7e5a9595ab1136). Add an assertion in the systick reset method so
8
we don't let any new boards in with the same bug.
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Message-id: 20200825160847.18091-1-peter.maydell@linaro.org
13
---
14
hw/timer/armv7m_systick.c | 8 ++++++++
15
1 file changed, 8 insertions(+)
16
17
diff --git a/hw/timer/armv7m_systick.c b/hw/timer/armv7m_systick.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/timer/armv7m_systick.c
20
+++ b/hw/timer/armv7m_systick.c
21
@@ -XXX,XX +XXX,XX @@ static void systick_reset(DeviceState *dev)
22
{
23
SysTickState *s = SYSTICK(dev);
24
25
+ /*
26
+ * Forgetting to set system_clock_scale is always a board code
27
+ * bug. We can't check this earlier because for some boards
28
+ * (like stellaris) it is not yet configured at the point where
29
+ * the systick device is realized.
30
+ */
31
+ assert(system_clock_scale != 0);
32
+
33
s->control = 0;
34
s->reload = 0;
35
s->tick = 0;
36
--
37
2.20.1
38
39
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
This adds two acceptance tests for the quanta-gsj machine.
3
There is only one additional EL1 register modeled, which
4
also needs to use access_actlr_w.
4
5
5
One test downloads a lightly patched openbmc flash image from github and
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
verifies that it boots all the way to the login prompt.
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
8
Message-id: 20230811214031.171020-8-richard.henderson@linaro.org
8
The other test downloads a kernel, initrd and dtb built from the same
9
openbmc source and verifies that the kernel detects all CPUs and boots
10
to the point where it can't find the root filesystem (because we have no
11
flash image in this case).
12
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
16
Message-id: 20200911052101.2602693-15-hskinnemoen@google.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
10
---
19
tests/acceptance/boot_linux_console.py | 83 ++++++++++++++++++++++++++
11
target/arm/tcg/cpu64.c | 3 ++-
20
1 file changed, 83 insertions(+)
12
1 file changed, 2 insertions(+), 1 deletion(-)
21
13
22
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
14
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
23
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
24
--- a/tests/acceptance/boot_linux_console.py
16
--- a/target/arm/tcg/cpu64.c
25
+++ b/tests/acceptance/boot_linux_console.py
17
+++ b/target/arm/tcg/cpu64.c
26
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(LinuxKernelTest):
18
@@ -XXX,XX +XXX,XX @@ static void define_neoverse_n1_cp_reginfo(ARMCPU *cpu)
27
'sda')
19
static const ARMCPRegInfo neoverse_v1_cp_reginfo[] = {
28
# cubieboard's reboot is not functioning; omit reboot test.
20
{ .name = "CPUECTLR2_EL1", .state = ARM_CP_STATE_AA64,
29
21
.opc0 = 3, .opc1 = 0, .crn = 15, .crm = 1, .opc2 = 5,
30
+ def test_arm_quanta_gsj(self):
22
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
31
+ """
23
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0,
32
+ :avocado: tags=arch:arm
24
+ .accessfn = access_actlr_w },
33
+ :avocado: tags=machine:quanta-gsj
25
{ .name = "CPUPPMCR_EL3", .state = ARM_CP_STATE_AA64,
34
+ """
26
.opc0 = 3, .opc1 = 6, .crn = 15, .crm = 2, .opc2 = 0,
35
+ # 25 MiB compressed, 32 MiB uncompressed.
27
.access = PL3_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
36
+ image_url = (
37
+ 'https://github.com/hskinnemoen/openbmc/releases/download/'
38
+ '20200711-gsj-qemu-0/obmc-phosphor-image-gsj.static.mtd.gz')
39
+ image_hash = '14895e634923345cb5c8776037ff7876df96f6b1'
40
+ image_path_gz = self.fetch_asset(image_url, asset_hash=image_hash)
41
+ image_name = 'obmc.mtd'
42
+ image_path = os.path.join(self.workdir, image_name)
43
+ archive.gzip_uncompress(image_path_gz, image_path)
44
+
45
+ self.vm.set_console()
46
+ drive_args = 'file=' + image_path + ',if=mtd,bus=0,unit=0'
47
+ self.vm.add_args('-drive', drive_args)
48
+ self.vm.launch()
49
+
50
+ # Disable drivers and services that stall for a long time during boot,
51
+ # to avoid running past the 90-second timeout. These may be removed
52
+ # as the corresponding device support is added.
53
+ kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + (
54
+ 'console=${console} '
55
+ 'mem=${mem} '
56
+ 'initcall_blacklist=npcm_i2c_bus_driver_init '
57
+ 'systemd.mask=systemd-random-seed.service '
58
+ 'systemd.mask=dropbearkey.service '
59
+ )
60
+
61
+ self.wait_for_console_pattern('> BootBlock by Nuvoton')
62
+ self.wait_for_console_pattern('>Device: Poleg BMC NPCM730')
63
+ self.wait_for_console_pattern('>Skip DDR init.')
64
+ self.wait_for_console_pattern('U-Boot ')
65
+ interrupt_interactive_console_until_pattern(
66
+ self, 'Hit any key to stop autoboot:', 'U-Boot>')
67
+ exec_command_and_wait_for_pattern(
68
+ self, "setenv bootargs ${bootargs} " + kernel_command_line,
69
+ 'U-Boot>')
70
+ exec_command_and_wait_for_pattern(
71
+ self, 'run romboot', 'Booting Kernel from flash')
72
+ self.wait_for_console_pattern('Booting Linux on physical CPU 0x0')
73
+ self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0')
74
+ self.wait_for_console_pattern('OpenBMC Project Reference Distro')
75
+ self.wait_for_console_pattern('gsj login:')
76
+
77
+ def test_arm_quanta_gsj_initrd(self):
78
+ """
79
+ :avocado: tags=arch:arm
80
+ :avocado: tags=machine:quanta-gsj
81
+ """
82
+ initrd_url = (
83
+ 'https://github.com/hskinnemoen/openbmc/releases/download/'
84
+ '20200711-gsj-qemu-0/obmc-phosphor-initramfs-gsj.cpio.xz')
85
+ initrd_hash = '98fefe5d7e56727b1eb17d5c00311b1b5c945300'
86
+ initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
87
+ kernel_url = (
88
+ 'https://github.com/hskinnemoen/openbmc/releases/download/'
89
+ '20200711-gsj-qemu-0/uImage-gsj.bin')
90
+ kernel_hash = 'fa67b2f141d56d39b3c54305c0e8a899c99eb2c7'
91
+ kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
92
+ dtb_url = (
93
+ 'https://github.com/hskinnemoen/openbmc/releases/download/'
94
+ '20200711-gsj-qemu-0/nuvoton-npcm730-gsj.dtb')
95
+ dtb_hash = '18315f7006d7b688d8312d5c727eecd819aa36a4'
96
+ dtb_path = self.fetch_asset(dtb_url, asset_hash=dtb_hash)
97
+
98
+ self.vm.set_console()
99
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
100
+ 'console=ttyS0,115200n8 '
101
+ 'earlycon=uart8250,mmio32,0xf0001000')
102
+ self.vm.add_args('-kernel', kernel_path,
103
+ '-initrd', initrd_path,
104
+ '-dtb', dtb_path,
105
+ '-append', kernel_command_line)
106
+ self.vm.launch()
107
+
108
+ self.wait_for_console_pattern('Booting Linux on physical CPU 0x0')
109
+ self.wait_for_console_pattern('CPU1: thread -1, cpu 1, socket 0')
110
+ self.wait_for_console_pattern(
111
+ 'Give root password for system maintenance')
112
+
113
def test_arm_orangepi(self):
114
"""
115
:avocado: tags=arch:arm
116
--
28
--
117
2.20.1
29
2.34.1
118
119
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Cédric Le Goater <clg@kaod.org>
3
Like FEAT_TRF (Self-hosted Trace Extension), suppress tracing
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
external to the cpu, which is out of scope for QEMU.
5
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
5
6
Message-id: 20200911052101.2602693-14-hskinnemoen@google.com
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 20230811214031.171020-10-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
10
---
9
docs/system/arm/nuvoton.rst | 92 +++++++++++++++++++++++++++++++++++++
11
target/arm/cpu.c | 3 +++
10
docs/system/target-arm.rst | 1 +
12
1 file changed, 3 insertions(+)
11
2 files changed, 93 insertions(+)
12
create mode 100644 docs/system/arm/nuvoton.rst
13
13
14
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
15
new file mode 100644
16
index XXXXXXX..XXXXXXX
17
--- /dev/null
18
+++ b/docs/system/arm/nuvoton.rst
19
@@ -XXX,XX +XXX,XX @@
20
+Nuvoton iBMC boards (``npcm750-evb``, ``quanta-gsj``)
21
+=====================================================
22
+
23
+The `Nuvoton iBMC`_ chips (NPCM7xx) are a family of ARM-based SoCs that are
24
+designed to be used as Baseboard Management Controllers (BMCs) in various
25
+servers. They all feature one or two ARM Cortex A9 CPU cores, as well as an
26
+assortment of peripherals targeted for either Enterprise or Data Center /
27
+Hyperscale applications. The former is a superset of the latter, so NPCM750 has
28
+all the peripherals of NPCM730 and more.
29
+
30
+.. _Nuvoton iBMC: https://www.nuvoton.com/products/cloud-computing/ibmc/
31
+
32
+The NPCM750 SoC has two Cortex A9 cores and is targeted for the Enterprise
33
+segment. The following machines are based on this chip :
34
+
35
+- ``npcm750-evb`` Nuvoton NPCM750 Evaluation board
36
+
37
+The NPCM730 SoC has two Cortex A9 cores and is targeted for Data Center and
38
+Hyperscale applications. The following machines are based on this chip :
39
+
40
+- ``quanta-gsj`` Quanta GSJ server BMC
41
+
42
+There are also two more SoCs, NPCM710 and NPCM705, which are single-core
43
+variants of NPCM750 and NPCM730, respectively. These are currently not
44
+supported by QEMU.
45
+
46
+Supported devices
47
+-----------------
48
+
49
+ * SMP (Dual Core Cortex-A9)
50
+ * Cortex-A9MPCore built-in peripherals: SCU, GIC, Global Timer, Private Timer
51
+ and Watchdog.
52
+ * SRAM, ROM and DRAM mappings
53
+ * System Global Control Registers (GCR)
54
+ * Clock and reset controller (CLK)
55
+ * Timer controller (TIM)
56
+ * Serial ports (16550-based)
57
+ * DDR4 memory controller (dummy interface indicating memory training is done)
58
+ * OTP controllers (no protection features)
59
+ * Flash Interface Unit (FIU; no protection features)
60
+
61
+Missing devices
62
+---------------
63
+
64
+ * GPIO controller
65
+ * LPC/eSPI host-to-BMC interface, including
66
+
67
+ * Keyboard and mouse controller interface (KBCI)
68
+ * Keyboard Controller Style (KCS) channels
69
+ * BIOS POST code FIFO
70
+ * System Wake-up Control (SWC)
71
+ * Shared memory (SHM)
72
+ * eSPI slave interface
73
+
74
+ * Ethernet controllers (GMAC and EMC)
75
+ * USB host (USBH)
76
+ * USB device (USBD)
77
+ * SMBus controller (SMBF)
78
+ * Peripheral SPI controller (PSPI)
79
+ * Analog to Digital Converter (ADC)
80
+ * SD/MMC host
81
+ * Random Number Generator (RNG)
82
+ * PECI interface
83
+ * Pulse Width Modulation (PWM)
84
+ * Tachometer
85
+ * PCI and PCIe root complex and bridges
86
+ * VDM and MCTP support
87
+ * Serial I/O expansion
88
+ * LPC/eSPI host
89
+ * Coprocessor
90
+ * Graphics
91
+ * Video capture
92
+ * Encoding compression engine
93
+ * Security features
94
+
95
+Boot options
96
+------------
97
+
98
+The Nuvoton machines can boot from an OpenBMC firmware image, or directly into
99
+a kernel using the ``-kernel`` option. OpenBMC images for `quanta-gsj` and
100
+possibly others can be downloaded from the OpenPOWER jenkins :
101
+
102
+ https://openpower.xyz/
103
+
104
+The firmware image should be attached as an MTD drive. Example :
105
+
106
+.. code-block:: bash
107
+
108
+ $ qemu-system-arm -machine quanta-gsj -nographic \
109
+ -drive file=image-bmc,if=mtd,bus=0,unit=0,format=raw
110
+
111
+The default root password for test images is usually ``0penBmc``.
112
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
113
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
114
--- a/docs/system/target-arm.rst
16
--- a/target/arm/cpu.c
115
+++ b/docs/system/target-arm.rst
17
+++ b/target/arm/cpu.c
116
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
18
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
117
arm/musicpal
19
/* FEAT_SPE (Statistical Profiling Extension) */
118
arm/gumstix
20
cpu->isar.id_aa64dfr0 =
119
arm/nseries
21
FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, PMSVER, 0);
120
+ arm/nuvoton
22
+ /* FEAT_TRBE (Trace Buffer Extension) */
121
arm/orangepi
23
+ cpu->isar.id_aa64dfr0 =
122
arm/palm
24
+ FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, TRACEBUFFER, 0);
123
arm/xscale
25
/* FEAT_TRF (Self-hosted Trace Extension) */
26
cpu->isar.id_aa64dfr0 =
27
FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, TRACEFILT, 0);
124
--
28
--
125
2.20.1
29
2.34.1
126
127
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Only argument set members have to be C identifiers, everything
3
This feature allows the operating system to set TCR_ELx.HWU*
4
else gets prefixed during conversion to C. Some places just
4
to allow the implementation to use the PBHA bits from the
5
checked the leading character, and some places matched a leading
5
block and page descriptors for for IMPLEMENTATION DEFINED
6
character plus a C identifier.
6
purposes. Since QEMU has no need to use these bits, we may
7
simply ignore them.
7
8
8
Convert everything to match full identifiers, including the
9
[&%@&] prefix, and drop the full C identifier requirement.
10
11
Reported-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20200903192334.1603773-1-richard.henderson@linaro.org
11
Message-id: 20230811214031.171020-11-richard.henderson@linaro.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
13
---
17
tests/decode/succ_ident1.decode | 7 +++++
14
docs/system/arm/emulation.rst | 1 +
18
scripts/decodetree.py | 46 +++++++++++++++++++++------------
15
target/arm/tcg/cpu32.c | 2 +-
19
2 files changed, 37 insertions(+), 16 deletions(-)
16
target/arm/tcg/cpu64.c | 2 +-
20
create mode 100644 tests/decode/succ_ident1.decode
17
3 files changed, 3 insertions(+), 2 deletions(-)
21
18
22
diff --git a/tests/decode/succ_ident1.decode b/tests/decode/succ_ident1.decode
19
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
23
new file mode 100644
24
index XXXXXXX..XXXXXXX
25
--- /dev/null
26
+++ b/tests/decode/succ_ident1.decode
27
@@ -XXX,XX +XXX,XX @@
28
+%1f 0:8
29
+%2f 8:8
30
+%3f 16:8
31
+
32
+&3arg a b c
33
+@3arg ........ ........ ........ ........ &3arg a=%1f b=%2f c=%3f
34
+3insn 00000000 ........ ........ ........ @3arg
35
diff --git a/scripts/decodetree.py b/scripts/decodetree.py
36
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
37
--- a/scripts/decodetree.py
21
--- a/docs/system/arm/emulation.rst
38
+++ b/scripts/decodetree.py
22
+++ b/docs/system/arm/emulation.rst
39
@@ -XXX,XX +XXX,XX @@ output_fd = None
23
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
40
insntype = 'uint32_t'
24
- FEAT_HAFDBS (Hardware management of the access flag and dirty bit state)
41
decode_function = 'decode'
25
- FEAT_HCX (Support for the HCRX_EL2 register)
42
26
- FEAT_HPDS (Hierarchical permission disables)
43
-re_ident = '[a-zA-Z][a-zA-Z0-9_]*'
27
+- FEAT_HPDS2 (Translation table page-based hardware attributes)
44
+# An identifier for C.
28
- FEAT_I8MM (AArch64 Int8 matrix multiplication instructions)
45
+re_C_ident = '[a-zA-Z][a-zA-Z0-9_]*'
29
- FEAT_IDST (ID space trap handling)
46
30
- FEAT_IESB (Implicit error synchronization event)
47
+# Identifiers for Arguments, Fields, Formats and Patterns.
31
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
48
+re_arg_ident = '&[a-zA-Z0-9_]*'
32
index XXXXXXX..XXXXXXX 100644
49
+re_fld_ident = '%[a-zA-Z0-9_]*'
33
--- a/target/arm/tcg/cpu32.c
50
+re_fmt_ident = '@[a-zA-Z0-9_]*'
34
+++ b/target/arm/tcg/cpu32.c
51
+re_pat_ident = '[a-zA-Z0-9_]*'
35
@@ -XXX,XX +XXX,XX @@ void aa32_max_features(ARMCPU *cpu)
52
36
cpu->isar.id_mmfr3 = t;
53
def error_with_file(file, lineno, *args):
37
54
"""Print an error message from file:line and args and exit."""
38
t = cpu->isar.id_mmfr4;
55
@@ -XXX,XX +XXX,XX @@ class ExcMultiPattern(MultiPattern):
39
- t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* FEAT_AA32HPD */
56
def parse_field(lineno, name, toks):
40
+ t = FIELD_DP32(t, ID_MMFR4, HPDS, 2); /* FEAT_HPDS2 */
57
"""Parse one instruction field from TOKS at LINENO"""
41
t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
58
global fields
42
t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* FEAT_TTCNP */
59
- global re_ident
43
t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* FEAT_XNX */
60
global insnwidth
44
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
61
45
index XXXXXXX..XXXXXXX 100644
62
# A "simple" field will have only one entry;
46
--- a/target/arm/tcg/cpu64.c
63
@@ -XXX,XX +XXX,XX @@ def parse_field(lineno, name, toks):
47
+++ b/target/arm/tcg/cpu64.c
64
width = 0
48
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
65
func = None
49
t = FIELD_DP64(t, ID_AA64MMFR1, HAFDBS, 2); /* FEAT_HAFDBS */
66
for t in toks:
50
t = FIELD_DP64(t, ID_AA64MMFR1, VMIDBITS, 2); /* FEAT_VMID16 */
67
- if re.fullmatch('!function=' + re_ident, t):
51
t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1); /* FEAT_VHE */
68
+ if re.match('^!function=', t):
52
- t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* FEAT_HPDS */
69
if func:
53
+ t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 2); /* FEAT_HPDS2 */
70
error(lineno, 'duplicate function')
54
t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1); /* FEAT_LOR */
71
func = t.split('=')
55
t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 3); /* FEAT_PAN3 */
72
@@ -XXX,XX +XXX,XX @@ def parse_field(lineno, name, toks):
56
t = FIELD_DP64(t, ID_AA64MMFR1, XNX, 1); /* FEAT_XNX */
73
def parse_arguments(lineno, name, toks):
74
"""Parse one argument set from TOKS at LINENO"""
75
global arguments
76
- global re_ident
77
+ global re_C_ident
78
global anyextern
79
80
flds = []
81
@@ -XXX,XX +XXX,XX @@ def parse_arguments(lineno, name, toks):
82
extern = True
83
anyextern = True
84
continue
85
- if not re.fullmatch(re_ident, t):
86
+ if not re.fullmatch(re_C_ident, t):
87
error(lineno, 'invalid argument set token "{0}"'.format(t))
88
if t in flds:
89
error(lineno, 'duplicate argument "{0}"'.format(t))
90
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
91
global arguments
92
global formats
93
global allpatterns
94
- global re_ident
95
+ global re_arg_ident
96
+ global re_fld_ident
97
+ global re_fmt_ident
98
+ global re_C_ident
99
global insnwidth
100
global insnmask
101
global variablewidth
102
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
103
fmt = None
104
for t in toks:
105
# '&Foo' gives a format an explcit argument set.
106
- if t[0] == '&':
107
+ if re.fullmatch(re_arg_ident, t):
108
tt = t[1:]
109
if arg:
110
error(lineno, 'multiple argument sets')
111
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
112
continue
113
114
# '@Foo' gives a pattern an explicit format.
115
- if t[0] == '@':
116
+ if re.fullmatch(re_fmt_ident, t):
117
tt = t[1:]
118
if fmt:
119
error(lineno, 'multiple formats')
120
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
121
continue
122
123
# '%Foo' imports a field.
124
- if t[0] == '%':
125
+ if re.fullmatch(re_fld_ident, t):
126
tt = t[1:]
127
flds = add_field_byname(lineno, flds, tt, tt)
128
continue
129
130
# 'Foo=%Bar' imports a field with a different name.
131
- if re.fullmatch(re_ident + '=%' + re_ident, t):
132
+ if re.fullmatch(re_C_ident + '=' + re_fld_ident, t):
133
(fname, iname) = t.split('=%')
134
flds = add_field_byname(lineno, flds, fname, iname)
135
continue
136
137
# 'Foo=number' sets an argument field to a constant value
138
- if re.fullmatch(re_ident + '=[+-]?[0-9]+', t):
139
+ if re.fullmatch(re_C_ident + '=[+-]?[0-9]+', t):
140
(fname, value) = t.split('=')
141
value = int(value)
142
flds = add_field(lineno, flds, fname, ConstField(value))
143
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
144
fixedmask = (fixedmask << shift) | fms
145
undefmask = (undefmask << shift) | ubm
146
# Otherwise, fieldname:fieldwidth
147
- elif re.fullmatch(re_ident + ':s?[0-9]+', t):
148
+ elif re.fullmatch(re_C_ident + ':s?[0-9]+', t):
149
(fname, flen) = t.split(':')
150
sign = False
151
if flen[0] == 's':
152
@@ -XXX,XX +XXX,XX @@ def parse_generic(lineno, parent_pat, name, toks):
153
154
def parse_file(f, parent_pat):
155
"""Parse all of the patterns within a file"""
156
+ global re_arg_ident
157
+ global re_fld_ident
158
+ global re_fmt_ident
159
+ global re_pat_ident
160
161
# Read all of the lines of the file. Concatenate lines
162
# ending in backslash; discard empty lines and comments.
163
@@ -XXX,XX +XXX,XX @@ def parse_file(f, parent_pat):
164
continue
165
166
# Determine the type of object needing to be parsed.
167
- if name[0] == '%':
168
+ if re.fullmatch(re_fld_ident, name):
169
parse_field(start_lineno, name[1:], toks)
170
- elif name[0] == '&':
171
+ elif re.fullmatch(re_arg_ident, name):
172
parse_arguments(start_lineno, name[1:], toks)
173
- elif name[0] == '@':
174
+ elif re.fullmatch(re_fmt_ident, name):
175
parse_generic(start_lineno, None, name[1:], toks)
176
- else:
177
+ elif re.fullmatch(re_pat_ident, name):
178
parse_generic(start_lineno, parent_pat, name, toks)
179
+ else:
180
+ error(lineno, 'invalid token "{0}"'.format(name))
181
toks = []
182
183
if nesting != 0:
184
--
57
--
185
2.20.1
58
2.34.1
186
187
diff view generated by jsdifflib
Deleted patch
1
In the Neon instructions, some instruction formats have a 2-bit size
2
field which corresponds exactly to QEMU's MO_8/16/32/64. However the
3
floating-point insns in the 3-same group have a 1-bit size field
4
which is "0 for 32-bit float and 1 for 16-bit float". Currently we
5
pass these values directly through to trans_ functions, which means
6
that when reading a particular trans_ function you need to know if
7
that insn uses a 2-bit size or a 1-bit size.
8
1
9
Move the handling of the 1-bit size to the decodetree file, so that
10
all these insns consistently pass a size to the trans_ function which
11
is an MO_8/16/32/64 value.
12
13
In this commit we switch over the insns using the 3same_fp and
14
3same_fp_q0 formats.
15
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Message-id: 20200903133209.5141-2-peter.maydell@linaro.org
19
---
20
target/arm/neon-dp.decode | 15 ++++++++++-----
21
target/arm/translate-neon.c.inc | 16 +++++++++++-----
22
2 files changed, 21 insertions(+), 10 deletions(-)
23
24
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
25
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/neon-dp.decode
27
+++ b/target/arm/neon-dp.decode
28
@@ -XXX,XX +XXX,XX @@
29
@3same_q0 .... ... . . . size:2 .... .... .... . 0 . . .... \
30
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0
31
32
-# For FP insns the high bit of 'size' is used as part of opcode decode
33
-@3same_fp .... ... . . . . size:1 .... .... .... . q:1 . . .... \
34
- &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp
35
-@3same_fp_q0 .... ... . . . . size:1 .... .... .... . 0 . . .... \
36
- &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0
37
+# For FP insns the high bit of 'size' is used as part of opcode decode,
38
+# and the 'size' bit is 0 for 32-bit float and 1 for 16-bit float.
39
+# This converts this encoding to the same MO_8/16/32/64 values that the
40
+# integer neon insns use.
41
+%3same_fp_size 20:1 !function=neon_3same_fp_size
42
+
43
+@3same_fp .... ... . . . . . .... .... .... . q:1 . . .... \
44
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp size=%3same_fp_size
45
+@3same_fp_q0 .... ... . . . . . .... .... .... . 0 . . .... \
46
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0 size=%3same_fp_size
47
48
VHADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 0 .... @3same
49
VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same
50
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/translate-neon.c.inc
53
+++ b/target/arm/translate-neon.c.inc
54
@@ -XXX,XX +XXX,XX @@ static inline int rsub_8(DisasContext *s, int x)
55
return 8 - x;
56
}
57
58
+static inline int neon_3same_fp_size(DisasContext *s, int x)
59
+{
60
+ /* Convert 0==fp32, 1==fp16 into a MO_* value */
61
+ return MO_32 - x;
62
+}
63
+
64
/* Include the generated Neon decoder */
65
#include "decode-neon-dp.c.inc"
66
#include "decode-neon-ls.c.inc"
67
@@ -XXX,XX +XXX,XX @@ DO_3SAME_VQDMULH(VQRDMULH, qrdmulh)
68
WRAP_FP_GVEC(gen_##INSN##_fp16_3s, FPST_STD_F16, HFUNC) \
69
static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
70
{ \
71
- if (a->size != 0) { \
72
+ if (a->size == MO_16) { \
73
if (!dc_isar_feature(aa32_fp16_arith, s)) { \
74
return false; \
75
} \
76
@@ -XXX,XX +XXX,XX @@ static bool trans_VMAXNM_fp_3s(DisasContext *s, arg_3same *a)
77
return false;
78
}
79
80
- if (a->size != 0) {
81
+ if (a->size == MO_16) {
82
if (!dc_isar_feature(aa32_fp16_arith, s)) {
83
return false;
84
}
85
@@ -XXX,XX +XXX,XX @@ static bool trans_VMINNM_fp_3s(DisasContext *s, arg_3same *a)
86
return false;
87
}
88
89
- if (a->size != 0) {
90
+ if (a->size == MO_16) {
91
if (!dc_isar_feature(aa32_fp16_arith, s)) {
92
return false;
93
}
94
@@ -XXX,XX +XXX,XX @@ static bool do_3same_fp_pair(DisasContext *s, arg_3same *a,
95
assert(a->q == 0); /* enforced by decode patterns */
96
97
98
- fpstatus = fpstatus_ptr(a->size != 0 ? FPST_STD_F16 : FPST_STD);
99
+ fpstatus = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
100
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
101
vfp_reg_offset(1, a->vn),
102
vfp_reg_offset(1, a->vm),
103
@@ -XXX,XX +XXX,XX @@ static bool do_3same_fp_pair(DisasContext *s, arg_3same *a,
104
#define DO_3S_FP_PAIR(INSN,FUNC) \
105
static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
106
{ \
107
- if (a->size != 0) { \
108
+ if (a->size == MO_16) { \
109
if (!dc_isar_feature(aa32_fp16_arith, s)) { \
110
return false; \
111
} \
112
--
113
2.20.1
114
115
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Alex Bennée <alex.bennee@linaro.org>
2
2
3
This just implements the bare minimum to cause the boot block to skip
3
This is a mandatory feature for Armv8.1 architectures but we don't
4
memory initialization.
4
state the feature clearly in our emulation list. Also include
5
FEAT_CRC32 comment in aarch64_max_tcg_initfn for ease of grepping.
5
6
6
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Cédric Le Goater <clg@kaod.org>
8
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20230824075406.1515566-1-alex.bennee@linaro.org
9
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Cc: qemu-stable@nongnu.org
10
Tested-by: Alexander Bulekov <alxndr@bu.edu>
11
Message-Id: <20230222110104.3996971-1-alex.bennee@linaro.org>
11
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
12
[PMM: pluralize 'instructions' in docs]
12
Message-id: 20200911052101.2602693-10-hskinnemoen@google.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
14
---
15
include/hw/arm/npcm7xx.h | 2 +
15
docs/system/arm/emulation.rst | 1 +
16
include/hw/mem/npcm7xx_mc.h | 36 ++++++++++++++++
16
target/arm/tcg/cpu64.c | 2 +-
17
hw/arm/npcm7xx.c | 6 +++
17
2 files changed, 2 insertions(+), 1 deletion(-)
18
hw/mem/npcm7xx_mc.c | 84 +++++++++++++++++++++++++++++++++++++
19
hw/mem/meson.build | 1 +
20
5 files changed, 129 insertions(+)
21
create mode 100644 include/hw/mem/npcm7xx_mc.h
22
create mode 100644 hw/mem/npcm7xx_mc.c
23
18
24
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
19
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
25
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
26
--- a/include/hw/arm/npcm7xx.h
21
--- a/docs/system/arm/emulation.rst
27
+++ b/include/hw/arm/npcm7xx.h
22
+++ b/docs/system/arm/emulation.rst
28
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
29
24
- FEAT_BBM at level 2 (Translation table break-before-make levels)
30
#include "hw/boards.h"
25
- FEAT_BF16 (AArch64 BFloat16 instructions)
31
#include "hw/cpu/a9mpcore.h"
26
- FEAT_BTI (Branch Target Identification)
32
+#include "hw/mem/npcm7xx_mc.h"
27
+- FEAT_CRC32 (CRC32 instructions)
33
#include "hw/misc/npcm7xx_clk.h"
28
- FEAT_CSV2 (Cache speculation variant 2)
34
#include "hw/misc/npcm7xx_gcr.h"
29
- FEAT_CSV2_1p1 (Cache speculation variant 2, version 1.1)
35
#include "hw/nvram/npcm7xx_otp.h"
30
- FEAT_CSV2_1p2 (Cache speculation variant 2, version 1.2)
36
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
31
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
37
NPCM7xxTimerCtrlState tim[3];
38
NPCM7xxOTPState key_storage;
39
NPCM7xxOTPState fuse_array;
40
+ NPCM7xxMCState mc;
41
} NPCM7xxState;
42
43
#define TYPE_NPCM7XX "npcm7xx"
44
diff --git a/include/hw/mem/npcm7xx_mc.h b/include/hw/mem/npcm7xx_mc.h
45
new file mode 100644
46
index XXXXXXX..XXXXXXX
47
--- /dev/null
48
+++ b/include/hw/mem/npcm7xx_mc.h
49
@@ -XXX,XX +XXX,XX @@
50
+/*
51
+ * Nuvoton NPCM7xx Memory Controller stub
52
+ *
53
+ * Copyright 2020 Google LLC
54
+ *
55
+ * This program is free software; you can redistribute it and/or modify it
56
+ * under the terms of the GNU General Public License as published by the
57
+ * Free Software Foundation; either version 2 of the License, or
58
+ * (at your option) any later version.
59
+ *
60
+ * This program is distributed in the hope that it will be useful, but WITHOUT
61
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
62
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
63
+ * for more details.
64
+ */
65
+#ifndef NPCM7XX_MC_H
66
+#define NPCM7XX_MC_H
67
+
68
+#include "exec/memory.h"
69
+#include "hw/sysbus.h"
70
+
71
+/**
72
+ * struct NPCM7xxMCState - Device state for the memory controller.
73
+ * @parent: System bus device.
74
+ * @mmio: Memory region through which registers are accessed.
75
+ */
76
+typedef struct NPCM7xxMCState {
77
+ SysBusDevice parent;
78
+
79
+ MemoryRegion mmio;
80
+} NPCM7xxMCState;
81
+
82
+#define TYPE_NPCM7XX_MC "npcm7xx-mc"
83
+#define NPCM7XX_MC(obj) OBJECT_CHECK(NPCM7xxMCState, (obj), TYPE_NPCM7XX_MC)
84
+
85
+#endif /* NPCM7XX_MC_H */
86
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
87
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
88
--- a/hw/arm/npcm7xx.c
33
--- a/target/arm/tcg/cpu64.c
89
+++ b/hw/arm/npcm7xx.c
34
+++ b/target/arm/tcg/cpu64.c
90
@@ -XXX,XX +XXX,XX @@
35
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
91
#define NPCM7XX_CPUP_BA (0xf03fe000)
36
t = FIELD_DP64(t, ID_AA64ISAR0, AES, 2); /* FEAT_PMULL */
92
#define NPCM7XX_GCR_BA (0xf0800000)
37
t = FIELD_DP64(t, ID_AA64ISAR0, SHA1, 1); /* FEAT_SHA1 */
93
#define NPCM7XX_CLK_BA (0xf0801000)
38
t = FIELD_DP64(t, ID_AA64ISAR0, SHA2, 2); /* FEAT_SHA512 */
94
+#define NPCM7XX_MC_BA (0xf0824000)
39
- t = FIELD_DP64(t, ID_AA64ISAR0, CRC32, 1);
95
40
+ t = FIELD_DP64(t, ID_AA64ISAR0, CRC32, 1); /* FEAT_CRC32 */
96
/* Internal AHB SRAM */
41
t = FIELD_DP64(t, ID_AA64ISAR0, ATOMIC, 2); /* FEAT_LSE */
97
#define NPCM7XX_RAM3_BA (0xc0008000)
42
t = FIELD_DP64(t, ID_AA64ISAR0, RDM, 1); /* FEAT_RDM */
98
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
43
t = FIELD_DP64(t, ID_AA64ISAR0, SHA3, 1); /* FEAT_SHA3 */
99
TYPE_NPCM7XX_KEY_STORAGE);
100
object_initialize_child(obj, "otp2", &s->fuse_array,
101
TYPE_NPCM7XX_FUSE_ARRAY);
102
+ object_initialize_child(obj, "mc", &s->mc, TYPE_NPCM7XX_MC);
103
104
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
105
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
106
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
107
sysbus_mmio_map(SYS_BUS_DEVICE(&s->fuse_array), 0, NPCM7XX_OTP2_BA);
108
npcm7xx_init_fuses(s);
109
110
+ /* Fake Memory Controller (MC). Cannot fail. */
111
+ sysbus_realize(SYS_BUS_DEVICE(&s->mc), &error_abort);
112
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->mc), 0, NPCM7XX_MC_BA);
113
+
114
/* Timer Modules (TIM). Cannot fail. */
115
QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
116
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
117
diff --git a/hw/mem/npcm7xx_mc.c b/hw/mem/npcm7xx_mc.c
118
new file mode 100644
119
index XXXXXXX..XXXXXXX
120
--- /dev/null
121
+++ b/hw/mem/npcm7xx_mc.c
122
@@ -XXX,XX +XXX,XX @@
123
+/*
124
+ * Nuvoton NPCM7xx Memory Controller stub
125
+ *
126
+ * Copyright 2020 Google LLC
127
+ *
128
+ * This program is free software; you can redistribute it and/or modify it
129
+ * under the terms of the GNU General Public License as published by the
130
+ * Free Software Foundation; either version 2 of the License, or
131
+ * (at your option) any later version.
132
+ *
133
+ * This program is distributed in the hope that it will be useful, but WITHOUT
134
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
135
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
136
+ * for more details.
137
+ */
138
+
139
+#include "qemu/osdep.h"
140
+
141
+#include "hw/mem/npcm7xx_mc.h"
142
+#include "qapi/error.h"
143
+#include "qemu/log.h"
144
+#include "qemu/module.h"
145
+#include "qemu/units.h"
146
+
147
+#define NPCM7XX_MC_REGS_SIZE (4 * KiB)
148
+
149
+static uint64_t npcm7xx_mc_read(void *opaque, hwaddr addr, unsigned int size)
150
+{
151
+ /*
152
+ * If bits 8..11 @ offset 0 are not zero, the boot block thinks the memory
153
+ * controller has already been initialized and will skip DDR training.
154
+ */
155
+ if (addr == 0) {
156
+ return 0x100;
157
+ }
158
+
159
+ qemu_log_mask(LOG_UNIMP, "%s: mostly unimplemented\n", __func__);
160
+
161
+ return 0;
162
+}
163
+
164
+static void npcm7xx_mc_write(void *opaque, hwaddr addr, uint64_t v,
165
+ unsigned int size)
166
+{
167
+ qemu_log_mask(LOG_UNIMP, "%s: mostly unimplemented\n", __func__);
168
+}
169
+
170
+static const MemoryRegionOps npcm7xx_mc_ops = {
171
+ .read = npcm7xx_mc_read,
172
+ .write = npcm7xx_mc_write,
173
+ .endianness = DEVICE_LITTLE_ENDIAN,
174
+ .valid = {
175
+ .min_access_size = 4,
176
+ .max_access_size = 4,
177
+ .unaligned = false,
178
+ },
179
+};
180
+
181
+static void npcm7xx_mc_realize(DeviceState *dev, Error **errp)
182
+{
183
+ NPCM7xxMCState *s = NPCM7XX_MC(dev);
184
+
185
+ memory_region_init_io(&s->mmio, OBJECT(s), &npcm7xx_mc_ops, s, "regs",
186
+ NPCM7XX_MC_REGS_SIZE);
187
+ sysbus_init_mmio(&s->parent, &s->mmio);
188
+}
189
+
190
+static void npcm7xx_mc_class_init(ObjectClass *klass, void *data)
191
+{
192
+ DeviceClass *dc = DEVICE_CLASS(klass);
193
+
194
+ dc->desc = "NPCM7xx Memory Controller stub";
195
+ dc->realize = npcm7xx_mc_realize;
196
+}
197
+
198
+static const TypeInfo npcm7xx_mc_types[] = {
199
+ {
200
+ .name = TYPE_NPCM7XX_MC,
201
+ .parent = TYPE_SYS_BUS_DEVICE,
202
+ .instance_size = sizeof(NPCM7xxMCState),
203
+ .class_init = npcm7xx_mc_class_init,
204
+ },
205
+};
206
+DEFINE_TYPES(npcm7xx_mc_types);
207
diff --git a/hw/mem/meson.build b/hw/mem/meson.build
208
index XXXXXXX..XXXXXXX 100644
209
--- a/hw/mem/meson.build
210
+++ b/hw/mem/meson.build
211
@@ -XXX,XX +XXX,XX @@
212
mem_ss = ss.source_set()
213
mem_ss.add(files('memory-device.c'))
214
mem_ss.add(when: 'CONFIG_DIMM', if_true: files('pc-dimm.c'))
215
+mem_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_mc.c'))
216
mem_ss.add(when: 'CONFIG_NVDIMM', if_true: files('nvdimm.c'))
217
218
softmmu_ss.add_all(when: 'CONFIG_MEM_DEVICE', if_true: mem_ss)
219
--
44
--
220
2.20.1
45
2.34.1
221
46
222
47
diff view generated by jsdifflib
1
From: Aaron Lindsay <aaron@os.amperecomputing.com>
1
From: Jean-Christophe Dubois <jcd@tribudubois.net>
2
2
3
This check was backwards when introduced in commit
3
i.MX7 IOMUX GPR device is not equivalent to i.MX6UL IOMUXC GPR device.
4
033614c47de78409ad3fb39bb7bd1483b71c6789:
4
In particular, register 22 is not present on i.MX6UL and this is actualy
5
The only register that is really emulated in the i.MX7 IOMUX GPR device.
5
6
6
target/arm: Filter cycle counter based on PMCCFILTR_EL0
7
Note: The i.MX6UL code is actually also implementing the IOMUX GPR device
8
as an unimplemented device at the same bus adress and the 2 instantiations
9
were actualy colliding. So we go back to the unimplemented device for now.
7
10
8
Cc: qemu-stable@nongnu.org
11
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
9
Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
12
Message-id: 48681bf51ee97646479bb261bee19abebbc8074e.1692964892.git.jcd@tribudubois.net
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
15
---
13
target/arm/helper.c | 2 +-
16
include/hw/arm/fsl-imx6ul.h | 2 --
14
1 file changed, 1 insertion(+), 1 deletion(-)
17
hw/arm/fsl-imx6ul.c | 11 -----------
18
2 files changed, 13 deletions(-)
15
19
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
20
diff --git a/include/hw/arm/fsl-imx6ul.h b/include/hw/arm/fsl-imx6ul.h
17
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper.c
22
--- a/include/hw/arm/fsl-imx6ul.h
19
+++ b/target/arm/helper.c
23
+++ b/include/hw/arm/fsl-imx6ul.h
20
@@ -XXX,XX +XXX,XX @@ static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter)
24
@@ -XXX,XX +XXX,XX @@
21
}
25
#include "hw/misc/imx6ul_ccm.h"
22
} else {
26
#include "hw/misc/imx6_src.h"
23
prohibited = arm_feature(env, ARM_FEATURE_EL3) &&
27
#include "hw/misc/imx7_snvs.h"
24
- (env->cp15.mdcr_el3 & MDCR_SPME);
28
-#include "hw/misc/imx7_gpr.h"
25
+ !(env->cp15.mdcr_el3 & MDCR_SPME);
29
#include "hw/intc/imx_gpcv2.h"
30
#include "hw/watchdog/wdt_imx2.h"
31
#include "hw/gpio/imx_gpio.h"
32
@@ -XXX,XX +XXX,XX @@ struct FslIMX6ULState {
33
IMX6SRCState src;
34
IMX7SNVSState snvs;
35
IMXGPCv2State gpcv2;
36
- IMX7GPRState gpr;
37
IMXSPIState spi[FSL_IMX6UL_NUM_ECSPIS];
38
IMXI2CState i2c[FSL_IMX6UL_NUM_I2CS];
39
IMXSerialState uart[FSL_IMX6UL_NUM_UARTS];
40
diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/arm/fsl-imx6ul.c
43
+++ b/hw/arm/fsl-imx6ul.c
44
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_init(Object *obj)
45
*/
46
object_initialize_child(obj, "snvs", &s->snvs, TYPE_IMX7_SNVS);
47
48
- /*
49
- * GPR
50
- */
51
- object_initialize_child(obj, "gpr", &s->gpr, TYPE_IMX7_GPR);
52
-
53
/*
54
* GPIOs 1 to 5
55
*/
56
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
57
FSL_IMX6UL_WDOGn_IRQ[i]));
26
}
58
}
27
59
28
if (prohibited && counter == 31) {
60
- /*
61
- * GPR
62
- */
63
- sysbus_realize(SYS_BUS_DEVICE(&s->gpr), &error_abort);
64
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpr), 0, FSL_IMX6UL_IOMUXC_GPR_ADDR);
65
-
66
/*
67
* SDMA
68
*/
29
--
69
--
30
2.20.1
70
2.34.1
31
32
diff view generated by jsdifflib
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
1
From: Jean-Christophe Dubois <jcd@tribudubois.net>
2
2
3
Connect CAN0 and CAN1 on the ZynqMP.
3
* Add Addr and size definition for most i.MX6UL devices in i.MX6UL header file.
4
* Use those newly defined named constants whenever possible.
5
* Standardize the way we init a familly of unimplemented devices
6
- SAI
7
- PWM
8
- CAN
9
* Add/rework few comments
4
10
5
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
11
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
12
Message-id: d579043fbd4e4b490370783fda43fc02c8e9be75.1692964892.git.jcd@tribudubois.net
7
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Message-id: 1597278668-339715-3-git-send-email-fnu.vikram@xilinx.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
15
---
11
include/hw/arm/xlnx-zynqmp.h | 8 ++++++++
16
include/hw/arm/fsl-imx6ul.h | 156 +++++++++++++++++++++++++++++++-----
12
hw/arm/xlnx-zcu102.c | 20 ++++++++++++++++++++
17
hw/arm/fsl-imx6ul.c | 147 ++++++++++++++++++++++-----------
13
hw/arm/xlnx-zynqmp.c | 34 ++++++++++++++++++++++++++++++++++
18
2 files changed, 232 insertions(+), 71 deletions(-)
14
3 files changed, 62 insertions(+)
15
19
16
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
20
diff --git a/include/hw/arm/fsl-imx6ul.h b/include/hw/arm/fsl-imx6ul.h
17
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/xlnx-zynqmp.h
22
--- a/include/hw/arm/fsl-imx6ul.h
19
+++ b/include/hw/arm/xlnx-zynqmp.h
23
+++ b/include/hw/arm/fsl-imx6ul.h
20
@@ -XXX,XX +XXX,XX @@
24
@@ -XXX,XX +XXX,XX @@
21
#include "hw/intc/arm_gic.h"
25
#include "exec/memory.h"
22
#include "hw/net/cadence_gem.h"
26
#include "cpu.h"
23
#include "hw/char/cadence_uart.h"
24
+#include "hw/net/xlnx-zynqmp-can.h"
25
#include "hw/ide/ahci.h"
26
#include "hw/sd/sdhci.h"
27
#include "hw/ssi/xilinx_spips.h"
28
@@ -XXX,XX +XXX,XX @@
29
#include "hw/cpu/cluster.h"
30
#include "target/arm/cpu.h"
31
#include "qom/object.h"
27
#include "qom/object.h"
32
+#include "net/can_emu.h"
28
+#include "qemu/units.h"
33
29
34
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
30
#define TYPE_FSL_IMX6UL "fsl-imx6ul"
35
typedef struct XlnxZynqMPState XlnxZynqMPState;
31
OBJECT_DECLARE_SIMPLE_TYPE(FslIMX6ULState, FSL_IMX6UL)
36
@@ -XXX,XX +XXX,XX @@ DECLARE_INSTANCE_CHECKER(XlnxZynqMPState, XLNX_ZYNQMP,
32
@@ -XXX,XX +XXX,XX @@ enum FslIMX6ULConfiguration {
37
#define XLNX_ZYNQMP_NUM_RPU_CPUS 2
33
FSL_IMX6UL_NUM_ADCS = 2,
38
#define XLNX_ZYNQMP_NUM_GEMS 4
34
FSL_IMX6UL_NUM_USB_PHYS = 2,
39
#define XLNX_ZYNQMP_NUM_UARTS 2
35
FSL_IMX6UL_NUM_USBS = 2,
40
+#define XLNX_ZYNQMP_NUM_CAN 2
36
+ FSL_IMX6UL_NUM_SAIS = 3,
41
+#define XLNX_ZYNQMP_CAN_REF_CLK (24 * 1000 * 1000)
37
+ FSL_IMX6UL_NUM_CANS = 2,
42
#define XLNX_ZYNQMP_NUM_SDHCI 2
38
+ FSL_IMX6UL_NUM_PWMS = 4,
43
#define XLNX_ZYNQMP_NUM_SPIS 2
44
#define XLNX_ZYNQMP_NUM_GDMA_CH 8
45
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
46
47
CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
48
CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS];
49
+ XlnxZynqMPCANState can[XLNX_ZYNQMP_NUM_CAN];
50
SysbusAHCIState sata;
51
SDHCIState sdhci[XLNX_ZYNQMP_NUM_SDHCI];
52
XilinxSPIPS spi[XLNX_ZYNQMP_NUM_SPIS];
53
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
54
bool virt;
55
/* Has the RPU subsystem? */
56
bool has_rpu;
57
+
58
+ /* CAN bus. */
59
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
60
};
39
};
61
40
62
#endif
41
struct FslIMX6ULState {
63
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
42
@@ -XXX,XX +XXX,XX @@ struct FslIMX6ULState {
43
44
enum FslIMX6ULMemoryMap {
45
FSL_IMX6UL_MMDC_ADDR = 0x80000000,
46
- FSL_IMX6UL_MMDC_SIZE = 2 * 1024 * 1024 * 1024UL,
47
+ FSL_IMX6UL_MMDC_SIZE = (2 * GiB),
48
49
FSL_IMX6UL_QSPI1_MEM_ADDR = 0x60000000,
50
- FSL_IMX6UL_EIM_ALIAS_ADDR = 0x58000000,
51
- FSL_IMX6UL_EIM_CS_ADDR = 0x50000000,
52
- FSL_IMX6UL_AES_ENCRYPT_ADDR = 0x10000000,
53
- FSL_IMX6UL_QSPI1_RX_ADDR = 0x0C000000,
54
+ FSL_IMX6UL_QSPI1_MEM_SIZE = (256 * MiB),
55
56
- /* AIPS-2 */
57
+ FSL_IMX6UL_EIM_ALIAS_ADDR = 0x58000000,
58
+ FSL_IMX6UL_EIM_ALIAS_SIZE = (128 * MiB),
59
+
60
+ FSL_IMX6UL_EIM_CS_ADDR = 0x50000000,
61
+ FSL_IMX6UL_EIM_CS_SIZE = (128 * MiB),
62
+
63
+ FSL_IMX6UL_AES_ENCRYPT_ADDR = 0x10000000,
64
+ FSL_IMX6UL_AES_ENCRYPT_SIZE = (1 * MiB),
65
+
66
+ FSL_IMX6UL_QSPI1_RX_ADDR = 0x0C000000,
67
+ FSL_IMX6UL_QSPI1_RX_SIZE = (32 * MiB),
68
+
69
+ /* AIPS-2 Begin */
70
FSL_IMX6UL_UART6_ADDR = 0x021FC000,
71
+
72
FSL_IMX6UL_I2C4_ADDR = 0x021F8000,
73
+
74
FSL_IMX6UL_UART5_ADDR = 0x021F4000,
75
FSL_IMX6UL_UART4_ADDR = 0x021F0000,
76
FSL_IMX6UL_UART3_ADDR = 0x021EC000,
77
FSL_IMX6UL_UART2_ADDR = 0x021E8000,
78
+
79
FSL_IMX6UL_WDOG3_ADDR = 0x021E4000,
80
+
81
FSL_IMX6UL_QSPI_ADDR = 0x021E0000,
82
+ FSL_IMX6UL_QSPI_SIZE = 0x500,
83
+
84
FSL_IMX6UL_SYS_CNT_CTRL_ADDR = 0x021DC000,
85
+ FSL_IMX6UL_SYS_CNT_CTRL_SIZE = (16 * KiB),
86
+
87
FSL_IMX6UL_SYS_CNT_CMP_ADDR = 0x021D8000,
88
+ FSL_IMX6UL_SYS_CNT_CMP_SIZE = (16 * KiB),
89
+
90
FSL_IMX6UL_SYS_CNT_RD_ADDR = 0x021D4000,
91
+ FSL_IMX6UL_SYS_CNT_RD_SIZE = (16 * KiB),
92
+
93
FSL_IMX6UL_TZASC_ADDR = 0x021D0000,
94
+ FSL_IMX6UL_TZASC_SIZE = (16 * KiB),
95
+
96
FSL_IMX6UL_PXP_ADDR = 0x021CC000,
97
+ FSL_IMX6UL_PXP_SIZE = (16 * KiB),
98
+
99
FSL_IMX6UL_LCDIF_ADDR = 0x021C8000,
100
+ FSL_IMX6UL_LCDIF_SIZE = 0x100,
101
+
102
FSL_IMX6UL_CSI_ADDR = 0x021C4000,
103
+ FSL_IMX6UL_CSI_SIZE = 0x100,
104
+
105
FSL_IMX6UL_CSU_ADDR = 0x021C0000,
106
+ FSL_IMX6UL_CSU_SIZE = (16 * KiB),
107
+
108
FSL_IMX6UL_OCOTP_CTRL_ADDR = 0x021BC000,
109
+ FSL_IMX6UL_OCOTP_CTRL_SIZE = (4 * KiB),
110
+
111
FSL_IMX6UL_EIM_ADDR = 0x021B8000,
112
+ FSL_IMX6UL_EIM_SIZE = 0x100,
113
+
114
FSL_IMX6UL_SIM2_ADDR = 0x021B4000,
115
+
116
FSL_IMX6UL_MMDC_CFG_ADDR = 0x021B0000,
117
+ FSL_IMX6UL_MMDC_CFG_SIZE = (4 * KiB),
118
+
119
FSL_IMX6UL_ROMCP_ADDR = 0x021AC000,
120
+ FSL_IMX6UL_ROMCP_SIZE = 0x300,
121
+
122
FSL_IMX6UL_I2C3_ADDR = 0x021A8000,
123
FSL_IMX6UL_I2C2_ADDR = 0x021A4000,
124
FSL_IMX6UL_I2C1_ADDR = 0x021A0000,
125
+
126
FSL_IMX6UL_ADC2_ADDR = 0x0219C000,
127
FSL_IMX6UL_ADC1_ADDR = 0x02198000,
128
+ FSL_IMX6UL_ADCn_SIZE = 0x100,
129
+
130
FSL_IMX6UL_USDHC2_ADDR = 0x02194000,
131
FSL_IMX6UL_USDHC1_ADDR = 0x02190000,
132
- FSL_IMX6UL_SIM1_ADDR = 0x0218C000,
133
- FSL_IMX6UL_ENET1_ADDR = 0x02188000,
134
- FSL_IMX6UL_USBO2_USBMISC_ADDR = 0x02184800,
135
- FSL_IMX6UL_USBO2_USB_ADDR = 0x02184000,
136
- FSL_IMX6UL_USBO2_PL301_ADDR = 0x02180000,
137
- FSL_IMX6UL_AIPS2_CFG_ADDR = 0x0217C000,
138
- FSL_IMX6UL_CAAM_ADDR = 0x02140000,
139
- FSL_IMX6UL_A7MPCORE_DAP_ADDR = 0x02100000,
140
141
- /* AIPS-1 */
142
+ FSL_IMX6UL_SIM1_ADDR = 0x0218C000,
143
+ FSL_IMX6UL_SIMn_SIZE = (16 * KiB),
144
+
145
+ FSL_IMX6UL_ENET1_ADDR = 0x02188000,
146
+
147
+ FSL_IMX6UL_USBO2_USBMISC_ADDR = 0x02184800,
148
+ FSL_IMX6UL_USBO2_USB1_ADDR = 0x02184000,
149
+ FSL_IMX6UL_USBO2_USB2_ADDR = 0x02184200,
150
+
151
+ FSL_IMX6UL_USBO2_PL301_ADDR = 0x02180000,
152
+ FSL_IMX6UL_USBO2_PL301_SIZE = (16 * KiB),
153
+
154
+ FSL_IMX6UL_AIPS2_CFG_ADDR = 0x0217C000,
155
+ FSL_IMX6UL_AIPS2_CFG_SIZE = 0x100,
156
+
157
+ FSL_IMX6UL_CAAM_ADDR = 0x02140000,
158
+ FSL_IMX6UL_CAAM_SIZE = (16 * KiB),
159
+
160
+ FSL_IMX6UL_A7MPCORE_DAP_ADDR = 0x02100000,
161
+ FSL_IMX6UL_A7MPCORE_DAP_SIZE = (4 * KiB),
162
+ /* AIPS-2 End */
163
+
164
+ /* AIPS-1 Begin */
165
FSL_IMX6UL_PWM8_ADDR = 0x020FC000,
166
FSL_IMX6UL_PWM7_ADDR = 0x020F8000,
167
FSL_IMX6UL_PWM6_ADDR = 0x020F4000,
168
FSL_IMX6UL_PWM5_ADDR = 0x020F0000,
169
+
170
FSL_IMX6UL_SDMA_ADDR = 0x020EC000,
171
+ FSL_IMX6UL_SDMA_SIZE = 0x300,
172
+
173
FSL_IMX6UL_GPT2_ADDR = 0x020E8000,
174
+
175
FSL_IMX6UL_IOMUXC_GPR_ADDR = 0x020E4000,
176
+ FSL_IMX6UL_IOMUXC_GPR_SIZE = 0x40,
177
+
178
FSL_IMX6UL_IOMUXC_ADDR = 0x020E0000,
179
+ FSL_IMX6UL_IOMUXC_SIZE = 0x700,
180
+
181
FSL_IMX6UL_GPC_ADDR = 0x020DC000,
182
+
183
FSL_IMX6UL_SRC_ADDR = 0x020D8000,
184
+
185
FSL_IMX6UL_EPIT2_ADDR = 0x020D4000,
186
FSL_IMX6UL_EPIT1_ADDR = 0x020D0000,
187
+
188
FSL_IMX6UL_SNVS_HP_ADDR = 0x020CC000,
189
+
190
FSL_IMX6UL_USBPHY2_ADDR = 0x020CA000,
191
- FSL_IMX6UL_USBPHY2_SIZE = (4 * 1024),
192
FSL_IMX6UL_USBPHY1_ADDR = 0x020C9000,
193
- FSL_IMX6UL_USBPHY1_SIZE = (4 * 1024),
194
+
195
FSL_IMX6UL_ANALOG_ADDR = 0x020C8000,
196
+ FSL_IMX6UL_ANALOG_SIZE = 0x300,
197
+
198
FSL_IMX6UL_CCM_ADDR = 0x020C4000,
199
+
200
FSL_IMX6UL_WDOG2_ADDR = 0x020C0000,
201
FSL_IMX6UL_WDOG1_ADDR = 0x020BC000,
202
+
203
FSL_IMX6UL_KPP_ADDR = 0x020B8000,
204
+ FSL_IMX6UL_KPP_SIZE = 0x10,
205
+
206
FSL_IMX6UL_ENET2_ADDR = 0x020B4000,
207
+
208
FSL_IMX6UL_SNVS_LP_ADDR = 0x020B0000,
209
+ FSL_IMX6UL_SNVS_LP_SIZE = (16 * KiB),
210
+
211
FSL_IMX6UL_GPIO5_ADDR = 0x020AC000,
212
FSL_IMX6UL_GPIO4_ADDR = 0x020A8000,
213
FSL_IMX6UL_GPIO3_ADDR = 0x020A4000,
214
FSL_IMX6UL_GPIO2_ADDR = 0x020A0000,
215
FSL_IMX6UL_GPIO1_ADDR = 0x0209C000,
216
+
217
FSL_IMX6UL_GPT1_ADDR = 0x02098000,
218
+
219
FSL_IMX6UL_CAN2_ADDR = 0x02094000,
220
FSL_IMX6UL_CAN1_ADDR = 0x02090000,
221
+ FSL_IMX6UL_CANn_SIZE = (4 * KiB),
222
+
223
FSL_IMX6UL_PWM4_ADDR = 0x0208C000,
224
FSL_IMX6UL_PWM3_ADDR = 0x02088000,
225
FSL_IMX6UL_PWM2_ADDR = 0x02084000,
226
FSL_IMX6UL_PWM1_ADDR = 0x02080000,
227
+ FSL_IMX6UL_PWMn_SIZE = 0x20,
228
+
229
FSL_IMX6UL_AIPS1_CFG_ADDR = 0x0207C000,
230
+ FSL_IMX6UL_AIPS1_CFG_SIZE = (16 * KiB),
231
+
232
FSL_IMX6UL_BEE_ADDR = 0x02044000,
233
+ FSL_IMX6UL_BEE_SIZE = (16 * KiB),
234
+
235
FSL_IMX6UL_TOUCH_CTRL_ADDR = 0x02040000,
236
+ FSL_IMX6UL_TOUCH_CTRL_SIZE = 0x100,
237
+
238
FSL_IMX6UL_SPBA_ADDR = 0x0203C000,
239
+ FSL_IMX6UL_SPBA_SIZE = 0x100,
240
+
241
FSL_IMX6UL_ASRC_ADDR = 0x02034000,
242
+ FSL_IMX6UL_ASRC_SIZE = 0x100,
243
+
244
FSL_IMX6UL_SAI3_ADDR = 0x02030000,
245
FSL_IMX6UL_SAI2_ADDR = 0x0202C000,
246
FSL_IMX6UL_SAI1_ADDR = 0x02028000,
247
+ FSL_IMX6UL_SAIn_SIZE = 0x200,
248
+
249
FSL_IMX6UL_UART8_ADDR = 0x02024000,
250
FSL_IMX6UL_UART1_ADDR = 0x02020000,
251
FSL_IMX6UL_UART7_ADDR = 0x02018000,
252
+
253
FSL_IMX6UL_ECSPI4_ADDR = 0x02014000,
254
FSL_IMX6UL_ECSPI3_ADDR = 0x02010000,
255
FSL_IMX6UL_ECSPI2_ADDR = 0x0200C000,
256
FSL_IMX6UL_ECSPI1_ADDR = 0x02008000,
257
+
258
FSL_IMX6UL_SPDIF_ADDR = 0x02004000,
259
+ FSL_IMX6UL_SPDIF_SIZE = 0x100,
260
+ /* AIPS-1 End */
261
+
262
+ FSL_IMX6UL_BCH_ADDR = 0x01808000,
263
+ FSL_IMX6UL_BCH_SIZE = 0x200,
264
+
265
+ FSL_IMX6UL_GPMI_ADDR = 0x01806000,
266
+ FSL_IMX6UL_GPMI_SIZE = 0x200,
267
268
FSL_IMX6UL_APBH_DMA_ADDR = 0x01804000,
269
- FSL_IMX6UL_APBH_DMA_SIZE = (32 * 1024),
270
+ FSL_IMX6UL_APBH_DMA_SIZE = (4 * KiB),
271
272
FSL_IMX6UL_A7MPCORE_ADDR = 0x00A00000,
273
274
FSL_IMX6UL_OCRAM_ALIAS_ADDR = 0x00920000,
275
- FSL_IMX6UL_OCRAM_ALIAS_SIZE = 0x00060000,
276
+ FSL_IMX6UL_OCRAM_ALIAS_SIZE = (384 * KiB),
277
+
278
FSL_IMX6UL_OCRAM_MEM_ADDR = 0x00900000,
279
- FSL_IMX6UL_OCRAM_MEM_SIZE = 0x00020000,
280
+ FSL_IMX6UL_OCRAM_MEM_SIZE = (128 * KiB),
281
+
282
FSL_IMX6UL_CAAM_MEM_ADDR = 0x00100000,
283
- FSL_IMX6UL_CAAM_MEM_SIZE = 0x00008000,
284
+ FSL_IMX6UL_CAAM_MEM_SIZE = (32 * KiB),
285
+
286
FSL_IMX6UL_ROM_ADDR = 0x00000000,
287
- FSL_IMX6UL_ROM_SIZE = 0x00018000,
288
+ FSL_IMX6UL_ROM_SIZE = (96 * KiB),
289
};
290
291
enum FslIMX6ULIRQs {
292
diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
64
index XXXXXXX..XXXXXXX 100644
293
index XXXXXXX..XXXXXXX 100644
65
--- a/hw/arm/xlnx-zcu102.c
294
--- a/hw/arm/fsl-imx6ul.c
66
+++ b/hw/arm/xlnx-zcu102.c
295
+++ b/hw/arm/fsl-imx6ul.c
67
@@ -XXX,XX +XXX,XX @@
296
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_init(Object *obj)
68
#include "sysemu/qtest.h"
297
object_initialize_child(obj, "snvs", &s->snvs, TYPE_IMX7_SNVS);
69
#include "sysemu/device_tree.h"
298
70
#include "qom/object.h"
299
/*
71
+#include "net/can_emu.h"
300
- * GPIOs 1 to 5
72
301
+ * GPIOs
73
struct XlnxZCU102 {
302
*/
74
MachineState parent_obj;
303
for (i = 0; i < FSL_IMX6UL_NUM_GPIOS; i++) {
75
@@ -XXX,XX +XXX,XX @@ struct XlnxZCU102 {
304
snprintf(name, NAME_SIZE, "gpio%d", i);
76
bool secure;
305
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_init(Object *obj)
77
bool virt;
306
}
78
307
79
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
308
/*
80
+
309
- * GPT 1, 2
81
struct arm_boot_info binfo;
310
+ * GPTs
82
};
311
*/
83
typedef struct XlnxZCU102 XlnxZCU102;
312
for (i = 0; i < FSL_IMX6UL_NUM_GPTS; i++) {
84
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_init(MachineState *machine)
313
snprintf(name, NAME_SIZE, "gpt%d", i);
85
object_property_set_bool(OBJECT(&s->soc), "virtualization", s->virt,
314
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_init(Object *obj)
86
&error_fatal);
315
}
87
316
88
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
317
/*
89
+ gchar *bus_name = g_strdup_printf("canbus%d", i);
318
- * EPIT 1, 2
90
+
319
+ * EPITs
91
+ object_property_set_link(OBJECT(&s->soc), bus_name,
320
*/
92
+ OBJECT(s->canbus[i]), &error_fatal);
321
for (i = 0; i < FSL_IMX6UL_NUM_EPITS; i++) {
93
+ g_free(bus_name);
322
snprintf(name, NAME_SIZE, "epit%d", i + 1);
323
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_init(Object *obj)
324
}
325
326
/*
327
- * eCSPI
328
+ * eCSPIs
329
*/
330
for (i = 0; i < FSL_IMX6UL_NUM_ECSPIS; i++) {
331
snprintf(name, NAME_SIZE, "spi%d", i + 1);
332
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_init(Object *obj)
333
}
334
335
/*
336
- * I2C
337
+ * I2Cs
338
*/
339
for (i = 0; i < FSL_IMX6UL_NUM_I2CS; i++) {
340
snprintf(name, NAME_SIZE, "i2c%d", i + 1);
341
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_init(Object *obj)
342
}
343
344
/*
345
- * UART
346
+ * UARTs
347
*/
348
for (i = 0; i < FSL_IMX6UL_NUM_UARTS; i++) {
349
snprintf(name, NAME_SIZE, "uart%d", i);
350
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_init(Object *obj)
351
}
352
353
/*
354
- * Ethernet
355
+ * Ethernets
356
*/
357
for (i = 0; i < FSL_IMX6UL_NUM_ETHS; i++) {
358
snprintf(name, NAME_SIZE, "eth%d", i);
359
object_initialize_child(obj, name, &s->eth[i], TYPE_IMX_ENET);
360
}
361
362
- /* USB */
363
+ /*
364
+ * USB PHYs
365
+ */
366
for (i = 0; i < FSL_IMX6UL_NUM_USB_PHYS; i++) {
367
snprintf(name, NAME_SIZE, "usbphy%d", i);
368
object_initialize_child(obj, name, &s->usbphy[i], TYPE_IMX_USBPHY);
369
}
370
+
371
+ /*
372
+ * USBs
373
+ */
374
for (i = 0; i < FSL_IMX6UL_NUM_USBS; i++) {
375
snprintf(name, NAME_SIZE, "usb%d", i);
376
object_initialize_child(obj, name, &s->usb[i], TYPE_CHIPIDEA);
377
}
378
379
/*
380
- * SDHCI
381
+ * SDHCIs
382
*/
383
for (i = 0; i < FSL_IMX6UL_NUM_USDHCS; i++) {
384
snprintf(name, NAME_SIZE, "usdhc%d", i);
385
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_init(Object *obj)
386
}
387
388
/*
389
- * Watchdog
390
+ * Watchdogs
391
*/
392
for (i = 0; i < FSL_IMX6UL_NUM_WDTS; i++) {
393
snprintf(name, NAME_SIZE, "wdt%d", i);
394
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
395
* A7MPCORE DAP
396
*/
397
create_unimplemented_device("a7mpcore-dap", FSL_IMX6UL_A7MPCORE_DAP_ADDR,
398
- 0x100000);
399
+ FSL_IMX6UL_A7MPCORE_DAP_SIZE);
400
401
/*
402
- * GPT 1, 2
403
+ * GPTs
404
*/
405
for (i = 0; i < FSL_IMX6UL_NUM_GPTS; i++) {
406
static const hwaddr FSL_IMX6UL_GPTn_ADDR[FSL_IMX6UL_NUM_GPTS] = {
407
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
408
}
409
410
/*
411
- * EPIT 1, 2
412
+ * EPITs
413
*/
414
for (i = 0; i < FSL_IMX6UL_NUM_EPITS; i++) {
415
static const hwaddr FSL_IMX6UL_EPITn_ADDR[FSL_IMX6UL_NUM_EPITS] = {
416
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
417
}
418
419
/*
420
- * GPIO
421
+ * GPIOs
422
*/
423
for (i = 0; i < FSL_IMX6UL_NUM_GPIOS; i++) {
424
static const hwaddr FSL_IMX6UL_GPIOn_ADDR[FSL_IMX6UL_NUM_GPIOS] = {
425
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
426
}
427
428
/*
429
- * IOMUXC and IOMUXC_GPR
430
+ * IOMUXC
431
*/
432
- for (i = 0; i < 1; i++) {
433
- static const hwaddr FSL_IMX6UL_IOMUXCn_ADDR[FSL_IMX6UL_NUM_IOMUXCS] = {
434
- FSL_IMX6UL_IOMUXC_ADDR,
435
- FSL_IMX6UL_IOMUXC_GPR_ADDR,
436
- };
437
-
438
- snprintf(name, NAME_SIZE, "iomuxc%d", i);
439
- create_unimplemented_device(name, FSL_IMX6UL_IOMUXCn_ADDR[i], 0x4000);
440
- }
441
+ create_unimplemented_device("iomuxc", FSL_IMX6UL_IOMUXC_ADDR,
442
+ FSL_IMX6UL_IOMUXC_SIZE);
443
+ create_unimplemented_device("iomuxc_gpr", FSL_IMX6UL_IOMUXC_GPR_ADDR,
444
+ FSL_IMX6UL_IOMUXC_GPR_SIZE);
445
446
/*
447
* CCM
448
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
449
sysbus_realize(SYS_BUS_DEVICE(&s->gpcv2), &error_abort);
450
sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpcv2), 0, FSL_IMX6UL_GPC_ADDR);
451
452
- /* Initialize all ECSPI */
453
+ /*
454
+ * ECSPIs
455
+ */
456
for (i = 0; i < FSL_IMX6UL_NUM_ECSPIS; i++) {
457
static const hwaddr FSL_IMX6UL_SPIn_ADDR[FSL_IMX6UL_NUM_ECSPIS] = {
458
FSL_IMX6UL_ECSPI1_ADDR,
459
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
460
}
461
462
/*
463
- * I2C
464
+ * I2Cs
465
*/
466
for (i = 0; i < FSL_IMX6UL_NUM_I2CS; i++) {
467
static const hwaddr FSL_IMX6UL_I2Cn_ADDR[FSL_IMX6UL_NUM_I2CS] = {
468
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
469
}
470
471
/*
472
- * UART
473
+ * UARTs
474
*/
475
for (i = 0; i < FSL_IMX6UL_NUM_UARTS; i++) {
476
static const hwaddr FSL_IMX6UL_UARTn_ADDR[FSL_IMX6UL_NUM_UARTS] = {
477
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
478
}
479
480
/*
481
- * Ethernet
482
+ * Ethernets
483
*
484
* We must use two loops since phy_connected affects the other interface
485
* and we have to set all properties before calling sysbus_realize().
486
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
487
FSL_IMX6UL_ENETn_TIMER_IRQ[i]));
488
}
489
490
- /* USB */
491
+ /*
492
+ * USB PHYs
493
+ */
494
for (i = 0; i < FSL_IMX6UL_NUM_USB_PHYS; i++) {
495
+ static const hwaddr
496
+ FSL_IMX6UL_USB_PHYn_ADDR[FSL_IMX6UL_NUM_USB_PHYS] = {
497
+ FSL_IMX6UL_USBPHY1_ADDR,
498
+ FSL_IMX6UL_USBPHY2_ADDR,
499
+ };
500
+
501
sysbus_realize(SYS_BUS_DEVICE(&s->usbphy[i]), &error_abort);
502
sysbus_mmio_map(SYS_BUS_DEVICE(&s->usbphy[i]), 0,
503
- FSL_IMX6UL_USBPHY1_ADDR + i * 0x1000);
504
+ FSL_IMX6UL_USB_PHYn_ADDR[i]);
505
}
506
507
+ /*
508
+ * USBs
509
+ */
510
for (i = 0; i < FSL_IMX6UL_NUM_USBS; i++) {
511
+ static const hwaddr FSL_IMX6UL_USB02_USBn_ADDR[FSL_IMX6UL_NUM_USBS] = {
512
+ FSL_IMX6UL_USBO2_USB1_ADDR,
513
+ FSL_IMX6UL_USBO2_USB2_ADDR,
514
+ };
515
+
516
static const int FSL_IMX6UL_USBn_IRQ[] = {
517
FSL_IMX6UL_USB1_IRQ,
518
FSL_IMX6UL_USB2_IRQ,
519
};
520
+
521
sysbus_realize(SYS_BUS_DEVICE(&s->usb[i]), &error_abort);
522
sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0,
523
- FSL_IMX6UL_USBO2_USB_ADDR + i * 0x200);
524
+ FSL_IMX6UL_USB02_USBn_ADDR[i]);
525
sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i]), 0,
526
qdev_get_gpio_in(DEVICE(&s->a7mpcore),
527
FSL_IMX6UL_USBn_IRQ[i]));
528
}
529
530
/*
531
- * USDHC
532
+ * USDHCs
533
*/
534
for (i = 0; i < FSL_IMX6UL_NUM_USDHCS; i++) {
535
static const hwaddr FSL_IMX6UL_USDHCn_ADDR[FSL_IMX6UL_NUM_USDHCS] = {
536
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
537
sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0, FSL_IMX6UL_SNVS_HP_ADDR);
538
539
/*
540
- * Watchdog
541
+ * Watchdogs
542
*/
543
for (i = 0; i < FSL_IMX6UL_NUM_WDTS; i++) {
544
static const hwaddr FSL_IMX6UL_WDOGn_ADDR[FSL_IMX6UL_NUM_WDTS] = {
545
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
546
FSL_IMX6UL_WDOG2_ADDR,
547
FSL_IMX6UL_WDOG3_ADDR,
548
};
549
+
550
static const int FSL_IMX6UL_WDOGn_IRQ[FSL_IMX6UL_NUM_WDTS] = {
551
FSL_IMX6UL_WDOG1_IRQ,
552
FSL_IMX6UL_WDOG2_IRQ,
553
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
554
/*
555
* SDMA
556
*/
557
- create_unimplemented_device("sdma", FSL_IMX6UL_SDMA_ADDR, 0x4000);
558
+ create_unimplemented_device("sdma", FSL_IMX6UL_SDMA_ADDR,
559
+ FSL_IMX6UL_SDMA_SIZE);
560
561
/*
562
- * SAI (Audio SSI (Synchronous Serial Interface))
563
+ * SAIs (Audio SSI (Synchronous Serial Interface))
564
*/
565
- create_unimplemented_device("sai1", FSL_IMX6UL_SAI1_ADDR, 0x4000);
566
- create_unimplemented_device("sai2", FSL_IMX6UL_SAI2_ADDR, 0x4000);
567
- create_unimplemented_device("sai3", FSL_IMX6UL_SAI3_ADDR, 0x4000);
568
+ for (i = 0; i < FSL_IMX6UL_NUM_SAIS; i++) {
569
+ static const hwaddr FSL_IMX6UL_SAIn_ADDR[FSL_IMX6UL_NUM_SAIS] = {
570
+ FSL_IMX6UL_SAI1_ADDR,
571
+ FSL_IMX6UL_SAI2_ADDR,
572
+ FSL_IMX6UL_SAI3_ADDR,
573
+ };
574
+
575
+ snprintf(name, NAME_SIZE, "sai%d", i);
576
+ create_unimplemented_device(name, FSL_IMX6UL_SAIn_ADDR[i],
577
+ FSL_IMX6UL_SAIn_SIZE);
94
+ }
578
+ }
95
+
579
96
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
580
/*
97
581
- * PWM
98
/* Create and plug in the SD cards */
582
+ * PWMs
99
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_machine_instance_init(Object *obj)
583
*/
100
"Set on/off to enable/disable emulating a "
584
- create_unimplemented_device("pwm1", FSL_IMX6UL_PWM1_ADDR, 0x4000);
101
"guest CPU which implements the ARM "
585
- create_unimplemented_device("pwm2", FSL_IMX6UL_PWM2_ADDR, 0x4000);
102
"Virtualization Extensions");
586
- create_unimplemented_device("pwm3", FSL_IMX6UL_PWM3_ADDR, 0x4000);
103
+ object_property_add_link(obj, "xlnx-zcu102.canbus0", TYPE_CAN_BUS,
587
- create_unimplemented_device("pwm4", FSL_IMX6UL_PWM4_ADDR, 0x4000);
104
+ (Object **)&s->canbus[0],
588
+ for (i = 0; i < FSL_IMX6UL_NUM_PWMS; i++) {
105
+ object_property_allow_set_link,
589
+ static const hwaddr FSL_IMX6UL_PWMn_ADDR[FSL_IMX6UL_NUM_PWMS] = {
106
+ 0);
590
+ FSL_IMX6UL_PWM1_ADDR,
107
+
591
+ FSL_IMX6UL_PWM2_ADDR,
108
+ object_property_add_link(obj, "xlnx-zcu102.canbus1", TYPE_CAN_BUS,
592
+ FSL_IMX6UL_PWM3_ADDR,
109
+ (Object **)&s->canbus[1],
593
+ FSL_IMX6UL_PWM4_ADDR,
110
+ object_property_allow_set_link,
594
+ };
111
+ 0);
595
+
112
}
596
+ snprintf(name, NAME_SIZE, "pwm%d", i);
113
597
+ create_unimplemented_device(name, FSL_IMX6UL_PWMn_ADDR[i],
114
static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data)
598
+ FSL_IMX6UL_PWMn_SIZE);
115
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
116
index XXXXXXX..XXXXXXX 100644
117
--- a/hw/arm/xlnx-zynqmp.c
118
+++ b/hw/arm/xlnx-zynqmp.c
119
@@ -XXX,XX +XXX,XX @@ static const int uart_intr[XLNX_ZYNQMP_NUM_UARTS] = {
120
21, 22,
121
};
122
123
+static const uint64_t can_addr[XLNX_ZYNQMP_NUM_CAN] = {
124
+ 0xFF060000, 0xFF070000,
125
+};
126
+
127
+static const int can_intr[XLNX_ZYNQMP_NUM_CAN] = {
128
+ 23, 24,
129
+};
130
+
131
static const uint64_t sdhci_addr[XLNX_ZYNQMP_NUM_SDHCI] = {
132
0xFF160000, 0xFF170000,
133
};
134
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj)
135
TYPE_CADENCE_UART);
136
}
137
138
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
139
+ object_initialize_child(obj, "can[*]", &s->can[i],
140
+ TYPE_XLNX_ZYNQMP_CAN);
141
+ }
599
+ }
142
+
600
143
object_initialize_child(obj, "sata", &s->sata, TYPE_SYSBUS_AHCI);
601
/*
144
602
* Audio ASRC (asynchronous sample rate converter)
145
for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
603
*/
146
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
604
- create_unimplemented_device("asrc", FSL_IMX6UL_ASRC_ADDR, 0x4000);
147
gic_spi[uart_intr[i]]);
605
+ create_unimplemented_device("asrc", FSL_IMX6UL_ASRC_ADDR,
148
}
606
+ FSL_IMX6UL_ASRC_SIZE);
149
607
150
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
608
/*
151
+ object_property_set_int(OBJECT(&s->can[i]), "ext_clk_freq",
609
- * CAN
152
+ XLNX_ZYNQMP_CAN_REF_CLK, &error_abort);
610
+ * CANs
153
+
611
*/
154
+ object_property_set_link(OBJECT(&s->can[i]), "canbus",
612
- create_unimplemented_device("can1", FSL_IMX6UL_CAN1_ADDR, 0x4000);
155
+ OBJECT(s->canbus[i]), &error_fatal);
613
- create_unimplemented_device("can2", FSL_IMX6UL_CAN2_ADDR, 0x4000);
156
+
614
+ for (i = 0; i < FSL_IMX6UL_NUM_CANS; i++) {
157
+ sysbus_realize(SYS_BUS_DEVICE(&s->can[i]), &err);
615
+ static const hwaddr FSL_IMX6UL_CANn_ADDR[FSL_IMX6UL_NUM_CANS] = {
158
+ if (err) {
616
+ FSL_IMX6UL_CAN1_ADDR,
159
+ error_propagate(errp, err);
617
+ FSL_IMX6UL_CAN2_ADDR,
160
+ return;
618
+ };
161
+ }
619
+
162
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->can[i]), 0, can_addr[i]);
620
+ snprintf(name, NAME_SIZE, "can%d", i);
163
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->can[i]), 0,
621
+ create_unimplemented_device(name, FSL_IMX6UL_CANn_ADDR[i],
164
+ gic_spi[can_intr[i]]);
622
+ FSL_IMX6UL_CANn_SIZE);
165
+ }
623
+ }
166
+
624
167
object_property_set_int(OBJECT(&s->sata), "num-ports", SATA_NUM_PORTS,
625
/*
168
&error_abort);
626
* APHB_DMA
169
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sata), errp)) {
627
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
170
@@ -XXX,XX +XXX,XX @@ static Property xlnx_zynqmp_props[] = {
628
};
171
DEFINE_PROP_BOOL("has_rpu", XlnxZynqMPState, has_rpu, false),
629
172
DEFINE_PROP_LINK("ddr-ram", XlnxZynqMPState, ddr_ram, TYPE_MEMORY_REGION,
630
snprintf(name, NAME_SIZE, "adc%d", i);
173
MemoryRegion *),
631
- create_unimplemented_device(name, FSL_IMX6UL_ADCn_ADDR[i], 0x4000);
174
+ DEFINE_PROP_LINK("canbus0", XlnxZynqMPState, canbus[0], TYPE_CAN_BUS,
632
+ create_unimplemented_device(name, FSL_IMX6UL_ADCn_ADDR[i],
175
+ CanBusState *),
633
+ FSL_IMX6UL_ADCn_SIZE);
176
+ DEFINE_PROP_LINK("canbus1", XlnxZynqMPState, canbus[1], TYPE_CAN_BUS,
634
}
177
+ CanBusState *),
635
178
DEFINE_PROP_END_OF_LIST()
636
/*
179
};
637
* LCD
180
638
*/
639
- create_unimplemented_device("lcdif", FSL_IMX6UL_LCDIF_ADDR, 0x4000);
640
+ create_unimplemented_device("lcdif", FSL_IMX6UL_LCDIF_ADDR,
641
+ FSL_IMX6UL_LCDIF_SIZE);
642
643
/*
644
* ROM memory
181
--
645
--
182
2.20.1
646
2.34.1
183
184
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Jean-Christophe Dubois <jcd@tribudubois.net>
2
2
3
This implements a device model for the NPCM7xx SPI flash controller.
3
* Add TZASC as unimplemented device.
4
- Allow bare metal application to access this (unimplemented) device
5
* Add CSU as unimplemented device.
6
- Allow bare metal application to access this (unimplemented) device
7
* Add 4 missing PWM devices
4
8
5
Direct reads and writes, and user-mode transactions have been tested in
9
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
6
various modes. Protection features are not implemented yet.
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
11
Message-id: 59e4dc56e14eccfefd379275ec19048dff9c10b3.1692964892.git.jcd@tribudubois.net
8
All the FIU instances are available in the SoC's address space,
9
regardless of whether or not they're connected to actual flash chips.
10
11
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
12
Reviewed-by: Cédric Le Goater <clg@kaod.org>
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Tested-by: Alexander Bulekov <alxndr@bu.edu>
16
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
17
Message-id: 20200911052101.2602693-11-hskinnemoen@google.com
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
13
---
20
include/hw/arm/npcm7xx.h | 2 +
14
include/hw/arm/fsl-imx6ul.h | 2 +-
21
include/hw/ssi/npcm7xx_fiu.h | 73 +++++
15
hw/arm/fsl-imx6ul.c | 16 ++++++++++++++++
22
hw/arm/npcm7xx.c | 58 ++++
16
2 files changed, 17 insertions(+), 1 deletion(-)
23
hw/ssi/npcm7xx_fiu.c | 572 +++++++++++++++++++++++++++++++++++
24
hw/arm/Kconfig | 1 +
25
hw/ssi/meson.build | 1 +
26
hw/ssi/trace-events | 11 +
27
7 files changed, 718 insertions(+)
28
create mode 100644 include/hw/ssi/npcm7xx_fiu.h
29
create mode 100644 hw/ssi/npcm7xx_fiu.c
30
17
31
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
18
diff --git a/include/hw/arm/fsl-imx6ul.h b/include/hw/arm/fsl-imx6ul.h
32
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
33
--- a/include/hw/arm/npcm7xx.h
20
--- a/include/hw/arm/fsl-imx6ul.h
34
+++ b/include/hw/arm/npcm7xx.h
21
+++ b/include/hw/arm/fsl-imx6ul.h
35
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ enum FslIMX6ULConfiguration {
36
#include "hw/misc/npcm7xx_gcr.h"
23
FSL_IMX6UL_NUM_USBS = 2,
37
#include "hw/nvram/npcm7xx_otp.h"
24
FSL_IMX6UL_NUM_SAIS = 3,
38
#include "hw/timer/npcm7xx_timer.h"
25
FSL_IMX6UL_NUM_CANS = 2,
39
+#include "hw/ssi/npcm7xx_fiu.h"
26
- FSL_IMX6UL_NUM_PWMS = 4,
40
#include "target/arm/cpu.h"
27
+ FSL_IMX6UL_NUM_PWMS = 8,
41
28
};
42
#define NPCM7XX_MAX_NUM_CPUS (2)
29
43
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
30
struct FslIMX6ULState {
44
NPCM7xxOTPState key_storage;
31
diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
45
NPCM7xxOTPState fuse_array;
46
NPCM7xxMCState mc;
47
+ NPCM7xxFIUState fiu[2];
48
} NPCM7xxState;
49
50
#define TYPE_NPCM7XX "npcm7xx"
51
diff --git a/include/hw/ssi/npcm7xx_fiu.h b/include/hw/ssi/npcm7xx_fiu.h
52
new file mode 100644
53
index XXXXXXX..XXXXXXX
54
--- /dev/null
55
+++ b/include/hw/ssi/npcm7xx_fiu.h
56
@@ -XXX,XX +XXX,XX @@
57
+/*
58
+ * Nuvoton NPCM7xx Flash Interface Unit (FIU)
59
+ *
60
+ * Copyright 2020 Google LLC
61
+ *
62
+ * This program is free software; you can redistribute it and/or modify it
63
+ * under the terms of the GNU General Public License as published by the
64
+ * Free Software Foundation; either version 2 of the License, or
65
+ * (at your option) any later version.
66
+ *
67
+ * This program is distributed in the hope that it will be useful, but WITHOUT
68
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
69
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
70
+ * for more details.
71
+ */
72
+#ifndef NPCM7XX_FIU_H
73
+#define NPCM7XX_FIU_H
74
+
75
+#include "hw/ssi/ssi.h"
76
+#include "hw/sysbus.h"
77
+
78
+/*
79
+ * Number of registers in our device state structure. Don't change this without
80
+ * incrementing the version_id in the vmstate.
81
+ */
82
+#define NPCM7XX_FIU_NR_REGS (0x7c / sizeof(uint32_t))
83
+
84
+typedef struct NPCM7xxFIUState NPCM7xxFIUState;
85
+
86
+/**
87
+ * struct NPCM7xxFIUFlash - Per-chipselect flash controller state.
88
+ * @direct_access: Memory region for direct flash access.
89
+ * @fiu: Pointer to flash controller shared state.
90
+ */
91
+typedef struct NPCM7xxFIUFlash {
92
+ MemoryRegion direct_access;
93
+ NPCM7xxFIUState *fiu;
94
+} NPCM7xxFIUFlash;
95
+
96
+/**
97
+ * NPCM7xxFIUState - Device state for one Flash Interface Unit.
98
+ * @parent: System bus device.
99
+ * @mmio: Memory region for register access.
100
+ * @cs_count: Number of flash chips that may be connected to this module.
101
+ * @active_cs: Currently active chip select, or -1 if no chip is selected.
102
+ * @cs_lines: GPIO lines that may be wired to flash chips.
103
+ * @flash: Array of @cs_count per-flash-chip state objects.
104
+ * @spi: The SPI bus mastered by this controller.
105
+ * @regs: Register contents.
106
+ *
107
+ * Each FIU has a shared bank of registers, and controls up to four chip
108
+ * selects. Each chip select has a dedicated memory region which may be used to
109
+ * read and write the flash connected to that chip select as if it were memory.
110
+ */
111
+struct NPCM7xxFIUState {
112
+ SysBusDevice parent;
113
+
114
+ MemoryRegion mmio;
115
+
116
+ int32_t cs_count;
117
+ int32_t active_cs;
118
+ qemu_irq *cs_lines;
119
+ NPCM7xxFIUFlash *flash;
120
+
121
+ SSIBus *spi;
122
+
123
+ uint32_t regs[NPCM7XX_FIU_NR_REGS];
124
+};
125
+
126
+#define TYPE_NPCM7XX_FIU "npcm7xx-fiu"
127
+#define NPCM7XX_FIU(obj) OBJECT_CHECK(NPCM7xxFIUState, (obj), TYPE_NPCM7XX_FIU)
128
+
129
+#endif /* NPCM7XX_FIU_H */
130
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
131
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
132
--- a/hw/arm/npcm7xx.c
33
--- a/hw/arm/fsl-imx6ul.c
133
+++ b/hw/arm/npcm7xx.c
34
+++ b/hw/arm/fsl-imx6ul.c
134
@@ -XXX,XX +XXX,XX @@ static const hwaddr npcm7xx_uart_addr[] = {
35
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
135
0xf0004000,
36
FSL_IMX6UL_PWM2_ADDR,
136
};
37
FSL_IMX6UL_PWM3_ADDR,
137
38
FSL_IMX6UL_PWM4_ADDR,
138
+/* Direct memory-mapped access to SPI0 CS0-1. */
39
+ FSL_IMX6UL_PWM5_ADDR,
139
+static const hwaddr npcm7xx_fiu0_flash_addr[] = {
40
+ FSL_IMX6UL_PWM6_ADDR,
140
+ 0x80000000, /* CS0 */
41
+ FSL_IMX6UL_PWM7_ADDR,
141
+ 0x88000000, /* CS1 */
42
+ FSL_IMX6UL_PWM8_ADDR,
142
+};
43
};
143
+
44
144
+/* Direct memory-mapped access to SPI3 CS0-3. */
45
snprintf(name, NAME_SIZE, "pwm%d", i);
145
+static const hwaddr npcm7xx_fiu3_flash_addr[] = {
46
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
146
+ 0xa0000000, /* CS0 */
47
create_unimplemented_device("lcdif", FSL_IMX6UL_LCDIF_ADDR,
147
+ 0xa8000000, /* CS1 */
48
FSL_IMX6UL_LCDIF_SIZE);
148
+ 0xb0000000, /* CS2 */
149
+ 0xb8000000, /* CS3 */
150
+};
151
+
152
+static const struct {
153
+ const char *name;
154
+ hwaddr regs_addr;
155
+ int cs_count;
156
+ const hwaddr *flash_addr;
157
+} npcm7xx_fiu[] = {
158
+ {
159
+ .name = "fiu0",
160
+ .regs_addr = 0xfb000000,
161
+ .cs_count = ARRAY_SIZE(npcm7xx_fiu0_flash_addr),
162
+ .flash_addr = npcm7xx_fiu0_flash_addr,
163
+ }, {
164
+ .name = "fiu3",
165
+ .regs_addr = 0xc0000000,
166
+ .cs_count = ARRAY_SIZE(npcm7xx_fiu3_flash_addr),
167
+ .flash_addr = npcm7xx_fiu3_flash_addr,
168
+ },
169
+};
170
+
171
static void npcm7xx_write_secondary_boot(ARMCPU *cpu,
172
const struct arm_boot_info *info)
173
{
174
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
175
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
176
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
177
}
178
+
179
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu));
180
+ for (i = 0; i < ARRAY_SIZE(s->fiu); i++) {
181
+ object_initialize_child(obj, npcm7xx_fiu[i].name, &s->fiu[i],
182
+ TYPE_NPCM7XX_FIU);
183
+ }
184
}
185
186
static void npcm7xx_realize(DeviceState *dev, Error **errp)
187
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
188
serial_hd(i), DEVICE_LITTLE_ENDIAN);
189
}
190
49
191
+ /*
50
+ /*
192
+ * Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
51
+ * CSU
193
+ * specified, but this is a programming error.
194
+ */
52
+ */
195
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu));
53
+ create_unimplemented_device("csu", FSL_IMX6UL_CSU_ADDR,
196
+ for (i = 0; i < ARRAY_SIZE(s->fiu); i++) {
54
+ FSL_IMX6UL_CSU_SIZE);
197
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->fiu[i]);
198
+ int j;
199
+
200
+ object_property_set_int(OBJECT(sbd), "cs-count",
201
+ npcm7xx_fiu[i].cs_count, &error_abort);
202
+ sysbus_realize(sbd, &error_abort);
203
+
204
+ sysbus_mmio_map(sbd, 0, npcm7xx_fiu[i].regs_addr);
205
+ for (j = 0; j < npcm7xx_fiu[i].cs_count; j++) {
206
+ sysbus_mmio_map(sbd, j + 1, npcm7xx_fiu[i].flash_addr[j]);
207
+ }
208
+ }
209
+
210
/* RAM2 (SRAM) */
211
memory_region_init_ram(&s->sram, OBJECT(dev), "ram2",
212
NPCM7XX_RAM2_SZ, &error_abort);
213
diff --git a/hw/ssi/npcm7xx_fiu.c b/hw/ssi/npcm7xx_fiu.c
214
new file mode 100644
215
index XXXXXXX..XXXXXXX
216
--- /dev/null
217
+++ b/hw/ssi/npcm7xx_fiu.c
218
@@ -XXX,XX +XXX,XX @@
219
+/*
220
+ * Nuvoton NPCM7xx Flash Interface Unit (FIU)
221
+ *
222
+ * Copyright 2020 Google LLC
223
+ *
224
+ * This program is free software; you can redistribute it and/or modify it
225
+ * under the terms of the GNU General Public License as published by the
226
+ * Free Software Foundation; either version 2 of the License, or
227
+ * (at your option) any later version.
228
+ *
229
+ * This program is distributed in the hope that it will be useful, but WITHOUT
230
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
231
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
232
+ * for more details.
233
+ */
234
+
235
+#include "qemu/osdep.h"
236
+
237
+#include "hw/irq.h"
238
+#include "hw/qdev-properties.h"
239
+#include "hw/ssi/npcm7xx_fiu.h"
240
+#include "migration/vmstate.h"
241
+#include "qapi/error.h"
242
+#include "qemu/error-report.h"
243
+#include "qemu/log.h"
244
+#include "qemu/module.h"
245
+#include "qemu/units.h"
246
+
247
+#include "trace.h"
248
+
249
+/* Up to 128 MiB of flash may be accessed directly as memory. */
250
+#define NPCM7XX_FIU_FLASH_WINDOW_SIZE (128 * MiB)
251
+
252
+/* Each module has 4 KiB of register space. Only a fraction of it is used. */
253
+#define NPCM7XX_FIU_CTRL_REGS_SIZE (4 * KiB)
254
+
255
+/* 32-bit FIU register indices. */
256
+enum NPCM7xxFIURegister {
257
+ NPCM7XX_FIU_DRD_CFG,
258
+ NPCM7XX_FIU_DWR_CFG,
259
+ NPCM7XX_FIU_UMA_CFG,
260
+ NPCM7XX_FIU_UMA_CTS,
261
+ NPCM7XX_FIU_UMA_CMD,
262
+ NPCM7XX_FIU_UMA_ADDR,
263
+ NPCM7XX_FIU_PRT_CFG,
264
+ NPCM7XX_FIU_UMA_DW0 = 0x0020 / sizeof(uint32_t),
265
+ NPCM7XX_FIU_UMA_DW1,
266
+ NPCM7XX_FIU_UMA_DW2,
267
+ NPCM7XX_FIU_UMA_DW3,
268
+ NPCM7XX_FIU_UMA_DR0,
269
+ NPCM7XX_FIU_UMA_DR1,
270
+ NPCM7XX_FIU_UMA_DR2,
271
+ NPCM7XX_FIU_UMA_DR3,
272
+ NPCM7XX_FIU_PRT_CMD0,
273
+ NPCM7XX_FIU_PRT_CMD1,
274
+ NPCM7XX_FIU_PRT_CMD2,
275
+ NPCM7XX_FIU_PRT_CMD3,
276
+ NPCM7XX_FIU_PRT_CMD4,
277
+ NPCM7XX_FIU_PRT_CMD5,
278
+ NPCM7XX_FIU_PRT_CMD6,
279
+ NPCM7XX_FIU_PRT_CMD7,
280
+ NPCM7XX_FIU_PRT_CMD8,
281
+ NPCM7XX_FIU_PRT_CMD9,
282
+ NPCM7XX_FIU_CFG = 0x78 / sizeof(uint32_t),
283
+ NPCM7XX_FIU_REGS_END,
284
+};
285
+
286
+/* FIU_{DRD,DWR,UMA,PTR}_CFG cannot be written when this bit is set. */
287
+#define NPCM7XX_FIU_CFG_LCK BIT(31)
288
+
289
+/* Direct Read configuration register fields. */
290
+#define FIU_DRD_CFG_ADDSIZ(rv) extract32(rv, 16, 2)
291
+#define FIU_ADDSIZ_3BYTES 0
292
+#define FIU_ADDSIZ_4BYTES 1
293
+#define FIU_DRD_CFG_DBW(rv) extract32(rv, 12, 2)
294
+#define FIU_DRD_CFG_ACCTYPE(rv) extract32(rv, 8, 2)
295
+#define FIU_DRD_CFG_RDCMD(rv) extract32(rv, 0, 8)
296
+
297
+/* Direct Write configuration register fields. */
298
+#define FIU_DWR_CFG_ADDSIZ(rv) extract32(rv, 16, 2)
299
+#define FIU_DWR_CFG_WRCMD(rv) extract32(rv, 0, 8)
300
+
301
+/* User-Mode Access register fields. */
302
+
303
+/* Command Mode Lock and the bits protected by it. */
304
+#define FIU_UMA_CFG_CMMLCK BIT(30)
305
+#define FIU_UMA_CFG_CMMLCK_MASK 0x00000403
306
+
307
+#define FIU_UMA_CFG_RDATSIZ(rv) extract32(rv, 24, 5)
308
+#define FIU_UMA_CFG_DBSIZ(rv) extract32(rv, 21, 3)
309
+#define FIU_UMA_CFG_WDATSIZ(rv) extract32(rv, 16, 5)
310
+#define FIU_UMA_CFG_ADDSIZ(rv) extract32(rv, 11, 3)
311
+#define FIU_UMA_CFG_CMDSIZ(rv) extract32(rv, 10, 1)
312
+#define FIU_UMA_CFG_DBPCK(rv) extract32(rv, 6, 2)
313
+
314
+#define FIU_UMA_CTS_RDYIE BIT(25)
315
+#define FIU_UMA_CTS_RDYST BIT(24)
316
+#define FIU_UMA_CTS_SW_CS BIT(16)
317
+#define FIU_UMA_CTS_DEV_NUM(rv) extract32(rv, 8, 2)
318
+#define FIU_UMA_CTS_EXEC_DONE BIT(0)
319
+
320
+/*
321
+ * Returns the index of flash in the fiu->flash array. This corresponds to the
322
+ * chip select ID of the flash.
323
+ */
324
+static int npcm7xx_fiu_cs_index(NPCM7xxFIUState *fiu, NPCM7xxFIUFlash *flash)
325
+{
326
+ int index = flash - fiu->flash;
327
+
328
+ g_assert(index >= 0 && index < fiu->cs_count);
329
+
330
+ return index;
331
+}
332
+
333
+/* Assert the chip select specified in the UMA Control/Status Register. */
334
+static void npcm7xx_fiu_select(NPCM7xxFIUState *s, int cs_id)
335
+{
336
+ trace_npcm7xx_fiu_select(DEVICE(s)->canonical_path, cs_id);
337
+
338
+ if (cs_id < s->cs_count) {
339
+ qemu_irq_lower(s->cs_lines[cs_id]);
340
+ } else {
341
+ qemu_log_mask(LOG_GUEST_ERROR,
342
+ "%s: UMA to CS%d; this module has only %d chip selects",
343
+ DEVICE(s)->canonical_path, cs_id, s->cs_count);
344
+ cs_id = -1;
345
+ }
346
+
347
+ s->active_cs = cs_id;
348
+}
349
+
350
+/* Deassert the currently active chip select. */
351
+static void npcm7xx_fiu_deselect(NPCM7xxFIUState *s)
352
+{
353
+ if (s->active_cs < 0) {
354
+ return;
355
+ }
356
+
357
+ trace_npcm7xx_fiu_deselect(DEVICE(s)->canonical_path, s->active_cs);
358
+
359
+ qemu_irq_raise(s->cs_lines[s->active_cs]);
360
+ s->active_cs = -1;
361
+}
362
+
363
+/* Direct flash memory read handler. */
364
+static uint64_t npcm7xx_fiu_flash_read(void *opaque, hwaddr addr,
365
+ unsigned int size)
366
+{
367
+ NPCM7xxFIUFlash *f = opaque;
368
+ NPCM7xxFIUState *fiu = f->fiu;
369
+ uint64_t value = 0;
370
+ uint32_t drd_cfg;
371
+ int dummy_cycles;
372
+ int i;
373
+
374
+ if (fiu->active_cs != -1) {
375
+ qemu_log_mask(LOG_GUEST_ERROR,
376
+ "%s: direct flash read with CS%d already active",
377
+ DEVICE(fiu)->canonical_path, fiu->active_cs);
378
+ }
379
+
380
+ npcm7xx_fiu_select(fiu, npcm7xx_fiu_cs_index(fiu, f));
381
+
382
+ drd_cfg = fiu->regs[NPCM7XX_FIU_DRD_CFG];
383
+ ssi_transfer(fiu->spi, FIU_DRD_CFG_RDCMD(drd_cfg));
384
+
385
+ switch (FIU_DRD_CFG_ADDSIZ(drd_cfg)) {
386
+ case FIU_ADDSIZ_4BYTES:
387
+ ssi_transfer(fiu->spi, extract32(addr, 24, 8));
388
+ /* fall through */
389
+ case FIU_ADDSIZ_3BYTES:
390
+ ssi_transfer(fiu->spi, extract32(addr, 16, 8));
391
+ ssi_transfer(fiu->spi, extract32(addr, 8, 8));
392
+ ssi_transfer(fiu->spi, extract32(addr, 0, 8));
393
+ break;
394
+
395
+ default:
396
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad address size %d\n",
397
+ DEVICE(fiu)->canonical_path, FIU_DRD_CFG_ADDSIZ(drd_cfg));
398
+ break;
399
+ }
400
+
401
+ /* Flash chip model expects one transfer per dummy bit, not byte */
402
+ dummy_cycles =
403
+ (FIU_DRD_CFG_DBW(drd_cfg) * 8) >> FIU_DRD_CFG_ACCTYPE(drd_cfg);
404
+ for (i = 0; i < dummy_cycles; i++) {
405
+ ssi_transfer(fiu->spi, 0);
406
+ }
407
+
408
+ for (i = 0; i < size; i++) {
409
+ value = deposit64(value, 8 * i, 8, ssi_transfer(fiu->spi, 0));
410
+ }
411
+
412
+ trace_npcm7xx_fiu_flash_read(DEVICE(fiu)->canonical_path, fiu->active_cs,
413
+ addr, size, value);
414
+
415
+ npcm7xx_fiu_deselect(fiu);
416
+
417
+ return value;
418
+}
419
+
420
+/* Direct flash memory write handler. */
421
+static void npcm7xx_fiu_flash_write(void *opaque, hwaddr addr, uint64_t v,
422
+ unsigned int size)
423
+{
424
+ NPCM7xxFIUFlash *f = opaque;
425
+ NPCM7xxFIUState *fiu = f->fiu;
426
+ uint32_t dwr_cfg;
427
+ int cs_id;
428
+ int i;
429
+
430
+ if (fiu->active_cs != -1) {
431
+ qemu_log_mask(LOG_GUEST_ERROR,
432
+ "%s: direct flash write with CS%d already active",
433
+ DEVICE(fiu)->canonical_path, fiu->active_cs);
434
+ }
435
+
436
+ cs_id = npcm7xx_fiu_cs_index(fiu, f);
437
+ trace_npcm7xx_fiu_flash_write(DEVICE(fiu)->canonical_path, cs_id, addr,
438
+ size, v);
439
+ npcm7xx_fiu_select(fiu, cs_id);
440
+
441
+ dwr_cfg = fiu->regs[NPCM7XX_FIU_DWR_CFG];
442
+ ssi_transfer(fiu->spi, FIU_DWR_CFG_WRCMD(dwr_cfg));
443
+
444
+ switch (FIU_DWR_CFG_ADDSIZ(dwr_cfg)) {
445
+ case FIU_ADDSIZ_4BYTES:
446
+ ssi_transfer(fiu->spi, extract32(addr, 24, 8));
447
+ /* fall through */
448
+ case FIU_ADDSIZ_3BYTES:
449
+ ssi_transfer(fiu->spi, extract32(addr, 16, 8));
450
+ ssi_transfer(fiu->spi, extract32(addr, 8, 8));
451
+ ssi_transfer(fiu->spi, extract32(addr, 0, 8));
452
+ break;
453
+
454
+ default:
455
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad address size %d\n",
456
+ DEVICE(fiu)->canonical_path, FIU_DWR_CFG_ADDSIZ(dwr_cfg));
457
+ break;
458
+ }
459
+
460
+ for (i = 0; i < size; i++) {
461
+ ssi_transfer(fiu->spi, extract64(v, i * 8, 8));
462
+ }
463
+
464
+ npcm7xx_fiu_deselect(fiu);
465
+}
466
+
467
+static const MemoryRegionOps npcm7xx_fiu_flash_ops = {
468
+ .read = npcm7xx_fiu_flash_read,
469
+ .write = npcm7xx_fiu_flash_write,
470
+ .endianness = DEVICE_LITTLE_ENDIAN,
471
+ .valid = {
472
+ .min_access_size = 1,
473
+ .max_access_size = 8,
474
+ .unaligned = true,
475
+ },
476
+};
477
+
478
+/* Control register read handler. */
479
+static uint64_t npcm7xx_fiu_ctrl_read(void *opaque, hwaddr addr,
480
+ unsigned int size)
481
+{
482
+ hwaddr reg = addr / sizeof(uint32_t);
483
+ NPCM7xxFIUState *s = opaque;
484
+ uint32_t value;
485
+
486
+ if (reg < NPCM7XX_FIU_NR_REGS) {
487
+ value = s->regs[reg];
488
+ } else {
489
+ qemu_log_mask(LOG_GUEST_ERROR,
490
+ "%s: read from invalid offset 0x%" PRIx64 "\n",
491
+ DEVICE(s)->canonical_path, addr);
492
+ value = 0;
493
+ }
494
+
495
+ trace_npcm7xx_fiu_ctrl_read(DEVICE(s)->canonical_path, addr, value);
496
+
497
+ return value;
498
+}
499
+
500
+/* Send the specified number of address bytes from the UMA address register. */
501
+static void send_address(SSIBus *spi, unsigned int addsiz, uint32_t addr)
502
+{
503
+ switch (addsiz) {
504
+ case 4:
505
+ ssi_transfer(spi, extract32(addr, 24, 8));
506
+ /* fall through */
507
+ case 3:
508
+ ssi_transfer(spi, extract32(addr, 16, 8));
509
+ /* fall through */
510
+ case 2:
511
+ ssi_transfer(spi, extract32(addr, 8, 8));
512
+ /* fall through */
513
+ case 1:
514
+ ssi_transfer(spi, extract32(addr, 0, 8));
515
+ /* fall through */
516
+ case 0:
517
+ break;
518
+ }
519
+}
520
+
521
+/* Send the number of dummy bits specified in the UMA config register. */
522
+static void send_dummy_bits(SSIBus *spi, uint32_t uma_cfg, uint32_t uma_cmd)
523
+{
524
+ unsigned int bits_per_clock = 1U << FIU_UMA_CFG_DBPCK(uma_cfg);
525
+ unsigned int i;
526
+
527
+ for (i = 0; i < FIU_UMA_CFG_DBSIZ(uma_cfg); i++) {
528
+ /* Use bytes 0 and 1 first, then keep repeating byte 2 */
529
+ unsigned int field = (i < 2) ? ((i + 1) * 8) : 24;
530
+ unsigned int j;
531
+
532
+ for (j = 0; j < 8; j += bits_per_clock) {
533
+ ssi_transfer(spi, extract32(uma_cmd, field + j, bits_per_clock));
534
+ }
535
+ }
536
+}
537
+
538
+/* Perform a User-Mode Access transaction. */
539
+static void npcm7xx_fiu_uma_transaction(NPCM7xxFIUState *s)
540
+{
541
+ uint32_t uma_cts = s->regs[NPCM7XX_FIU_UMA_CTS];
542
+ uint32_t uma_cfg;
543
+ unsigned int i;
544
+
545
+ /* SW_CS means the CS is already forced low, so don't touch it. */
546
+ if (uma_cts & FIU_UMA_CTS_SW_CS) {
547
+ int cs_id = FIU_UMA_CTS_DEV_NUM(s->regs[NPCM7XX_FIU_UMA_CTS]);
548
+ npcm7xx_fiu_select(s, cs_id);
549
+ }
550
+
551
+ /* Send command, if present. */
552
+ uma_cfg = s->regs[NPCM7XX_FIU_UMA_CFG];
553
+ if (FIU_UMA_CFG_CMDSIZ(uma_cfg) > 0) {
554
+ ssi_transfer(s->spi, extract32(s->regs[NPCM7XX_FIU_UMA_CMD], 0, 8));
555
+ }
556
+
557
+ /* Send address, if present. */
558
+ send_address(s->spi, FIU_UMA_CFG_ADDSIZ(uma_cfg),
559
+ s->regs[NPCM7XX_FIU_UMA_ADDR]);
560
+
561
+ /* Write data, if present. */
562
+ for (i = 0; i < FIU_UMA_CFG_WDATSIZ(uma_cfg); i++) {
563
+ unsigned int reg =
564
+ (i < 16) ? (NPCM7XX_FIU_UMA_DW0 + i / 4) : NPCM7XX_FIU_UMA_DW3;
565
+ unsigned int field = (i % 4) * 8;
566
+
567
+ ssi_transfer(s->spi, extract32(s->regs[reg], field, 8));
568
+ }
569
+
570
+ /* Send dummy bits, if present. */
571
+ send_dummy_bits(s->spi, uma_cfg, s->regs[NPCM7XX_FIU_UMA_CMD]);
572
+
573
+ /* Read data, if present. */
574
+ for (i = 0; i < FIU_UMA_CFG_RDATSIZ(uma_cfg); i++) {
575
+ unsigned int reg = NPCM7XX_FIU_UMA_DR0 + i / 4;
576
+ unsigned int field = (i % 4) * 8;
577
+ uint8_t c;
578
+
579
+ c = ssi_transfer(s->spi, 0);
580
+ if (reg <= NPCM7XX_FIU_UMA_DR3) {
581
+ s->regs[reg] = deposit32(s->regs[reg], field, 8, c);
582
+ }
583
+ }
584
+
585
+ /* Again, don't touch CS if the user is forcing it low. */
586
+ if (uma_cts & FIU_UMA_CTS_SW_CS) {
587
+ npcm7xx_fiu_deselect(s);
588
+ }
589
+
590
+ /* RDYST means a command has completed since it was cleared. */
591
+ s->regs[NPCM7XX_FIU_UMA_CTS] |= FIU_UMA_CTS_RDYST;
592
+ /* EXEC_DONE means Execute Command / Not Done, so clear it here. */
593
+ s->regs[NPCM7XX_FIU_UMA_CTS] &= ~FIU_UMA_CTS_EXEC_DONE;
594
+}
595
+
596
+/* Control register write handler. */
597
+static void npcm7xx_fiu_ctrl_write(void *opaque, hwaddr addr, uint64_t v,
598
+ unsigned int size)
599
+{
600
+ hwaddr reg = addr / sizeof(uint32_t);
601
+ NPCM7xxFIUState *s = opaque;
602
+ uint32_t value = v;
603
+
604
+ trace_npcm7xx_fiu_ctrl_write(DEVICE(s)->canonical_path, addr, value);
605
+
606
+ switch (reg) {
607
+ case NPCM7XX_FIU_UMA_CFG:
608
+ if (s->regs[reg] & FIU_UMA_CFG_CMMLCK) {
609
+ value &= ~FIU_UMA_CFG_CMMLCK_MASK;
610
+ value |= (s->regs[reg] & FIU_UMA_CFG_CMMLCK_MASK);
611
+ }
612
+ /* fall through */
613
+ case NPCM7XX_FIU_DRD_CFG:
614
+ case NPCM7XX_FIU_DWR_CFG:
615
+ if (s->regs[reg] & NPCM7XX_FIU_CFG_LCK) {
616
+ qemu_log_mask(LOG_GUEST_ERROR,
617
+ "%s: write to locked register @ 0x%" PRIx64 "\n",
618
+ DEVICE(s)->canonical_path, addr);
619
+ return;
620
+ }
621
+ s->regs[reg] = value;
622
+ break;
623
+
624
+ case NPCM7XX_FIU_UMA_CTS:
625
+ if (value & FIU_UMA_CTS_RDYST) {
626
+ value &= ~FIU_UMA_CTS_RDYST;
627
+ } else {
628
+ value |= s->regs[reg] & FIU_UMA_CTS_RDYST;
629
+ }
630
+ if ((s->regs[reg] ^ value) & FIU_UMA_CTS_SW_CS) {
631
+ if (value & FIU_UMA_CTS_SW_CS) {
632
+ /*
633
+ * Don't drop CS if there's a transfer in progress, or we're
634
+ * about to start one.
635
+ */
636
+ if (!((value | s->regs[reg]) & FIU_UMA_CTS_EXEC_DONE)) {
637
+ npcm7xx_fiu_deselect(s);
638
+ }
639
+ } else {
640
+ int cs_id = FIU_UMA_CTS_DEV_NUM(s->regs[NPCM7XX_FIU_UMA_CTS]);
641
+ npcm7xx_fiu_select(s, cs_id);
642
+ }
643
+ }
644
+ s->regs[reg] = value | (s->regs[reg] & FIU_UMA_CTS_EXEC_DONE);
645
+ if (value & FIU_UMA_CTS_EXEC_DONE) {
646
+ npcm7xx_fiu_uma_transaction(s);
647
+ }
648
+ break;
649
+
650
+ case NPCM7XX_FIU_UMA_DR0 ... NPCM7XX_FIU_UMA_DR3:
651
+ qemu_log_mask(LOG_GUEST_ERROR,
652
+ "%s: write to read-only register @ 0x%" PRIx64 "\n",
653
+ DEVICE(s)->canonical_path, addr);
654
+ return;
655
+
656
+ case NPCM7XX_FIU_PRT_CFG:
657
+ case NPCM7XX_FIU_PRT_CMD0 ... NPCM7XX_FIU_PRT_CMD9:
658
+ qemu_log_mask(LOG_UNIMP, "%s: PRT is not implemented\n", __func__);
659
+ break;
660
+
661
+ case NPCM7XX_FIU_UMA_CMD:
662
+ case NPCM7XX_FIU_UMA_ADDR:
663
+ case NPCM7XX_FIU_UMA_DW0 ... NPCM7XX_FIU_UMA_DW3:
664
+ case NPCM7XX_FIU_CFG:
665
+ s->regs[reg] = value;
666
+ break;
667
+
668
+ default:
669
+ qemu_log_mask(LOG_GUEST_ERROR,
670
+ "%s: write to invalid offset 0x%" PRIx64 "\n",
671
+ DEVICE(s)->canonical_path, addr);
672
+ return;
673
+ }
674
+}
675
+
676
+static const MemoryRegionOps npcm7xx_fiu_ctrl_ops = {
677
+ .read = npcm7xx_fiu_ctrl_read,
678
+ .write = npcm7xx_fiu_ctrl_write,
679
+ .endianness = DEVICE_LITTLE_ENDIAN,
680
+ .valid = {
681
+ .min_access_size = 4,
682
+ .max_access_size = 4,
683
+ .unaligned = false,
684
+ },
685
+};
686
+
687
+static void npcm7xx_fiu_enter_reset(Object *obj, ResetType type)
688
+{
689
+ NPCM7xxFIUState *s = NPCM7XX_FIU(obj);
690
+
691
+ trace_npcm7xx_fiu_enter_reset(DEVICE(obj)->canonical_path, type);
692
+
693
+ memset(s->regs, 0, sizeof(s->regs));
694
+
695
+ s->regs[NPCM7XX_FIU_DRD_CFG] = 0x0300100b;
696
+ s->regs[NPCM7XX_FIU_DWR_CFG] = 0x03000002;
697
+ s->regs[NPCM7XX_FIU_UMA_CFG] = 0x00000400;
698
+ s->regs[NPCM7XX_FIU_UMA_CTS] = 0x00010000;
699
+ s->regs[NPCM7XX_FIU_UMA_CMD] = 0x0000000b;
700
+ s->regs[NPCM7XX_FIU_PRT_CFG] = 0x00000400;
701
+ s->regs[NPCM7XX_FIU_CFG] = 0x0000000b;
702
+}
703
+
704
+static void npcm7xx_fiu_hold_reset(Object *obj)
705
+{
706
+ NPCM7xxFIUState *s = NPCM7XX_FIU(obj);
707
+ int i;
708
+
709
+ trace_npcm7xx_fiu_hold_reset(DEVICE(obj)->canonical_path);
710
+
711
+ for (i = 0; i < s->cs_count; i++) {
712
+ qemu_irq_raise(s->cs_lines[i]);
713
+ }
714
+}
715
+
716
+static void npcm7xx_fiu_realize(DeviceState *dev, Error **errp)
717
+{
718
+ NPCM7xxFIUState *s = NPCM7XX_FIU(dev);
719
+ SysBusDevice *sbd = &s->parent;
720
+ int i;
721
+
722
+ if (s->cs_count <= 0) {
723
+ error_setg(errp, "%s: %d chip selects specified, need at least one",
724
+ dev->canonical_path, s->cs_count);
725
+ return;
726
+ }
727
+
728
+ s->spi = ssi_create_bus(dev, "spi");
729
+ s->cs_lines = g_new0(qemu_irq, s->cs_count);
730
+ qdev_init_gpio_out_named(DEVICE(s), s->cs_lines, "cs", s->cs_count);
731
+ s->flash = g_new0(NPCM7xxFIUFlash, s->cs_count);
732
+
55
+
733
+ /*
56
+ /*
734
+ * Register the control registers region first. It may be followed by one
57
+ * TZASC
735
+ * or more direct flash access regions.
736
+ */
58
+ */
737
+ memory_region_init_io(&s->mmio, OBJECT(s), &npcm7xx_fiu_ctrl_ops, s, "ctrl",
59
+ create_unimplemented_device("tzasc", FSL_IMX6UL_TZASC_ADDR,
738
+ NPCM7XX_FIU_CTRL_REGS_SIZE);
60
+ FSL_IMX6UL_TZASC_SIZE);
739
+ sysbus_init_mmio(sbd, &s->mmio);
740
+
61
+
741
+ for (i = 0; i < s->cs_count; i++) {
62
/*
742
+ NPCM7xxFIUFlash *flash = &s->flash[i];
63
* ROM memory
743
+ flash->fiu = s;
64
*/
744
+ memory_region_init_io(&flash->direct_access, OBJECT(s),
745
+ &npcm7xx_fiu_flash_ops, &s->flash[i], "flash",
746
+ NPCM7XX_FIU_FLASH_WINDOW_SIZE);
747
+ sysbus_init_mmio(sbd, &flash->direct_access);
748
+ }
749
+}
750
+
751
+static const VMStateDescription vmstate_npcm7xx_fiu = {
752
+ .name = "npcm7xx-fiu",
753
+ .version_id = 0,
754
+ .minimum_version_id = 0,
755
+ .fields = (VMStateField[]) {
756
+ VMSTATE_INT32(active_cs, NPCM7xxFIUState),
757
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxFIUState, NPCM7XX_FIU_NR_REGS),
758
+ VMSTATE_END_OF_LIST(),
759
+ },
760
+};
761
+
762
+static Property npcm7xx_fiu_properties[] = {
763
+ DEFINE_PROP_INT32("cs-count", NPCM7xxFIUState, cs_count, 0),
764
+ DEFINE_PROP_END_OF_LIST(),
765
+};
766
+
767
+static void npcm7xx_fiu_class_init(ObjectClass *klass, void *data)
768
+{
769
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
770
+ DeviceClass *dc = DEVICE_CLASS(klass);
771
+
772
+ QEMU_BUILD_BUG_ON(NPCM7XX_FIU_REGS_END > NPCM7XX_FIU_NR_REGS);
773
+
774
+ dc->desc = "NPCM7xx Flash Interface Unit";
775
+ dc->realize = npcm7xx_fiu_realize;
776
+ dc->vmsd = &vmstate_npcm7xx_fiu;
777
+ rc->phases.enter = npcm7xx_fiu_enter_reset;
778
+ rc->phases.hold = npcm7xx_fiu_hold_reset;
779
+ device_class_set_props(dc, npcm7xx_fiu_properties);
780
+}
781
+
782
+static const TypeInfo npcm7xx_fiu_types[] = {
783
+ {
784
+ .name = TYPE_NPCM7XX_FIU,
785
+ .parent = TYPE_SYS_BUS_DEVICE,
786
+ .instance_size = sizeof(NPCM7xxFIUState),
787
+ .class_init = npcm7xx_fiu_class_init,
788
+ },
789
+};
790
+DEFINE_TYPES(npcm7xx_fiu_types);
791
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
792
index XXXXXXX..XXXXXXX 100644
793
--- a/hw/arm/Kconfig
794
+++ b/hw/arm/Kconfig
795
@@ -XXX,XX +XXX,XX @@ config NPCM7XX
796
select ARM_GIC
797
select PL310 # cache controller
798
select SERIAL
799
+ select SSI
800
select UNIMP
801
802
config FSL_IMX25
803
diff --git a/hw/ssi/meson.build b/hw/ssi/meson.build
804
index XXXXXXX..XXXXXXX 100644
805
--- a/hw/ssi/meson.build
806
+++ b/hw/ssi/meson.build
807
@@ -XXX,XX +XXX,XX @@
808
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_smc.c'))
809
softmmu_ss.add(when: 'CONFIG_MSF2', if_true: files('mss-spi.c'))
810
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_fiu.c'))
811
softmmu_ss.add(when: 'CONFIG_PL022', if_true: files('pl022.c'))
812
softmmu_ss.add(when: 'CONFIG_SSI', if_true: files('ssi.c'))
813
softmmu_ss.add(when: 'CONFIG_STM32F2XX_SPI', if_true: files('stm32f2xx_spi.c'))
814
diff --git a/hw/ssi/trace-events b/hw/ssi/trace-events
815
index XXXXXXX..XXXXXXX 100644
816
--- a/hw/ssi/trace-events
817
+++ b/hw/ssi/trace-events
818
@@ -XXX,XX +XXX,XX @@ aspeed_smc_dma_checksum(uint32_t addr, uint32_t data) "0x%08x: 0x%08x"
819
aspeed_smc_dma_rw(const char *dir, uint32_t flash_addr, uint32_t dram_addr, uint32_t size) "%s flash:@0x%08x dram:@0x%08x size:0x%08x"
820
aspeed_smc_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size %u: 0x%" PRIx64
821
aspeed_smc_flash_select(int cs, const char *prefix) "CS%d %sselect"
822
+
823
+# npcm7xx_fiu.c
824
+
825
+npcm7xx_fiu_enter_reset(const char *id, int reset_type) "%s reset type: %d"
826
+npcm7xx_fiu_hold_reset(const char *id) "%s"
827
+npcm7xx_fiu_select(const char *id, int cs) "%s select CS%d"
828
+npcm7xx_fiu_deselect(const char *id, int cs) "%s deselect CS%d"
829
+npcm7xx_fiu_ctrl_read(const char *id, uint64_t addr, uint32_t data) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
830
+npcm7xx_fiu_ctrl_write(const char *id, uint64_t addr, uint32_t data) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
831
+npcm7xx_fiu_flash_read(const char *id, int cs, uint64_t addr, unsigned int size, uint64_t value) "%s[%d] offset: 0x%08" PRIx64 " size: %u value: 0x%" PRIx64
832
+npcm7xx_fiu_flash_write(const char *id, int cs, uint64_t addr, unsigned int size, uint64_t value) "%s[%d] offset: 0x%08" PRIx64 " size: %u value: 0x%" PRIx64
833
--
65
--
834
2.20.1
66
2.34.1
835
67
836
68
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Jean-Christophe Dubois <jcd@tribudubois.net>
2
2
3
If a -bios option is specified on the command line, load the image into
3
* Add Addr and size definition for all i.MX7 devices in i.MX7 header file.
4
the internal ROM memory region, which contains the first instructions
4
* Use those newly defined named constants whenever possible.
5
run by the CPU after reset.
5
* Standardize the way we init a familly of unimplemented devices
6
- SAI
7
- PWM
8
- CAN
9
* Add/rework few comments
6
10
7
If -bios is not specified, the vbootrom included with qemu is loaded by
11
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
8
default.
12
Message-id: 59e195d33e4d486a8d131392acd46633c8c10ed7.1692964892.git.jcd@tribudubois.net
9
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
11
Reviewed-by: Cédric Le Goater <clg@kaod.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
15
Message-id: 20200911052101.2602693-8-hskinnemoen@google.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
15
---
18
hw/arm/npcm7xx_boards.c | 32 ++++++++++++++++++++++++++++++++
16
include/hw/arm/fsl-imx7.h | 330 ++++++++++++++++++++++++++++----------
19
1 file changed, 32 insertions(+)
17
hw/arm/fsl-imx7.c | 130 ++++++++++-----
18
2 files changed, 335 insertions(+), 125 deletions(-)
20
19
21
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
20
diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h
22
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/npcm7xx_boards.c
22
--- a/include/hw/arm/fsl-imx7.h
24
+++ b/hw/arm/npcm7xx_boards.c
23
+++ b/include/hw/arm/fsl-imx7.h
25
@@ -XXX,XX +XXX,XX @@
24
@@ -XXX,XX +XXX,XX @@
26
#include "exec/address-spaces.h"
25
#include "hw/misc/imx7_ccm.h"
27
#include "hw/arm/npcm7xx.h"
26
#include "hw/misc/imx7_snvs.h"
28
#include "hw/core/cpu.h"
27
#include "hw/misc/imx7_gpr.h"
29
+#include "hw/loader.h"
28
-#include "hw/misc/imx6_src.h"
30
#include "qapi/error.h"
29
#include "hw/watchdog/wdt_imx2.h"
31
+#include "qemu-common.h"
30
#include "hw/gpio/imx_gpio.h"
32
#include "qemu/units.h"
31
#include "hw/char/imx_serial.h"
33
+#include "sysemu/sysemu.h"
32
@@ -XXX,XX +XXX,XX @@
34
33
#include "hw/usb/chipidea.h"
35
#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7
34
#include "cpu.h"
36
#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff
35
#include "qom/object.h"
37
36
+#include "qemu/units.h"
38
+static const char npcm7xx_default_bootrom[] = "npcm7xx_bootrom.bin";
37
39
+
38
#define TYPE_FSL_IMX7 "fsl-imx7"
40
+static void npcm7xx_load_bootrom(MachineState *machine, NPCM7xxState *soc)
39
OBJECT_DECLARE_SIMPLE_TYPE(FslIMX7State, FSL_IMX7)
41
+{
40
@@ -XXX,XX +XXX,XX @@ enum FslIMX7Configuration {
42
+ g_autofree char *filename = NULL;
41
FSL_IMX7_NUM_ECSPIS = 4,
43
+ int ret;
42
FSL_IMX7_NUM_USBS = 3,
44
+
43
FSL_IMX7_NUM_ADCS = 2,
45
+ if (!bios_name) {
44
+ FSL_IMX7_NUM_SAIS = 3,
46
+ bios_name = npcm7xx_default_bootrom;
45
+ FSL_IMX7_NUM_CANS = 2,
46
+ FSL_IMX7_NUM_PWMS = 4,
47
};
48
49
struct FslIMX7State {
50
@@ -XXX,XX +XXX,XX @@ struct FslIMX7State {
51
52
enum FslIMX7MemoryMap {
53
FSL_IMX7_MMDC_ADDR = 0x80000000,
54
- FSL_IMX7_MMDC_SIZE = 2 * 1024 * 1024 * 1024UL,
55
+ FSL_IMX7_MMDC_SIZE = (2 * GiB),
56
57
- FSL_IMX7_GPIO1_ADDR = 0x30200000,
58
- FSL_IMX7_GPIO2_ADDR = 0x30210000,
59
- FSL_IMX7_GPIO3_ADDR = 0x30220000,
60
- FSL_IMX7_GPIO4_ADDR = 0x30230000,
61
- FSL_IMX7_GPIO5_ADDR = 0x30240000,
62
- FSL_IMX7_GPIO6_ADDR = 0x30250000,
63
- FSL_IMX7_GPIO7_ADDR = 0x30260000,
64
+ FSL_IMX7_QSPI1_MEM_ADDR = 0x60000000,
65
+ FSL_IMX7_QSPI1_MEM_SIZE = (256 * MiB),
66
67
- FSL_IMX7_IOMUXC_LPSR_GPR_ADDR = 0x30270000,
68
+ FSL_IMX7_PCIE1_MEM_ADDR = 0x40000000,
69
+ FSL_IMX7_PCIE1_MEM_SIZE = (256 * MiB),
70
71
- FSL_IMX7_WDOG1_ADDR = 0x30280000,
72
- FSL_IMX7_WDOG2_ADDR = 0x30290000,
73
- FSL_IMX7_WDOG3_ADDR = 0x302A0000,
74
- FSL_IMX7_WDOG4_ADDR = 0x302B0000,
75
+ FSL_IMX7_QSPI1_RX_BUF_ADDR = 0x34000000,
76
+ FSL_IMX7_QSPI1_RX_BUF_SIZE = (32 * MiB),
77
78
- FSL_IMX7_IOMUXC_LPSR_ADDR = 0x302C0000,
79
+ /* PCIe Peripherals */
80
+ FSL_IMX7_PCIE_REG_ADDR = 0x33800000,
81
82
- FSL_IMX7_GPT1_ADDR = 0x302D0000,
83
- FSL_IMX7_GPT2_ADDR = 0x302E0000,
84
- FSL_IMX7_GPT3_ADDR = 0x302F0000,
85
- FSL_IMX7_GPT4_ADDR = 0x30300000,
86
+ /* MMAP Peripherals */
87
+ FSL_IMX7_DMA_APBH_ADDR = 0x33000000,
88
+ FSL_IMX7_DMA_APBH_SIZE = 0x8000,
89
90
- FSL_IMX7_IOMUXC_ADDR = 0x30330000,
91
- FSL_IMX7_IOMUXC_GPR_ADDR = 0x30340000,
92
- FSL_IMX7_IOMUXCn_SIZE = 0x1000,
93
+ /* GPV configuration */
94
+ FSL_IMX7_GPV6_ADDR = 0x32600000,
95
+ FSL_IMX7_GPV5_ADDR = 0x32500000,
96
+ FSL_IMX7_GPV4_ADDR = 0x32400000,
97
+ FSL_IMX7_GPV3_ADDR = 0x32300000,
98
+ FSL_IMX7_GPV2_ADDR = 0x32200000,
99
+ FSL_IMX7_GPV1_ADDR = 0x32100000,
100
+ FSL_IMX7_GPV0_ADDR = 0x32000000,
101
+ FSL_IMX7_GPVn_SIZE = (1 * MiB),
102
103
- FSL_IMX7_OCOTP_ADDR = 0x30350000,
104
- FSL_IMX7_OCOTP_SIZE = 0x10000,
105
+ /* Arm Peripherals */
106
+ FSL_IMX7_A7MPCORE_ADDR = 0x31000000,
107
108
- FSL_IMX7_ANALOG_ADDR = 0x30360000,
109
- FSL_IMX7_SNVS_ADDR = 0x30370000,
110
- FSL_IMX7_CCM_ADDR = 0x30380000,
111
+ /* AIPS-3 Begin */
112
113
- FSL_IMX7_SRC_ADDR = 0x30390000,
114
- FSL_IMX7_SRC_SIZE = 0x1000,
115
+ FSL_IMX7_ENET2_ADDR = 0x30BF0000,
116
+ FSL_IMX7_ENET1_ADDR = 0x30BE0000,
117
118
- FSL_IMX7_ADC1_ADDR = 0x30610000,
119
- FSL_IMX7_ADC2_ADDR = 0x30620000,
120
- FSL_IMX7_ADCn_SIZE = 0x1000,
121
+ FSL_IMX7_SDMA_ADDR = 0x30BD0000,
122
+ FSL_IMX7_SDMA_SIZE = (4 * KiB),
123
124
- FSL_IMX7_PWM1_ADDR = 0x30660000,
125
- FSL_IMX7_PWM2_ADDR = 0x30670000,
126
- FSL_IMX7_PWM3_ADDR = 0x30680000,
127
- FSL_IMX7_PWM4_ADDR = 0x30690000,
128
- FSL_IMX7_PWMn_SIZE = 0x10000,
129
+ FSL_IMX7_EIM_ADDR = 0x30BC0000,
130
+ FSL_IMX7_EIM_SIZE = (4 * KiB),
131
132
- FSL_IMX7_PCIE_PHY_ADDR = 0x306D0000,
133
- FSL_IMX7_PCIE_PHY_SIZE = 0x10000,
134
+ FSL_IMX7_QSPI_ADDR = 0x30BB0000,
135
+ FSL_IMX7_QSPI_SIZE = 0x8000,
136
137
- FSL_IMX7_GPC_ADDR = 0x303A0000,
138
+ FSL_IMX7_SIM2_ADDR = 0x30BA0000,
139
+ FSL_IMX7_SIM1_ADDR = 0x30B90000,
140
+ FSL_IMX7_SIMn_SIZE = (4 * KiB),
141
+
142
+ FSL_IMX7_USDHC3_ADDR = 0x30B60000,
143
+ FSL_IMX7_USDHC2_ADDR = 0x30B50000,
144
+ FSL_IMX7_USDHC1_ADDR = 0x30B40000,
145
+
146
+ FSL_IMX7_USB3_ADDR = 0x30B30000,
147
+ FSL_IMX7_USBMISC3_ADDR = 0x30B30200,
148
+ FSL_IMX7_USB2_ADDR = 0x30B20000,
149
+ FSL_IMX7_USBMISC2_ADDR = 0x30B20200,
150
+ FSL_IMX7_USB1_ADDR = 0x30B10000,
151
+ FSL_IMX7_USBMISC1_ADDR = 0x30B10200,
152
+ FSL_IMX7_USBMISCn_SIZE = 0x200,
153
+
154
+ FSL_IMX7_USB_PL301_ADDR = 0x30AD0000,
155
+ FSL_IMX7_USB_PL301_SIZE = (64 * KiB),
156
+
157
+ FSL_IMX7_SEMAPHORE_HS_ADDR = 0x30AC0000,
158
+ FSL_IMX7_SEMAPHORE_HS_SIZE = (64 * KiB),
159
+
160
+ FSL_IMX7_MUB_ADDR = 0x30AB0000,
161
+ FSL_IMX7_MUA_ADDR = 0x30AA0000,
162
+ FSL_IMX7_MUn_SIZE = (KiB),
163
+
164
+ FSL_IMX7_UART7_ADDR = 0x30A90000,
165
+ FSL_IMX7_UART6_ADDR = 0x30A80000,
166
+ FSL_IMX7_UART5_ADDR = 0x30A70000,
167
+ FSL_IMX7_UART4_ADDR = 0x30A60000,
168
+
169
+ FSL_IMX7_I2C4_ADDR = 0x30A50000,
170
+ FSL_IMX7_I2C3_ADDR = 0x30A40000,
171
+ FSL_IMX7_I2C2_ADDR = 0x30A30000,
172
+ FSL_IMX7_I2C1_ADDR = 0x30A20000,
173
+
174
+ FSL_IMX7_CAN2_ADDR = 0x30A10000,
175
+ FSL_IMX7_CAN1_ADDR = 0x30A00000,
176
+ FSL_IMX7_CANn_SIZE = (4 * KiB),
177
+
178
+ FSL_IMX7_AIPS3_CONF_ADDR = 0x309F0000,
179
+ FSL_IMX7_AIPS3_CONF_SIZE = (64 * KiB),
180
181
FSL_IMX7_CAAM_ADDR = 0x30900000,
182
- FSL_IMX7_CAAM_SIZE = 0x40000,
183
+ FSL_IMX7_CAAM_SIZE = (256 * KiB),
184
185
- FSL_IMX7_CAN1_ADDR = 0x30A00000,
186
- FSL_IMX7_CAN2_ADDR = 0x30A10000,
187
- FSL_IMX7_CANn_SIZE = 0x10000,
188
+ FSL_IMX7_SPBA_ADDR = 0x308F0000,
189
+ FSL_IMX7_SPBA_SIZE = (4 * KiB),
190
191
- FSL_IMX7_I2C1_ADDR = 0x30A20000,
192
- FSL_IMX7_I2C2_ADDR = 0x30A30000,
193
- FSL_IMX7_I2C3_ADDR = 0x30A40000,
194
- FSL_IMX7_I2C4_ADDR = 0x30A50000,
195
+ FSL_IMX7_SAI3_ADDR = 0x308C0000,
196
+ FSL_IMX7_SAI2_ADDR = 0x308B0000,
197
+ FSL_IMX7_SAI1_ADDR = 0x308A0000,
198
+ FSL_IMX7_SAIn_SIZE = (4 * KiB),
199
200
- FSL_IMX7_ECSPI1_ADDR = 0x30820000,
201
- FSL_IMX7_ECSPI2_ADDR = 0x30830000,
202
- FSL_IMX7_ECSPI3_ADDR = 0x30840000,
203
- FSL_IMX7_ECSPI4_ADDR = 0x30630000,
204
-
205
- FSL_IMX7_LCDIF_ADDR = 0x30730000,
206
- FSL_IMX7_LCDIF_SIZE = 0x1000,
207
-
208
- FSL_IMX7_UART1_ADDR = 0x30860000,
209
+ FSL_IMX7_UART3_ADDR = 0x30880000,
210
/*
211
* Some versions of the reference manual claim that UART2 is @
212
* 0x30870000, but experiments with HW + DT files in upstream
213
@@ -XXX,XX +XXX,XX @@ enum FslIMX7MemoryMap {
214
* actually located @ 0x30890000
215
*/
216
FSL_IMX7_UART2_ADDR = 0x30890000,
217
- FSL_IMX7_UART3_ADDR = 0x30880000,
218
- FSL_IMX7_UART4_ADDR = 0x30A60000,
219
- FSL_IMX7_UART5_ADDR = 0x30A70000,
220
- FSL_IMX7_UART6_ADDR = 0x30A80000,
221
- FSL_IMX7_UART7_ADDR = 0x30A90000,
222
+ FSL_IMX7_UART1_ADDR = 0x30860000,
223
224
- FSL_IMX7_SAI1_ADDR = 0x308A0000,
225
- FSL_IMX7_SAI2_ADDR = 0x308B0000,
226
- FSL_IMX7_SAI3_ADDR = 0x308C0000,
227
- FSL_IMX7_SAIn_SIZE = 0x10000,
228
+ FSL_IMX7_ECSPI3_ADDR = 0x30840000,
229
+ FSL_IMX7_ECSPI2_ADDR = 0x30830000,
230
+ FSL_IMX7_ECSPI1_ADDR = 0x30820000,
231
+ FSL_IMX7_ECSPIn_SIZE = (4 * KiB),
232
233
- FSL_IMX7_ENET1_ADDR = 0x30BE0000,
234
- FSL_IMX7_ENET2_ADDR = 0x30BF0000,
235
+ /* AIPS-3 End */
236
237
- FSL_IMX7_USB1_ADDR = 0x30B10000,
238
- FSL_IMX7_USBMISC1_ADDR = 0x30B10200,
239
- FSL_IMX7_USB2_ADDR = 0x30B20000,
240
- FSL_IMX7_USBMISC2_ADDR = 0x30B20200,
241
- FSL_IMX7_USB3_ADDR = 0x30B30000,
242
- FSL_IMX7_USBMISC3_ADDR = 0x30B30200,
243
- FSL_IMX7_USBMISCn_SIZE = 0x200,
244
+ /* AIPS-2 Begin */
245
246
- FSL_IMX7_USDHC1_ADDR = 0x30B40000,
247
- FSL_IMX7_USDHC2_ADDR = 0x30B50000,
248
- FSL_IMX7_USDHC3_ADDR = 0x30B60000,
249
+ FSL_IMX7_AXI_DEBUG_MON_ADDR = 0x307E0000,
250
+ FSL_IMX7_AXI_DEBUG_MON_SIZE = (64 * KiB),
251
252
- FSL_IMX7_SDMA_ADDR = 0x30BD0000,
253
- FSL_IMX7_SDMA_SIZE = 0x1000,
254
+ FSL_IMX7_PERFMON2_ADDR = 0x307D0000,
255
+ FSL_IMX7_PERFMON1_ADDR = 0x307C0000,
256
+ FSL_IMX7_PERFMONn_SIZE = (64 * KiB),
257
+
258
+ FSL_IMX7_DDRC_ADDR = 0x307A0000,
259
+ FSL_IMX7_DDRC_SIZE = (4 * KiB),
260
+
261
+ FSL_IMX7_DDRC_PHY_ADDR = 0x30790000,
262
+ FSL_IMX7_DDRC_PHY_SIZE = (4 * KiB),
263
+
264
+ FSL_IMX7_TZASC_ADDR = 0x30780000,
265
+ FSL_IMX7_TZASC_SIZE = (64 * KiB),
266
+
267
+ FSL_IMX7_MIPI_DSI_ADDR = 0x30760000,
268
+ FSL_IMX7_MIPI_DSI_SIZE = (4 * KiB),
269
+
270
+ FSL_IMX7_MIPI_CSI_ADDR = 0x30750000,
271
+ FSL_IMX7_MIPI_CSI_SIZE = 0x4000,
272
+
273
+ FSL_IMX7_LCDIF_ADDR = 0x30730000,
274
+ FSL_IMX7_LCDIF_SIZE = 0x8000,
275
+
276
+ FSL_IMX7_CSI_ADDR = 0x30710000,
277
+ FSL_IMX7_CSI_SIZE = (4 * KiB),
278
+
279
+ FSL_IMX7_PXP_ADDR = 0x30700000,
280
+ FSL_IMX7_PXP_SIZE = 0x4000,
281
+
282
+ FSL_IMX7_EPDC_ADDR = 0x306F0000,
283
+ FSL_IMX7_EPDC_SIZE = (4 * KiB),
284
+
285
+ FSL_IMX7_PCIE_PHY_ADDR = 0x306D0000,
286
+ FSL_IMX7_PCIE_PHY_SIZE = (4 * KiB),
287
+
288
+ FSL_IMX7_SYSCNT_CTRL_ADDR = 0x306C0000,
289
+ FSL_IMX7_SYSCNT_CMP_ADDR = 0x306B0000,
290
+ FSL_IMX7_SYSCNT_RD_ADDR = 0x306A0000,
291
+
292
+ FSL_IMX7_PWM4_ADDR = 0x30690000,
293
+ FSL_IMX7_PWM3_ADDR = 0x30680000,
294
+ FSL_IMX7_PWM2_ADDR = 0x30670000,
295
+ FSL_IMX7_PWM1_ADDR = 0x30660000,
296
+ FSL_IMX7_PWMn_SIZE = (4 * KiB),
297
+
298
+ FSL_IMX7_FlEXTIMER2_ADDR = 0x30650000,
299
+ FSL_IMX7_FlEXTIMER1_ADDR = 0x30640000,
300
+ FSL_IMX7_FLEXTIMERn_SIZE = (4 * KiB),
301
+
302
+ FSL_IMX7_ECSPI4_ADDR = 0x30630000,
303
+
304
+ FSL_IMX7_ADC2_ADDR = 0x30620000,
305
+ FSL_IMX7_ADC1_ADDR = 0x30610000,
306
+ FSL_IMX7_ADCn_SIZE = (4 * KiB),
307
+
308
+ FSL_IMX7_AIPS2_CONF_ADDR = 0x305F0000,
309
+ FSL_IMX7_AIPS2_CONF_SIZE = (64 * KiB),
310
+
311
+ /* AIPS-2 End */
312
+
313
+ /* AIPS-1 Begin */
314
+
315
+ FSL_IMX7_CSU_ADDR = 0x303E0000,
316
+ FSL_IMX7_CSU_SIZE = (64 * KiB),
317
+
318
+ FSL_IMX7_RDC_ADDR = 0x303D0000,
319
+ FSL_IMX7_RDC_SIZE = (4 * KiB),
320
+
321
+ FSL_IMX7_SEMAPHORE2_ADDR = 0x303C0000,
322
+ FSL_IMX7_SEMAPHORE1_ADDR = 0x303B0000,
323
+ FSL_IMX7_SEMAPHOREn_SIZE = (4 * KiB),
324
+
325
+ FSL_IMX7_GPC_ADDR = 0x303A0000,
326
+
327
+ FSL_IMX7_SRC_ADDR = 0x30390000,
328
+ FSL_IMX7_SRC_SIZE = (4 * KiB),
329
+
330
+ FSL_IMX7_CCM_ADDR = 0x30380000,
331
+
332
+ FSL_IMX7_SNVS_HP_ADDR = 0x30370000,
333
+
334
+ FSL_IMX7_ANALOG_ADDR = 0x30360000,
335
+
336
+ FSL_IMX7_OCOTP_ADDR = 0x30350000,
337
+ FSL_IMX7_OCOTP_SIZE = 0x10000,
338
+
339
+ FSL_IMX7_IOMUXC_GPR_ADDR = 0x30340000,
340
+ FSL_IMX7_IOMUXC_GPR_SIZE = (4 * KiB),
341
+
342
+ FSL_IMX7_IOMUXC_ADDR = 0x30330000,
343
+ FSL_IMX7_IOMUXC_SIZE = (4 * KiB),
344
+
345
+ FSL_IMX7_KPP_ADDR = 0x30320000,
346
+ FSL_IMX7_KPP_SIZE = (4 * KiB),
347
+
348
+ FSL_IMX7_ROMCP_ADDR = 0x30310000,
349
+ FSL_IMX7_ROMCP_SIZE = (4 * KiB),
350
+
351
+ FSL_IMX7_GPT4_ADDR = 0x30300000,
352
+ FSL_IMX7_GPT3_ADDR = 0x302F0000,
353
+ FSL_IMX7_GPT2_ADDR = 0x302E0000,
354
+ FSL_IMX7_GPT1_ADDR = 0x302D0000,
355
+
356
+ FSL_IMX7_IOMUXC_LPSR_ADDR = 0x302C0000,
357
+ FSL_IMX7_IOMUXC_LPSR_SIZE = (4 * KiB),
358
+
359
+ FSL_IMX7_WDOG4_ADDR = 0x302B0000,
360
+ FSL_IMX7_WDOG3_ADDR = 0x302A0000,
361
+ FSL_IMX7_WDOG2_ADDR = 0x30290000,
362
+ FSL_IMX7_WDOG1_ADDR = 0x30280000,
363
+
364
+ FSL_IMX7_IOMUXC_LPSR_GPR_ADDR = 0x30270000,
365
+
366
+ FSL_IMX7_GPIO7_ADDR = 0x30260000,
367
+ FSL_IMX7_GPIO6_ADDR = 0x30250000,
368
+ FSL_IMX7_GPIO5_ADDR = 0x30240000,
369
+ FSL_IMX7_GPIO4_ADDR = 0x30230000,
370
+ FSL_IMX7_GPIO3_ADDR = 0x30220000,
371
+ FSL_IMX7_GPIO2_ADDR = 0x30210000,
372
+ FSL_IMX7_GPIO1_ADDR = 0x30200000,
373
+
374
+ FSL_IMX7_AIPS1_CONF_ADDR = 0x301F0000,
375
+ FSL_IMX7_AIPS1_CONF_SIZE = (64 * KiB),
376
377
- FSL_IMX7_A7MPCORE_ADDR = 0x31000000,
378
FSL_IMX7_A7MPCORE_DAP_ADDR = 0x30000000,
379
+ FSL_IMX7_A7MPCORE_DAP_SIZE = (1 * MiB),
380
381
- FSL_IMX7_PCIE_REG_ADDR = 0x33800000,
382
- FSL_IMX7_PCIE_REG_SIZE = 16 * 1024,
383
+ /* AIPS-1 End */
384
385
- FSL_IMX7_GPR_ADDR = 0x30340000,
386
+ FSL_IMX7_EIM_CS0_ADDR = 0x28000000,
387
+ FSL_IMX7_EIM_CS0_SIZE = (128 * MiB),
388
389
- FSL_IMX7_DMA_APBH_ADDR = 0x33000000,
390
- FSL_IMX7_DMA_APBH_SIZE = 0x2000,
391
+ FSL_IMX7_OCRAM_PXP_ADDR = 0x00940000,
392
+ FSL_IMX7_OCRAM_PXP_SIZE = (32 * KiB),
393
+
394
+ FSL_IMX7_OCRAM_EPDC_ADDR = 0x00920000,
395
+ FSL_IMX7_OCRAM_EPDC_SIZE = (128 * KiB),
396
+
397
+ FSL_IMX7_OCRAM_MEM_ADDR = 0x00900000,
398
+ FSL_IMX7_OCRAM_MEM_SIZE = (128 * KiB),
399
+
400
+ FSL_IMX7_TCMU_ADDR = 0x00800000,
401
+ FSL_IMX7_TCMU_SIZE = (32 * KiB),
402
+
403
+ FSL_IMX7_TCML_ADDR = 0x007F8000,
404
+ FSL_IMX7_TCML_SIZE = (32 * KiB),
405
+
406
+ FSL_IMX7_OCRAM_S_ADDR = 0x00180000,
407
+ FSL_IMX7_OCRAM_S_SIZE = (32 * KiB),
408
+
409
+ FSL_IMX7_CAAM_MEM_ADDR = 0x00100000,
410
+ FSL_IMX7_CAAM_MEM_SIZE = (32 * KiB),
411
+
412
+ FSL_IMX7_ROM_ADDR = 0x00000000,
413
+ FSL_IMX7_ROM_SIZE = (96 * KiB),
414
};
415
416
enum FslIMX7IRQs {
417
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
418
index XXXXXXX..XXXXXXX 100644
419
--- a/hw/arm/fsl-imx7.c
420
+++ b/hw/arm/fsl-imx7.c
421
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_init(Object *obj)
422
char name[NAME_SIZE];
423
int i;
424
425
+ /*
426
+ * CPUs
427
+ */
428
for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX7_NUM_CPUS); i++) {
429
snprintf(name, NAME_SIZE, "cpu%d", i);
430
object_initialize_child(obj, name, &s->cpu[i],
431
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_init(Object *obj)
432
TYPE_A15MPCORE_PRIV);
433
434
/*
435
- * GPIOs 1 to 7
436
+ * GPIOs
437
*/
438
for (i = 0; i < FSL_IMX7_NUM_GPIOS; i++) {
439
snprintf(name, NAME_SIZE, "gpio%d", i);
440
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_init(Object *obj)
441
}
442
443
/*
444
- * GPT1, 2, 3, 4
445
+ * GPTs
446
*/
447
for (i = 0; i < FSL_IMX7_NUM_GPTS; i++) {
448
snprintf(name, NAME_SIZE, "gpt%d", i);
449
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_init(Object *obj)
450
*/
451
object_initialize_child(obj, "gpcv2", &s->gpcv2, TYPE_IMX_GPCV2);
452
453
+ /*
454
+ * ECSPIs
455
+ */
456
for (i = 0; i < FSL_IMX7_NUM_ECSPIS; i++) {
457
snprintf(name, NAME_SIZE, "spi%d", i + 1);
458
object_initialize_child(obj, name, &s->spi[i], TYPE_IMX_SPI);
459
}
460
461
-
462
+ /*
463
+ * I2Cs
464
+ */
465
for (i = 0; i < FSL_IMX7_NUM_I2CS; i++) {
466
snprintf(name, NAME_SIZE, "i2c%d", i + 1);
467
object_initialize_child(obj, name, &s->i2c[i], TYPE_IMX_I2C);
468
}
469
470
/*
471
- * UART
472
+ * UARTs
473
*/
474
for (i = 0; i < FSL_IMX7_NUM_UARTS; i++) {
475
snprintf(name, NAME_SIZE, "uart%d", i);
476
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_init(Object *obj)
477
}
478
479
/*
480
- * Ethernet
481
+ * Ethernets
482
*/
483
for (i = 0; i < FSL_IMX7_NUM_ETHS; i++) {
484
snprintf(name, NAME_SIZE, "eth%d", i);
485
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_init(Object *obj)
486
}
487
488
/*
489
- * SDHCI
490
+ * SDHCIs
491
*/
492
for (i = 0; i < FSL_IMX7_NUM_USDHCS; i++) {
493
snprintf(name, NAME_SIZE, "usdhc%d", i);
494
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_init(Object *obj)
495
object_initialize_child(obj, "snvs", &s->snvs, TYPE_IMX7_SNVS);
496
497
/*
498
- * Watchdog
499
+ * Watchdogs
500
*/
501
for (i = 0; i < FSL_IMX7_NUM_WDTS; i++) {
502
snprintf(name, NAME_SIZE, "wdt%d", i);
503
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_init(Object *obj)
504
*/
505
object_initialize_child(obj, "gpr", &s->gpr, TYPE_IMX7_GPR);
506
507
+ /*
508
+ * PCIE
509
+ */
510
object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST);
511
512
+ /*
513
+ * USBs
514
+ */
515
for (i = 0; i < FSL_IMX7_NUM_USBS; i++) {
516
snprintf(name, NAME_SIZE, "usb%d", i);
517
object_initialize_child(obj, name, &s->usb[i], TYPE_CHIPIDEA);
518
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
519
return;
520
}
521
522
+ /*
523
+ * CPUs
524
+ */
525
for (i = 0; i < smp_cpus; i++) {
526
o = OBJECT(&s->cpu[i]);
527
528
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
529
* A7MPCORE DAP
530
*/
531
create_unimplemented_device("a7mpcore-dap", FSL_IMX7_A7MPCORE_DAP_ADDR,
532
- 0x100000);
533
+ FSL_IMX7_A7MPCORE_DAP_SIZE);
534
535
/*
536
- * GPT1, 2, 3, 4
537
+ * GPTs
538
*/
539
for (i = 0; i < FSL_IMX7_NUM_GPTS; i++) {
540
static const hwaddr FSL_IMX7_GPTn_ADDR[FSL_IMX7_NUM_GPTS] = {
541
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
542
FSL_IMX7_GPTn_IRQ[i]));
543
}
544
545
+ /*
546
+ * GPIOs
547
+ */
548
for (i = 0; i < FSL_IMX7_NUM_GPIOS; i++) {
549
static const hwaddr FSL_IMX7_GPIOn_ADDR[FSL_IMX7_NUM_GPIOS] = {
550
FSL_IMX7_GPIO1_ADDR,
551
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
552
/*
553
* IOMUXC and IOMUXC_LPSR
554
*/
555
- for (i = 0; i < FSL_IMX7_NUM_IOMUXCS; i++) {
556
- static const hwaddr FSL_IMX7_IOMUXCn_ADDR[FSL_IMX7_NUM_IOMUXCS] = {
557
- FSL_IMX7_IOMUXC_ADDR,
558
- FSL_IMX7_IOMUXC_LPSR_ADDR,
559
- };
560
-
561
- snprintf(name, NAME_SIZE, "iomuxc%d", i);
562
- create_unimplemented_device(name, FSL_IMX7_IOMUXCn_ADDR[i],
563
- FSL_IMX7_IOMUXCn_SIZE);
564
- }
565
+ create_unimplemented_device("iomuxc", FSL_IMX7_IOMUXC_ADDR,
566
+ FSL_IMX7_IOMUXC_SIZE);
567
+ create_unimplemented_device("iomuxc_lspr", FSL_IMX7_IOMUXC_LPSR_ADDR,
568
+ FSL_IMX7_IOMUXC_LPSR_SIZE);
569
570
/*
571
* CCM
572
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
573
sysbus_realize(SYS_BUS_DEVICE(&s->gpcv2), &error_abort);
574
sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpcv2), 0, FSL_IMX7_GPC_ADDR);
575
576
- /* Initialize all ECSPI */
577
+ /*
578
+ * ECSPIs
579
+ */
580
for (i = 0; i < FSL_IMX7_NUM_ECSPIS; i++) {
581
static const hwaddr FSL_IMX7_SPIn_ADDR[FSL_IMX7_NUM_ECSPIS] = {
582
FSL_IMX7_ECSPI1_ADDR,
583
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
584
FSL_IMX7_SPIn_IRQ[i]));
585
}
586
587
+ /*
588
+ * I2Cs
589
+ */
590
for (i = 0; i < FSL_IMX7_NUM_I2CS; i++) {
591
static const hwaddr FSL_IMX7_I2Cn_ADDR[FSL_IMX7_NUM_I2CS] = {
592
FSL_IMX7_I2C1_ADDR,
593
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
594
}
595
596
/*
597
- * UART
598
+ * UARTs
599
*/
600
for (i = 0; i < FSL_IMX7_NUM_UARTS; i++) {
601
static const hwaddr FSL_IMX7_UARTn_ADDR[FSL_IMX7_NUM_UARTS] = {
602
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
603
}
604
605
/*
606
- * Ethernet
607
+ * Ethernets
608
*
609
* We must use two loops since phy_connected affects the other interface
610
* and we have to set all properties before calling sysbus_realize().
611
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
612
}
613
614
/*
615
- * USDHC
616
+ * USDHCs
617
*/
618
for (i = 0; i < FSL_IMX7_NUM_USDHCS; i++) {
619
static const hwaddr FSL_IMX7_USDHCn_ADDR[FSL_IMX7_NUM_USDHCS] = {
620
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
621
* SNVS
622
*/
623
sysbus_realize(SYS_BUS_DEVICE(&s->snvs), &error_abort);
624
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0, FSL_IMX7_SNVS_ADDR);
625
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->snvs), 0, FSL_IMX7_SNVS_HP_ADDR);
626
627
/*
628
* SRC
629
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
630
create_unimplemented_device("src", FSL_IMX7_SRC_ADDR, FSL_IMX7_SRC_SIZE);
631
632
/*
633
- * Watchdog
634
+ * Watchdogs
635
*/
636
for (i = 0; i < FSL_IMX7_NUM_WDTS; i++) {
637
static const hwaddr FSL_IMX7_WDOGn_ADDR[FSL_IMX7_NUM_WDTS] = {
638
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
639
create_unimplemented_device("caam", FSL_IMX7_CAAM_ADDR, FSL_IMX7_CAAM_SIZE);
640
641
/*
642
- * PWM
643
+ * PWMs
644
*/
645
- create_unimplemented_device("pwm1", FSL_IMX7_PWM1_ADDR, FSL_IMX7_PWMn_SIZE);
646
- create_unimplemented_device("pwm2", FSL_IMX7_PWM2_ADDR, FSL_IMX7_PWMn_SIZE);
647
- create_unimplemented_device("pwm3", FSL_IMX7_PWM3_ADDR, FSL_IMX7_PWMn_SIZE);
648
- create_unimplemented_device("pwm4", FSL_IMX7_PWM4_ADDR, FSL_IMX7_PWMn_SIZE);
649
+ for (i = 0; i < FSL_IMX7_NUM_PWMS; i++) {
650
+ static const hwaddr FSL_IMX7_PWMn_ADDR[FSL_IMX7_NUM_PWMS] = {
651
+ FSL_IMX7_PWM1_ADDR,
652
+ FSL_IMX7_PWM2_ADDR,
653
+ FSL_IMX7_PWM3_ADDR,
654
+ FSL_IMX7_PWM4_ADDR,
655
+ };
656
+
657
+ snprintf(name, NAME_SIZE, "pwm%d", i);
658
+ create_unimplemented_device(name, FSL_IMX7_PWMn_ADDR[i],
659
+ FSL_IMX7_PWMn_SIZE);
47
+ }
660
+ }
48
+
661
49
+ filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
662
/*
50
+ if (!filename) {
663
- * CAN
51
+ error_report("Could not find ROM image '%s'", bios_name);
664
+ * CANs
52
+ if (!machine->kernel_filename) {
665
*/
53
+ /* We can't boot without a bootrom or a kernel image. */
666
- create_unimplemented_device("can1", FSL_IMX7_CAN1_ADDR, FSL_IMX7_CANn_SIZE);
54
+ exit(1);
667
- create_unimplemented_device("can2", FSL_IMX7_CAN2_ADDR, FSL_IMX7_CANn_SIZE);
55
+ }
668
+ for (i = 0; i < FSL_IMX7_NUM_CANS; i++) {
56
+ return;
669
+ static const hwaddr FSL_IMX7_CANn_ADDR[FSL_IMX7_NUM_CANS] = {
670
+ FSL_IMX7_CAN1_ADDR,
671
+ FSL_IMX7_CAN2_ADDR,
672
+ };
673
+
674
+ snprintf(name, NAME_SIZE, "can%d", i);
675
+ create_unimplemented_device(name, FSL_IMX7_CANn_ADDR[i],
676
+ FSL_IMX7_CANn_SIZE);
57
+ }
677
+ }
58
+ ret = load_image_mr(filename, &soc->irom);
678
59
+ if (ret < 0) {
679
/*
60
+ error_report("Failed to load ROM image '%s'", filename);
680
- * SAI (Audio SSI (Synchronous Serial Interface))
61
+ exit(1);
681
+ * SAIs (Audio SSI (Synchronous Serial Interface))
682
*/
683
- create_unimplemented_device("sai1", FSL_IMX7_SAI1_ADDR, FSL_IMX7_SAIn_SIZE);
684
- create_unimplemented_device("sai2", FSL_IMX7_SAI2_ADDR, FSL_IMX7_SAIn_SIZE);
685
- create_unimplemented_device("sai2", FSL_IMX7_SAI3_ADDR, FSL_IMX7_SAIn_SIZE);
686
+ for (i = 0; i < FSL_IMX7_NUM_SAIS; i++) {
687
+ static const hwaddr FSL_IMX7_SAIn_ADDR[FSL_IMX7_NUM_SAIS] = {
688
+ FSL_IMX7_SAI1_ADDR,
689
+ FSL_IMX7_SAI2_ADDR,
690
+ FSL_IMX7_SAI3_ADDR,
691
+ };
692
+
693
+ snprintf(name, NAME_SIZE, "sai%d", i);
694
+ create_unimplemented_device(name, FSL_IMX7_SAIn_ADDR[i],
695
+ FSL_IMX7_SAIn_SIZE);
62
+ }
696
+ }
63
+}
697
64
+
698
/*
65
static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
699
* OCOTP
66
{
700
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
67
memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, dram);
701
create_unimplemented_device("ocotp", FSL_IMX7_OCOTP_ADDR,
68
@@ -XXX,XX +XXX,XX @@ static void npcm750_evb_init(MachineState *machine)
702
FSL_IMX7_OCOTP_SIZE);
69
npcm7xx_connect_dram(soc, machine->ram);
703
70
qdev_realize(DEVICE(soc), NULL, &error_fatal);
704
+ /*
71
705
+ * GPR
72
+ npcm7xx_load_bootrom(machine, soc);
706
+ */
73
npcm7xx_load_kernel(machine, soc);
707
sysbus_realize(SYS_BUS_DEVICE(&s->gpr), &error_abort);
708
- sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpr), 0, FSL_IMX7_GPR_ADDR);
709
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpr), 0, FSL_IMX7_IOMUXC_GPR_ADDR);
710
711
+ /*
712
+ * PCIE
713
+ */
714
sysbus_realize(SYS_BUS_DEVICE(&s->pcie), &error_abort);
715
sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie), 0, FSL_IMX7_PCIE_REG_ADDR);
716
717
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
718
irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTD_IRQ);
719
sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 3, irq);
720
721
-
722
+ /*
723
+ * USBs
724
+ */
725
for (i = 0; i < FSL_IMX7_NUM_USBS; i++) {
726
static const hwaddr FSL_IMX7_USBMISCn_ADDR[FSL_IMX7_NUM_USBS] = {
727
FSL_IMX7_USBMISC1_ADDR,
728
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
729
*/
730
create_unimplemented_device("pcie-phy", FSL_IMX7_PCIE_PHY_ADDR,
731
FSL_IMX7_PCIE_PHY_SIZE);
732
+
74
}
733
}
75
734
76
@@ -XXX,XX +XXX,XX @@ static void quanta_gsj_init(MachineState *machine)
735
static Property fsl_imx7_properties[] = {
77
npcm7xx_connect_dram(soc, machine->ram);
78
qdev_realize(DEVICE(soc), NULL, &error_fatal);
79
80
+ npcm7xx_load_bootrom(machine, soc);
81
npcm7xx_load_kernel(machine, soc);
82
}
83
84
--
736
--
85
2.20.1
737
2.34.1
86
87
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Jean-Christophe Dubois <jcd@tribudubois.net>
2
2
3
This supports reading and writing OTP fuses and keys. Only fuse reading
3
* Add TZASC as unimplemented device.
4
has been tested. Protection is not implemented.
4
- Allow bare metal application to access this (unimplemented) device
5
* Add CSU as unimplemented device.
6
- Allow bare metal application to access this (unimplemented) device
7
* Add various memory segments
8
- OCRAM
9
- OCRAM EPDC
10
- OCRAM PXP
11
- OCRAM S
12
- ROM
13
- CAAM
5
14
6
Reviewed-by: Avi Fishman <avi.fishman@nuvoton.com>
15
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Message-id: f887a3483996ba06d40bd62ffdfb0ecf68621987.1692964892.git.jcd@tribudubois.net
9
Tested-by: Alexander Bulekov <alxndr@bu.edu>
10
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
11
Message-id: 20200911052101.2602693-9-hskinnemoen@google.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
19
---
14
include/hw/arm/npcm7xx.h | 3 +
20
include/hw/arm/fsl-imx7.h | 7 +++++
15
include/hw/nvram/npcm7xx_otp.h | 79 ++++++
21
hw/arm/fsl-imx7.c | 63 +++++++++++++++++++++++++++++++++++++++
16
hw/arm/npcm7xx.c | 29 +++
22
2 files changed, 70 insertions(+)
17
hw/nvram/npcm7xx_otp.c | 440 +++++++++++++++++++++++++++++++++
18
hw/nvram/meson.build | 1 +
19
5 files changed, 552 insertions(+)
20
create mode 100644 include/hw/nvram/npcm7xx_otp.h
21
create mode 100644 hw/nvram/npcm7xx_otp.c
22
23
23
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
24
diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h
24
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/arm/npcm7xx.h
26
--- a/include/hw/arm/fsl-imx7.h
26
+++ b/include/hw/arm/npcm7xx.h
27
+++ b/include/hw/arm/fsl-imx7.h
27
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@ struct FslIMX7State {
28
#include "hw/cpu/a9mpcore.h"
29
IMX7GPRState gpr;
29
#include "hw/misc/npcm7xx_clk.h"
30
ChipideaState usb[FSL_IMX7_NUM_USBS];
30
#include "hw/misc/npcm7xx_gcr.h"
31
DesignwarePCIEHost pcie;
31
+#include "hw/nvram/npcm7xx_otp.h"
32
+ MemoryRegion rom;
32
#include "hw/timer/npcm7xx_timer.h"
33
+ MemoryRegion caam;
33
#include "target/arm/cpu.h"
34
+ MemoryRegion ocram;
34
35
+ MemoryRegion ocram_epdc;
35
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
36
+ MemoryRegion ocram_pxp;
36
NPCM7xxGCRState gcr;
37
+ MemoryRegion ocram_s;
37
NPCM7xxCLKState clk;
38
NPCM7xxTimerCtrlState tim[3];
39
+ NPCM7xxOTPState key_storage;
40
+ NPCM7xxOTPState fuse_array;
41
} NPCM7xxState;
42
43
#define TYPE_NPCM7XX "npcm7xx"
44
diff --git a/include/hw/nvram/npcm7xx_otp.h b/include/hw/nvram/npcm7xx_otp.h
45
new file mode 100644
46
index XXXXXXX..XXXXXXX
47
--- /dev/null
48
+++ b/include/hw/nvram/npcm7xx_otp.h
49
@@ -XXX,XX +XXX,XX @@
50
+/*
51
+ * Nuvoton NPCM7xx OTP (Fuse Array) Interface
52
+ *
53
+ * Copyright 2020 Google LLC
54
+ *
55
+ * This program is free software; you can redistribute it and/or modify it
56
+ * under the terms of the GNU General Public License as published by the
57
+ * Free Software Foundation; either version 2 of the License, or
58
+ * (at your option) any later version.
59
+ *
60
+ * This program is distributed in the hope that it will be useful, but WITHOUT
61
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
62
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
63
+ * for more details.
64
+ */
65
+#ifndef NPCM7XX_OTP_H
66
+#define NPCM7XX_OTP_H
67
+
38
+
68
+#include "exec/memory.h"
39
uint32_t phy_num[FSL_IMX7_NUM_ETHS];
69
+#include "hw/sysbus.h"
40
bool phy_connected[FSL_IMX7_NUM_ETHS];
70
+
41
};
71
+/* Each OTP module holds 8192 bits of one-time programmable storage */
42
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
72
+#define NPCM7XX_OTP_ARRAY_BITS (8192)
73
+#define NPCM7XX_OTP_ARRAY_BYTES (NPCM7XX_OTP_ARRAY_BITS / BITS_PER_BYTE)
74
+
75
+/* Fuse array offsets */
76
+#define NPCM7XX_FUSE_FUSTRAP (0)
77
+#define NPCM7XX_FUSE_CP_FUSTRAP (12)
78
+#define NPCM7XX_FUSE_DAC_CALIB (16)
79
+#define NPCM7XX_FUSE_ADC_CALIB (24)
80
+#define NPCM7XX_FUSE_DERIVATIVE (64)
81
+#define NPCM7XX_FUSE_TEST_SIG (72)
82
+#define NPCM7XX_FUSE_DIE_LOCATION (74)
83
+#define NPCM7XX_FUSE_GP1 (80)
84
+#define NPCM7XX_FUSE_GP2 (128)
85
+
86
+/*
87
+ * Number of registers in our device state structure. Don't change this without
88
+ * incrementing the version_id in the vmstate.
89
+ */
90
+#define NPCM7XX_OTP_NR_REGS (0x18 / sizeof(uint32_t))
91
+
92
+/**
93
+ * struct NPCM7xxOTPState - Device state for one OTP module.
94
+ * @parent: System bus device.
95
+ * @mmio: Memory region through which registers are accessed.
96
+ * @regs: Register contents.
97
+ * @array: OTP storage array.
98
+ */
99
+typedef struct NPCM7xxOTPState {
100
+ SysBusDevice parent;
101
+
102
+ MemoryRegion mmio;
103
+ uint32_t regs[NPCM7XX_OTP_NR_REGS];
104
+ uint8_t array[NPCM7XX_OTP_ARRAY_BYTES];
105
+} NPCM7xxOTPState;
106
+
107
+#define TYPE_NPCM7XX_OTP "npcm7xx-otp"
108
+#define NPCM7XX_OTP(obj) OBJECT_CHECK(NPCM7xxOTPState, (obj), TYPE_NPCM7XX_OTP)
109
+
110
+#define TYPE_NPCM7XX_KEY_STORAGE "npcm7xx-key-storage"
111
+#define TYPE_NPCM7XX_FUSE_ARRAY "npcm7xx-fuse-array"
112
+
113
+typedef struct NPCM7xxOTPClass NPCM7xxOTPClass;
114
+
115
+/**
116
+ * npcm7xx_otp_array_write - ECC encode and write data to OTP array.
117
+ * @s: OTP module.
118
+ * @data: Data to be encoded and written.
119
+ * @offset: Offset of first byte to be written in the OTP array.
120
+ * @len: Number of bytes before ECC encoding.
121
+ *
122
+ * Each nibble of data is encoded into a byte, so the number of bytes written
123
+ * to the array will be @len * 2.
124
+ */
125
+extern void npcm7xx_otp_array_write(NPCM7xxOTPState *s, const void *data,
126
+ unsigned int offset, unsigned int len);
127
+
128
+#endif /* NPCM7XX_OTP_H */
129
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
130
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
131
--- a/hw/arm/npcm7xx.c
44
--- a/hw/arm/fsl-imx7.c
132
+++ b/hw/arm/npcm7xx.c
45
+++ b/hw/arm/fsl-imx7.c
133
@@ -XXX,XX +XXX,XX @@
46
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
134
#define NPCM7XX_MMIO_BA (0x80000000)
47
create_unimplemented_device("pcie-phy", FSL_IMX7_PCIE_PHY_ADDR,
135
#define NPCM7XX_MMIO_SZ (0x7ffd0000)
48
FSL_IMX7_PCIE_PHY_SIZE);
136
49
137
+/* OTP key storage and fuse strap array */
50
+ /*
138
+#define NPCM7XX_OTP1_BA (0xf0189000)
51
+ * CSU
139
+#define NPCM7XX_OTP2_BA (0xf018a000)
52
+ */
140
+
53
+ create_unimplemented_device("csu", FSL_IMX7_CSU_ADDR,
141
/* Core system modules. */
54
+ FSL_IMX7_CSU_SIZE);
142
#define NPCM7XX_L2C_BA (0xf03fc000)
143
#define NPCM7XX_CPUP_BA (0xf03fe000)
144
@@ -XXX,XX +XXX,XX @@ void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
145
arm_load_kernel(&soc->cpu[0], machine, &npcm7xx_binfo);
146
}
147
148
+static void npcm7xx_init_fuses(NPCM7xxState *s)
149
+{
150
+ NPCM7xxClass *nc = NPCM7XX_GET_CLASS(s);
151
+ uint32_t value;
152
+
55
+
153
+ /*
56
+ /*
154
+ * The initial mask of disabled modules indicates the chip derivative (e.g.
57
+ * TZASC
155
+ * NPCM750 or NPCM730).
156
+ */
58
+ */
157
+ value = tswap32(nc->disabled_modules);
59
+ create_unimplemented_device("tzasc", FSL_IMX7_TZASC_ADDR,
158
+ npcm7xx_otp_array_write(&s->fuse_array, &value, NPCM7XX_FUSE_DERIVATIVE,
60
+ FSL_IMX7_TZASC_SIZE);
159
+ sizeof(value));
160
+}
161
+
162
static qemu_irq npcm7xx_irq(NPCM7xxState *s, int n)
163
{
164
return qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
165
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
166
object_property_add_alias(obj, "power-on-straps", OBJECT(&s->gcr),
167
"power-on-straps");
168
object_initialize_child(obj, "clk", &s->clk, TYPE_NPCM7XX_CLK);
169
+ object_initialize_child(obj, "otp1", &s->key_storage,
170
+ TYPE_NPCM7XX_KEY_STORAGE);
171
+ object_initialize_child(obj, "otp2", &s->fuse_array,
172
+ TYPE_NPCM7XX_FUSE_ARRAY);
173
174
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
175
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
176
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
177
sysbus_realize(SYS_BUS_DEVICE(&s->clk), &error_abort);
178
sysbus_mmio_map(SYS_BUS_DEVICE(&s->clk), 0, NPCM7XX_CLK_BA);
179
180
+ /* OTP key storage and fuse strap array. Cannot fail. */
181
+ sysbus_realize(SYS_BUS_DEVICE(&s->key_storage), &error_abort);
182
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->key_storage), 0, NPCM7XX_OTP1_BA);
183
+ sysbus_realize(SYS_BUS_DEVICE(&s->fuse_array), &error_abort);
184
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->fuse_array), 0, NPCM7XX_OTP2_BA);
185
+ npcm7xx_init_fuses(s);
186
+
187
/* Timer Modules (TIM). Cannot fail. */
188
QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
189
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
190
diff --git a/hw/nvram/npcm7xx_otp.c b/hw/nvram/npcm7xx_otp.c
191
new file mode 100644
192
index XXXXXXX..XXXXXXX
193
--- /dev/null
194
+++ b/hw/nvram/npcm7xx_otp.c
195
@@ -XXX,XX +XXX,XX @@
196
+/*
197
+ * Nuvoton NPCM7xx OTP (Fuse Array) Interface
198
+ *
199
+ * Copyright 2020 Google LLC
200
+ *
201
+ * This program is free software; you can redistribute it and/or modify it
202
+ * under the terms of the GNU General Public License as published by the
203
+ * Free Software Foundation; either version 2 of the License, or
204
+ * (at your option) any later version.
205
+ *
206
+ * This program is distributed in the hope that it will be useful, but WITHOUT
207
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
208
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
209
+ * for more details.
210
+ */
211
+
212
+#include "qemu/osdep.h"
213
+
214
+#include "hw/nvram/npcm7xx_otp.h"
215
+#include "migration/vmstate.h"
216
+#include "qapi/error.h"
217
+#include "qemu/bitops.h"
218
+#include "qemu/log.h"
219
+#include "qemu/module.h"
220
+#include "qemu/units.h"
221
+
222
+/* Each module has 4 KiB of register space. Only a fraction of it is used. */
223
+#define NPCM7XX_OTP_REGS_SIZE (4 * KiB)
224
+
225
+/* 32-bit register indices. */
226
+typedef enum NPCM7xxOTPRegister {
227
+ NPCM7XX_OTP_FST,
228
+ NPCM7XX_OTP_FADDR,
229
+ NPCM7XX_OTP_FDATA,
230
+ NPCM7XX_OTP_FCFG,
231
+ /* Offset 0x10 is FKEYIND in OTP1, FUSTRAP in OTP2 */
232
+ NPCM7XX_OTP_FKEYIND = 0x0010 / sizeof(uint32_t),
233
+ NPCM7XX_OTP_FUSTRAP = 0x0010 / sizeof(uint32_t),
234
+ NPCM7XX_OTP_FCTL,
235
+ NPCM7XX_OTP_REGS_END,
236
+} NPCM7xxOTPRegister;
237
+
238
+/* Register field definitions. */
239
+#define FST_RIEN BIT(2)
240
+#define FST_RDST BIT(1)
241
+#define FST_RDY BIT(0)
242
+#define FST_RO_MASK (FST_RDST | FST_RDY)
243
+
244
+#define FADDR_BYTEADDR(rv) extract32((rv), 0, 10)
245
+#define FADDR_BITPOS(rv) extract32((rv), 10, 3)
246
+
247
+#define FDATA_CLEAR 0x00000001
248
+
249
+#define FCFG_FDIS BIT(31)
250
+#define FCFG_FCFGLK_MASK 0x00ff0000
251
+
252
+#define FCTL_PROG_CMD1 0x00000001
253
+#define FCTL_PROG_CMD2 0xbf79e5d0
254
+#define FCTL_READ_CMD 0x00000002
255
+
256
+/**
257
+ * struct NPCM7xxOTPClass - OTP module class.
258
+ * @parent: System bus device class.
259
+ * @mmio_ops: MMIO register operations for this type of module.
260
+ *
261
+ * The two OTP modules (key-storage and fuse-array) have slightly different
262
+ * behavior, so we give them different MMIO register operations.
263
+ */
264
+struct NPCM7xxOTPClass {
265
+ SysBusDeviceClass parent;
266
+
267
+ const MemoryRegionOps *mmio_ops;
268
+};
269
+
270
+#define NPCM7XX_OTP_CLASS(klass) \
271
+ OBJECT_CLASS_CHECK(NPCM7xxOTPClass, (klass), TYPE_NPCM7XX_OTP)
272
+#define NPCM7XX_OTP_GET_CLASS(obj) \
273
+ OBJECT_GET_CLASS(NPCM7xxOTPClass, (obj), TYPE_NPCM7XX_OTP)
274
+
275
+static uint8_t ecc_encode_nibble(uint8_t n)
276
+{
277
+ uint8_t result = n;
278
+
279
+ result |= (((n >> 0) & 1) ^ ((n >> 1) & 1)) << 4;
280
+ result |= (((n >> 2) & 1) ^ ((n >> 3) & 1)) << 5;
281
+ result |= (((n >> 0) & 1) ^ ((n >> 2) & 1)) << 6;
282
+ result |= (((n >> 1) & 1) ^ ((n >> 3) & 1)) << 7;
283
+
284
+ return result;
285
+}
286
+
287
+void npcm7xx_otp_array_write(NPCM7xxOTPState *s, const void *data,
288
+ unsigned int offset, unsigned int len)
289
+{
290
+ const uint8_t *src = data;
291
+ uint8_t *dst = &s->array[offset];
292
+
293
+ while (len-- > 0) {
294
+ uint8_t c = *src++;
295
+
296
+ *dst++ = ecc_encode_nibble(extract8(c, 0, 4));
297
+ *dst++ = ecc_encode_nibble(extract8(c, 4, 4));
298
+ }
299
+}
300
+
301
+/* Common register read handler for both OTP classes. */
302
+static uint64_t npcm7xx_otp_read(NPCM7xxOTPState *s, NPCM7xxOTPRegister reg)
303
+{
304
+ uint32_t value = 0;
305
+
306
+ switch (reg) {
307
+ case NPCM7XX_OTP_FST:
308
+ case NPCM7XX_OTP_FADDR:
309
+ case NPCM7XX_OTP_FDATA:
310
+ case NPCM7XX_OTP_FCFG:
311
+ value = s->regs[reg];
312
+ break;
313
+
314
+ case NPCM7XX_OTP_FCTL:
315
+ qemu_log_mask(LOG_GUEST_ERROR,
316
+ "%s: read from write-only FCTL register\n",
317
+ DEVICE(s)->canonical_path);
318
+ break;
319
+
320
+ default:
321
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: read from invalid offset 0x%zx\n",
322
+ DEVICE(s)->canonical_path, reg * sizeof(uint32_t));
323
+ break;
324
+ }
325
+
326
+ return value;
327
+}
328
+
329
+/* Read a byte from the OTP array into the data register. */
330
+static void npcm7xx_otp_read_array(NPCM7xxOTPState *s)
331
+{
332
+ uint32_t faddr = s->regs[NPCM7XX_OTP_FADDR];
333
+
334
+ s->regs[NPCM7XX_OTP_FDATA] = s->array[FADDR_BYTEADDR(faddr)];
335
+ s->regs[NPCM7XX_OTP_FST] |= FST_RDST | FST_RDY;
336
+}
337
+
338
+/* Program a byte from the data register into the OTP array. */
339
+static void npcm7xx_otp_program_array(NPCM7xxOTPState *s)
340
+{
341
+ uint32_t faddr = s->regs[NPCM7XX_OTP_FADDR];
342
+
343
+ /* Bits can only go 0->1, never 1->0. */
344
+ s->array[FADDR_BYTEADDR(faddr)] |= (1U << FADDR_BITPOS(faddr));
345
+ s->regs[NPCM7XX_OTP_FST] |= FST_RDST | FST_RDY;
346
+}
347
+
348
+/* Compute the next value of the FCFG register. */
349
+static uint32_t npcm7xx_otp_compute_fcfg(uint32_t cur_value, uint32_t new_value)
350
+{
351
+ uint32_t lock_mask;
352
+ uint32_t value;
353
+
61
+
354
+ /*
62
+ /*
355
+ * FCFGLK holds sticky bits 16..23, indicating which bits in FPRGLK (8..15)
63
+ * OCRAM memory
356
+ * and FRDLK (0..7) that are read-only.
357
+ */
64
+ */
358
+ lock_mask = (cur_value & FCFG_FCFGLK_MASK) >> 8;
65
+ memory_region_init_ram(&s->ocram, NULL, "imx7.ocram",
359
+ lock_mask |= lock_mask >> 8;
66
+ FSL_IMX7_OCRAM_MEM_SIZE,
360
+ /* FDIS and FCFGLK bits are sticky (write 1 to set; can't clear). */
67
+ &error_abort);
361
+ value = cur_value & (FCFG_FDIS | FCFG_FCFGLK_MASK);
68
+ memory_region_add_subregion(get_system_memory(), FSL_IMX7_OCRAM_MEM_ADDR,
362
+ /* Preserve read-only bits in FPRGLK and FRDLK */
69
+ &s->ocram);
363
+ value |= cur_value & lock_mask;
364
+ /* Set all bits that aren't read-only. */
365
+ value |= new_value & ~lock_mask;
366
+
367
+ return value;
368
+}
369
+
370
+/* Common register write handler for both OTP classes. */
371
+static void npcm7xx_otp_write(NPCM7xxOTPState *s, NPCM7xxOTPRegister reg,
372
+ uint32_t value)
373
+{
374
+ switch (reg) {
375
+ case NPCM7XX_OTP_FST:
376
+ /* RDST is cleared by writing 1 to it. */
377
+ if (value & FST_RDST) {
378
+ s->regs[NPCM7XX_OTP_FST] &= ~FST_RDST;
379
+ }
380
+ /* Preserve read-only and write-one-to-clear bits */
381
+ value &= ~FST_RO_MASK;
382
+ value |= s->regs[NPCM7XX_OTP_FST] & FST_RO_MASK;
383
+ break;
384
+
385
+ case NPCM7XX_OTP_FADDR:
386
+ break;
387
+
388
+ case NPCM7XX_OTP_FDATA:
389
+ /*
390
+ * This register is cleared by writing a magic value to it; no other
391
+ * values can be written.
392
+ */
393
+ if (value == FDATA_CLEAR) {
394
+ value = 0;
395
+ } else {
396
+ value = s->regs[NPCM7XX_OTP_FDATA];
397
+ }
398
+ break;
399
+
400
+ case NPCM7XX_OTP_FCFG:
401
+ value = npcm7xx_otp_compute_fcfg(s->regs[NPCM7XX_OTP_FCFG], value);
402
+ break;
403
+
404
+ case NPCM7XX_OTP_FCTL:
405
+ switch (value) {
406
+ case FCTL_READ_CMD:
407
+ npcm7xx_otp_read_array(s);
408
+ break;
409
+
410
+ case FCTL_PROG_CMD1:
411
+ /*
412
+ * Programming requires writing two separate magic values to this
413
+ * register; this is the first one. Just store it so it can be
414
+ * verified later when the second magic value is received.
415
+ */
416
+ break;
417
+
418
+ case FCTL_PROG_CMD2:
419
+ /*
420
+ * Only initiate programming if we received the first half of the
421
+ * command immediately before this one.
422
+ */
423
+ if (s->regs[NPCM7XX_OTP_FCTL] == FCTL_PROG_CMD1) {
424
+ npcm7xx_otp_program_array(s);
425
+ }
426
+ break;
427
+
428
+ default:
429
+ qemu_log_mask(LOG_GUEST_ERROR,
430
+ "%s: unrecognized FCNTL value 0x%" PRIx32 "\n",
431
+ DEVICE(s)->canonical_path, value);
432
+ break;
433
+ }
434
+ if (value != FCTL_PROG_CMD1) {
435
+ value = 0;
436
+ }
437
+ break;
438
+
439
+ default:
440
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: write to invalid offset 0x%zx\n",
441
+ DEVICE(s)->canonical_path, reg * sizeof(uint32_t));
442
+ return;
443
+ }
444
+
445
+ s->regs[reg] = value;
446
+}
447
+
448
+/* Register read handler specific to the fuse array OTP module. */
449
+static uint64_t npcm7xx_fuse_array_read(void *opaque, hwaddr addr,
450
+ unsigned int size)
451
+{
452
+ NPCM7xxOTPRegister reg = addr / sizeof(uint32_t);
453
+ NPCM7xxOTPState *s = opaque;
454
+ uint32_t value;
455
+
70
+
456
+ /*
71
+ /*
457
+ * Only the Fuse Strap register needs special handling; all other registers
72
+ * OCRAM EPDC memory
458
+ * work the same way for both kinds of OTP modules.
459
+ */
73
+ */
460
+ if (reg != NPCM7XX_OTP_FUSTRAP) {
74
+ memory_region_init_ram(&s->ocram_epdc, NULL, "imx7.ocram_epdc",
461
+ value = npcm7xx_otp_read(s, reg);
75
+ FSL_IMX7_OCRAM_EPDC_SIZE,
462
+ } else {
76
+ &error_abort);
463
+ /* FUSTRAP is stored as three copies in the OTP array. */
77
+ memory_region_add_subregion(get_system_memory(), FSL_IMX7_OCRAM_EPDC_ADDR,
464
+ uint32_t fustrap[3];
78
+ &s->ocram_epdc);
465
+
466
+ memcpy(fustrap, &s->array[0], sizeof(fustrap));
467
+
468
+ /* Determine value by a majority vote on each bit. */
469
+ value = (fustrap[0] & fustrap[1]) | (fustrap[0] & fustrap[2]) |
470
+ (fustrap[1] & fustrap[2]);
471
+ }
472
+
473
+ return value;
474
+}
475
+
476
+/* Register write handler specific to the fuse array OTP module. */
477
+static void npcm7xx_fuse_array_write(void *opaque, hwaddr addr, uint64_t v,
478
+ unsigned int size)
479
+{
480
+ NPCM7xxOTPRegister reg = addr / sizeof(uint32_t);
481
+ NPCM7xxOTPState *s = opaque;
482
+
79
+
483
+ /*
80
+ /*
484
+ * The Fuse Strap register is read-only. Other registers are handled by
81
+ * OCRAM PXP memory
485
+ * common code.
486
+ */
82
+ */
487
+ if (reg != NPCM7XX_OTP_FUSTRAP) {
83
+ memory_region_init_ram(&s->ocram_pxp, NULL, "imx7.ocram_pxp",
488
+ npcm7xx_otp_write(s, reg, v);
84
+ FSL_IMX7_OCRAM_PXP_SIZE,
489
+ }
85
+ &error_abort);
490
+}
86
+ memory_region_add_subregion(get_system_memory(), FSL_IMX7_OCRAM_PXP_ADDR,
491
+
87
+ &s->ocram_pxp);
492
+static const MemoryRegionOps npcm7xx_fuse_array_ops = {
493
+ .read = npcm7xx_fuse_array_read,
494
+ .write = npcm7xx_fuse_array_write,
495
+ .endianness = DEVICE_LITTLE_ENDIAN,
496
+ .valid = {
497
+ .min_access_size = 4,
498
+ .max_access_size = 4,
499
+ .unaligned = false,
500
+ },
501
+};
502
+
503
+/* Register read handler specific to the key storage OTP module. */
504
+static uint64_t npcm7xx_key_storage_read(void *opaque, hwaddr addr,
505
+ unsigned int size)
506
+{
507
+ NPCM7xxOTPRegister reg = addr / sizeof(uint32_t);
508
+ NPCM7xxOTPState *s = opaque;
509
+
88
+
510
+ /*
89
+ /*
511
+ * Only the Fuse Key Index register needs special handling; all other
90
+ * OCRAM_S memory
512
+ * registers work the same way for both kinds of OTP modules.
513
+ */
91
+ */
514
+ if (reg != NPCM7XX_OTP_FKEYIND) {
92
+ memory_region_init_ram(&s->ocram_s, NULL, "imx7.ocram_s",
515
+ return npcm7xx_otp_read(s, reg);
93
+ FSL_IMX7_OCRAM_S_SIZE,
516
+ }
94
+ &error_abort);
517
+
95
+ memory_region_add_subregion(get_system_memory(), FSL_IMX7_OCRAM_S_ADDR,
518
+ qemu_log_mask(LOG_UNIMP, "%s: FKEYIND is not implemented\n", __func__);
96
+ &s->ocram_s);
519
+
520
+ return s->regs[NPCM7XX_OTP_FKEYIND];
521
+}
522
+
523
+/* Register write handler specific to the key storage OTP module. */
524
+static void npcm7xx_key_storage_write(void *opaque, hwaddr addr, uint64_t v,
525
+ unsigned int size)
526
+{
527
+ NPCM7xxOTPRegister reg = addr / sizeof(uint32_t);
528
+ NPCM7xxOTPState *s = opaque;
529
+
97
+
530
+ /*
98
+ /*
531
+ * Only the Fuse Key Index register needs special handling; all other
99
+ * ROM memory
532
+ * registers work the same way for both kinds of OTP modules.
533
+ */
100
+ */
534
+ if (reg != NPCM7XX_OTP_FKEYIND) {
101
+ memory_region_init_rom(&s->rom, OBJECT(dev), "imx7.rom",
535
+ npcm7xx_otp_write(s, reg, v);
102
+ FSL_IMX7_ROM_SIZE, &error_abort);
536
+ return;
103
+ memory_region_add_subregion(get_system_memory(), FSL_IMX7_ROM_ADDR,
537
+ }
104
+ &s->rom);
538
+
105
+
539
+ qemu_log_mask(LOG_UNIMP, "%s: FKEYIND is not implemented\n", __func__);
106
+ /*
540
+
107
+ * CAAM memory
541
+ s->regs[NPCM7XX_OTP_FKEYIND] = v;
108
+ */
542
+}
109
+ memory_region_init_rom(&s->caam, OBJECT(dev), "imx7.caam",
543
+
110
+ FSL_IMX7_CAAM_MEM_SIZE, &error_abort);
544
+static const MemoryRegionOps npcm7xx_key_storage_ops = {
111
+ memory_region_add_subregion(get_system_memory(), FSL_IMX7_CAAM_MEM_ADDR,
545
+ .read = npcm7xx_key_storage_read,
112
+ &s->caam);
546
+ .write = npcm7xx_key_storage_write,
113
}
547
+ .endianness = DEVICE_LITTLE_ENDIAN,
114
548
+ .valid = {
115
static Property fsl_imx7_properties[] = {
549
+ .min_access_size = 4,
550
+ .max_access_size = 4,
551
+ .unaligned = false,
552
+ },
553
+};
554
+
555
+static void npcm7xx_otp_enter_reset(Object *obj, ResetType type)
556
+{
557
+ NPCM7xxOTPState *s = NPCM7XX_OTP(obj);
558
+
559
+ memset(s->regs, 0, sizeof(s->regs));
560
+
561
+ s->regs[NPCM7XX_OTP_FST] = 0x00000001;
562
+ s->regs[NPCM7XX_OTP_FCFG] = 0x20000000;
563
+}
564
+
565
+static void npcm7xx_otp_realize(DeviceState *dev, Error **errp)
566
+{
567
+ NPCM7xxOTPClass *oc = NPCM7XX_OTP_GET_CLASS(dev);
568
+ NPCM7xxOTPState *s = NPCM7XX_OTP(dev);
569
+ SysBusDevice *sbd = &s->parent;
570
+
571
+ memset(s->array, 0, sizeof(s->array));
572
+
573
+ memory_region_init_io(&s->mmio, OBJECT(s), oc->mmio_ops, s, "regs",
574
+ NPCM7XX_OTP_REGS_SIZE);
575
+ sysbus_init_mmio(sbd, &s->mmio);
576
+}
577
+
578
+static const VMStateDescription vmstate_npcm7xx_otp = {
579
+ .name = "npcm7xx-otp",
580
+ .version_id = 0,
581
+ .minimum_version_id = 0,
582
+ .fields = (VMStateField[]) {
583
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxOTPState, NPCM7XX_OTP_NR_REGS),
584
+ VMSTATE_UINT8_ARRAY(array, NPCM7xxOTPState, NPCM7XX_OTP_ARRAY_BYTES),
585
+ VMSTATE_END_OF_LIST(),
586
+ },
587
+};
588
+
589
+static void npcm7xx_otp_class_init(ObjectClass *klass, void *data)
590
+{
591
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
592
+ DeviceClass *dc = DEVICE_CLASS(klass);
593
+
594
+ QEMU_BUILD_BUG_ON(NPCM7XX_OTP_REGS_END > NPCM7XX_OTP_NR_REGS);
595
+
596
+ dc->realize = npcm7xx_otp_realize;
597
+ dc->vmsd = &vmstate_npcm7xx_otp;
598
+ rc->phases.enter = npcm7xx_otp_enter_reset;
599
+}
600
+
601
+static void npcm7xx_key_storage_class_init(ObjectClass *klass, void *data)
602
+{
603
+ NPCM7xxOTPClass *oc = NPCM7XX_OTP_CLASS(klass);
604
+
605
+ oc->mmio_ops = &npcm7xx_key_storage_ops;
606
+}
607
+
608
+static void npcm7xx_fuse_array_class_init(ObjectClass *klass, void *data)
609
+{
610
+ NPCM7xxOTPClass *oc = NPCM7XX_OTP_CLASS(klass);
611
+
612
+ oc->mmio_ops = &npcm7xx_fuse_array_ops;
613
+}
614
+
615
+static const TypeInfo npcm7xx_otp_types[] = {
616
+ {
617
+ .name = TYPE_NPCM7XX_OTP,
618
+ .parent = TYPE_SYS_BUS_DEVICE,
619
+ .instance_size = sizeof(NPCM7xxOTPState),
620
+ .class_size = sizeof(NPCM7xxOTPClass),
621
+ .class_init = npcm7xx_otp_class_init,
622
+ .abstract = true,
623
+ },
624
+ {
625
+ .name = TYPE_NPCM7XX_KEY_STORAGE,
626
+ .parent = TYPE_NPCM7XX_OTP,
627
+ .class_init = npcm7xx_key_storage_class_init,
628
+ },
629
+ {
630
+ .name = TYPE_NPCM7XX_FUSE_ARRAY,
631
+ .parent = TYPE_NPCM7XX_OTP,
632
+ .class_init = npcm7xx_fuse_array_class_init,
633
+ },
634
+};
635
+DEFINE_TYPES(npcm7xx_otp_types);
636
diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build
637
index XXXXXXX..XXXXXXX 100644
638
--- a/hw/nvram/meson.build
639
+++ b/hw/nvram/meson.build
640
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_DS1225Y', if_true: files('ds1225y.c'))
641
softmmu_ss.add(when: 'CONFIG_NMC93XX_EEPROM', if_true: files('eeprom93xx.c'))
642
softmmu_ss.add(when: 'CONFIG_AT24C', if_true: files('eeprom_at24c.c'))
643
softmmu_ss.add(when: 'CONFIG_MAC_NVRAM', if_true: files('mac_nvram.c'))
644
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_otp.c'))
645
softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_nvm.c'))
646
647
specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_nvram.c'))
648
--
116
--
649
2.20.1
117
2.34.1
650
118
651
119
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
From: Jean-Christophe Dubois <jcd@tribudubois.net>
2
2
3
Enough functionality to boot the Linux kernel has been implemented. This
3
The SRC device is normally used to start the secondary CPU.
4
includes:
4
5
5
When running Linux directly, QEMU is emulating a PSCI interface that UBOOT
6
- Correct power-on reset values so the various clock rates can be
6
is installing at boot time and therefore the fact that the SRC device is
7
accurately calculated.
7
unimplemented is hidden as Qemu respond directly to PSCI requets without
8
- Clock enables stick around when written.
8
using the SRC device.
9
9
10
In addition, a best effort attempt to implement SECCNT and CNTR25M was
10
But if you try to run a more bare metal application (maybe uboot itself),
11
made even though I don't think the kernel needs them.
11
then it is not possible to start the secondary CPU as the SRC is an
12
12
unimplemented device.
13
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
13
14
Reviewed-by: Joel Stanley <joel@jms.id.au>
14
This patch adds the ability to start the secondary CPU through the SRC
15
Reviewed-by: Cédric Le Goater <clg@kaod.org>
15
device so that you can use this feature in bare metal applications.
16
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
17
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
18
Tested-by: Alexander Bulekov <alxndr@bu.edu>
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
19
Message-id: ce9a0162defd2acee5dc7f8a674743de0cded569.1692964892.git.jcd@tribudubois.net
20
Message-id: 20200911052101.2602693-3-hskinnemoen@google.com
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
21
---
23
include/hw/misc/npcm7xx_clk.h | 48 ++++++
22
include/hw/arm/fsl-imx7.h | 3 +-
24
hw/misc/npcm7xx_clk.c | 266 ++++++++++++++++++++++++++++++++++
23
include/hw/misc/imx7_src.h | 66 +++++++++
25
hw/misc/meson.build | 1 +
24
hw/arm/fsl-imx7.c | 8 +-
26
hw/misc/trace-events | 4 +
25
hw/misc/imx7_src.c | 276 +++++++++++++++++++++++++++++++++++++
27
4 files changed, 319 insertions(+)
26
hw/misc/meson.build | 1 +
28
create mode 100644 include/hw/misc/npcm7xx_clk.h
27
hw/misc/trace-events | 4 +
29
create mode 100644 hw/misc/npcm7xx_clk.c
28
6 files changed, 356 insertions(+), 2 deletions(-)
30
29
create mode 100644 include/hw/misc/imx7_src.h
31
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
30
create mode 100644 hw/misc/imx7_src.c
31
32
diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h
33
index XXXXXXX..XXXXXXX 100644
34
--- a/include/hw/arm/fsl-imx7.h
35
+++ b/include/hw/arm/fsl-imx7.h
36
@@ -XXX,XX +XXX,XX @@
37
#include "hw/misc/imx7_ccm.h"
38
#include "hw/misc/imx7_snvs.h"
39
#include "hw/misc/imx7_gpr.h"
40
+#include "hw/misc/imx7_src.h"
41
#include "hw/watchdog/wdt_imx2.h"
42
#include "hw/gpio/imx_gpio.h"
43
#include "hw/char/imx_serial.h"
44
@@ -XXX,XX +XXX,XX @@ struct FslIMX7State {
45
IMX7CCMState ccm;
46
IMX7AnalogState analog;
47
IMX7SNVSState snvs;
48
+ IMX7SRCState src;
49
IMXGPCv2State gpcv2;
50
IMXSPIState spi[FSL_IMX7_NUM_ECSPIS];
51
IMXI2CState i2c[FSL_IMX7_NUM_I2CS];
52
@@ -XXX,XX +XXX,XX @@ enum FslIMX7MemoryMap {
53
FSL_IMX7_GPC_ADDR = 0x303A0000,
54
55
FSL_IMX7_SRC_ADDR = 0x30390000,
56
- FSL_IMX7_SRC_SIZE = (4 * KiB),
57
58
FSL_IMX7_CCM_ADDR = 0x30380000,
59
60
diff --git a/include/hw/misc/imx7_src.h b/include/hw/misc/imx7_src.h
32
new file mode 100644
61
new file mode 100644
33
index XXXXXXX..XXXXXXX
62
index XXXXXXX..XXXXXXX
34
--- /dev/null
63
--- /dev/null
35
+++ b/include/hw/misc/npcm7xx_clk.h
64
+++ b/include/hw/misc/imx7_src.h
36
@@ -XXX,XX +XXX,XX @@
65
@@ -XXX,XX +XXX,XX @@
37
+/*
66
+/*
38
+ * Nuvoton NPCM7xx Clock Control Registers.
67
+ * IMX7 System Reset Controller
39
+ *
68
+ *
40
+ * Copyright 2020 Google LLC
69
+ * Copyright (C) 2023 Jean-Christophe Dubois <jcd@tribudubois.net>
41
+ *
70
+ *
42
+ * This program is free software; you can redistribute it and/or modify it
71
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
43
+ * under the terms of the GNU General Public License as published by the
72
+ * See the COPYING file in the top-level directory.
44
+ * Free Software Foundation; either version 2 of the License, or
45
+ * (at your option) any later version.
46
+ *
47
+ * This program is distributed in the hope that it will be useful, but WITHOUT
48
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
49
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
50
+ * for more details.
51
+ */
73
+ */
52
+#ifndef NPCM7XX_CLK_H
74
+
53
+#define NPCM7XX_CLK_H
75
+#ifndef IMX7_SRC_H
54
+
76
+#define IMX7_SRC_H
55
+#include "exec/memory.h"
77
+
56
+#include "hw/sysbus.h"
78
+#include "hw/sysbus.h"
57
+
79
+#include "qemu/bitops.h"
58
+/*
80
+#include "qom/object.h"
59
+ * The reference clock frequency for the timer modules, and the SECCNT and
81
+
60
+ * CNTR25M registers in this module, is always 25 MHz.
82
+#define SRC_SCR 0
61
+ */
83
+#define SRC_A7RCR0 1
62
+#define NPCM7XX_TIMER_REF_HZ (25000000)
84
+#define SRC_A7RCR1 2
63
+
85
+#define SRC_M4RCR 3
64
+/*
86
+#define SRC_ERCR 5
65
+ * Number of registers in our device state structure. Don't change this without
87
+#define SRC_HSICPHY_RCR 7
66
+ * incrementing the version_id in the vmstate.
88
+#define SRC_USBOPHY1_RCR 8
67
+ */
89
+#define SRC_USBOPHY2_RCR 9
68
+#define NPCM7XX_CLK_NR_REGS (0x70 / sizeof(uint32_t))
90
+#define SRC_MPIPHY_RCR 10
69
+
91
+#define SRC_PCIEPHY_RCR 11
70
+typedef struct NPCM7xxCLKState {
92
+#define SRC_SBMR1 22
71
+ SysBusDevice parent;
93
+#define SRC_SRSR 23
72
+
94
+#define SRC_SISR 26
95
+#define SRC_SIMR 27
96
+#define SRC_SBMR2 28
97
+#define SRC_GPR1 29
98
+#define SRC_GPR2 30
99
+#define SRC_GPR3 31
100
+#define SRC_GPR4 32
101
+#define SRC_GPR5 33
102
+#define SRC_GPR6 34
103
+#define SRC_GPR7 35
104
+#define SRC_GPR8 36
105
+#define SRC_GPR9 37
106
+#define SRC_GPR10 38
107
+#define SRC_MAX 39
108
+
109
+/* SRC_A7SCR1 */
110
+#define R_CORE1_ENABLE_SHIFT 1
111
+#define R_CORE1_ENABLE_LENGTH 1
112
+/* SRC_A7SCR0 */
113
+#define R_CORE1_RST_SHIFT 5
114
+#define R_CORE1_RST_LENGTH 1
115
+#define R_CORE0_RST_SHIFT 4
116
+#define R_CORE0_RST_LENGTH 1
117
+
118
+#define TYPE_IMX7_SRC "imx7.src"
119
+OBJECT_DECLARE_SIMPLE_TYPE(IMX7SRCState, IMX7_SRC)
120
+
121
+struct IMX7SRCState {
122
+ /* <private> */
123
+ SysBusDevice parent_obj;
124
+
125
+ /* <public> */
73
+ MemoryRegion iomem;
126
+ MemoryRegion iomem;
74
+
127
+
75
+ uint32_t regs[NPCM7XX_CLK_NR_REGS];
128
+ uint32_t regs[SRC_MAX];
76
+
129
+};
77
+ /* Time reference for SECCNT and CNTR25M, initialized by power on reset */
130
+
78
+ int64_t ref_ns;
131
+#endif /* IMX7_SRC_H */
79
+} NPCM7xxCLKState;
132
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
80
+
133
index XXXXXXX..XXXXXXX 100644
81
+#define TYPE_NPCM7XX_CLK "npcm7xx-clk"
134
--- a/hw/arm/fsl-imx7.c
82
+#define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), TYPE_NPCM7XX_CLK)
135
+++ b/hw/arm/fsl-imx7.c
83
+
136
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_init(Object *obj)
84
+#endif /* NPCM7XX_CLK_H */
137
*/
85
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
138
object_initialize_child(obj, "gpcv2", &s->gpcv2, TYPE_IMX_GPCV2);
139
140
+ /*
141
+ * SRC
142
+ */
143
+ object_initialize_child(obj, "src", &s->src, TYPE_IMX7_SRC);
144
+
145
/*
146
* ECSPIs
147
*/
148
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
149
/*
150
* SRC
151
*/
152
- create_unimplemented_device("src", FSL_IMX7_SRC_ADDR, FSL_IMX7_SRC_SIZE);
153
+ sysbus_realize(SYS_BUS_DEVICE(&s->src), &error_abort);
154
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->src), 0, FSL_IMX7_SRC_ADDR);
155
156
/*
157
* Watchdogs
158
diff --git a/hw/misc/imx7_src.c b/hw/misc/imx7_src.c
86
new file mode 100644
159
new file mode 100644
87
index XXXXXXX..XXXXXXX
160
index XXXXXXX..XXXXXXX
88
--- /dev/null
161
--- /dev/null
89
+++ b/hw/misc/npcm7xx_clk.c
162
+++ b/hw/misc/imx7_src.c
90
@@ -XXX,XX +XXX,XX @@
163
@@ -XXX,XX +XXX,XX @@
91
+/*
164
+/*
92
+ * Nuvoton NPCM7xx Clock Control Registers.
165
+ * IMX7 System Reset Controller
93
+ *
166
+ *
94
+ * Copyright 2020 Google LLC
167
+ * Copyright (c) 2023 Jean-Christophe Dubois <jcd@tribudubois.net>
95
+ *
168
+ *
96
+ * This program is free software; you can redistribute it and/or modify it
169
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
97
+ * under the terms of the GNU General Public License as published by the
170
+ * See the COPYING file in the top-level directory.
98
+ * Free Software Foundation; either version 2 of the License, or
99
+ * (at your option) any later version.
100
+ *
171
+ *
101
+ * This program is distributed in the hope that it will be useful, but WITHOUT
102
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
103
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
104
+ * for more details.
105
+ */
172
+ */
106
+
173
+
107
+#include "qemu/osdep.h"
174
+#include "qemu/osdep.h"
108
+
175
+#include "hw/misc/imx7_src.h"
109
+#include "hw/misc/npcm7xx_clk.h"
110
+#include "migration/vmstate.h"
176
+#include "migration/vmstate.h"
111
+#include "qemu/error-report.h"
177
+#include "qemu/bitops.h"
112
+#include "qemu/log.h"
178
+#include "qemu/log.h"
179
+#include "qemu/main-loop.h"
113
+#include "qemu/module.h"
180
+#include "qemu/module.h"
114
+#include "qemu/timer.h"
181
+#include "target/arm/arm-powerctl.h"
115
+#include "qemu/units.h"
182
+#include "hw/core/cpu.h"
183
+#include "hw/registerfields.h"
184
+
116
+#include "trace.h"
185
+#include "trace.h"
117
+
186
+
118
+#define PLLCON_LOKI BIT(31)
187
+static const char *imx7_src_reg_name(uint32_t reg)
119
+#define PLLCON_LOKS BIT(30)
188
+{
120
+#define PLLCON_PWDEN BIT(12)
189
+ static char unknown[20];
121
+
190
+
122
+enum NPCM7xxCLKRegisters {
191
+ switch (reg) {
123
+ NPCM7XX_CLK_CLKEN1,
192
+ case SRC_SCR:
124
+ NPCM7XX_CLK_CLKSEL,
193
+ return "SRC_SCR";
125
+ NPCM7XX_CLK_CLKDIV1,
194
+ case SRC_A7RCR0:
126
+ NPCM7XX_CLK_PLLCON0,
195
+ return "SRC_A7RCR0";
127
+ NPCM7XX_CLK_PLLCON1,
196
+ case SRC_A7RCR1:
128
+ NPCM7XX_CLK_SWRSTR,
197
+ return "SRC_A7RCR1";
129
+ NPCM7XX_CLK_IPSRST1 = 0x20 / sizeof(uint32_t),
198
+ case SRC_M4RCR:
130
+ NPCM7XX_CLK_IPSRST2,
199
+ return "SRC_M4RCR";
131
+ NPCM7XX_CLK_CLKEN2,
200
+ case SRC_ERCR:
132
+ NPCM7XX_CLK_CLKDIV2,
201
+ return "SRC_ERCR";
133
+ NPCM7XX_CLK_CLKEN3,
202
+ case SRC_HSICPHY_RCR:
134
+ NPCM7XX_CLK_IPSRST3,
203
+ return "SRC_HSICPHY_RCR";
135
+ NPCM7XX_CLK_WD0RCR,
204
+ case SRC_USBOPHY1_RCR:
136
+ NPCM7XX_CLK_WD1RCR,
205
+ return "SRC_USBOPHY1_RCR";
137
+ NPCM7XX_CLK_WD2RCR,
206
+ case SRC_USBOPHY2_RCR:
138
+ NPCM7XX_CLK_SWRSTC1,
207
+ return "SRC_USBOPHY2_RCR";
139
+ NPCM7XX_CLK_SWRSTC2,
208
+ case SRC_PCIEPHY_RCR:
140
+ NPCM7XX_CLK_SWRSTC3,
209
+ return "SRC_PCIEPHY_RCR";
141
+ NPCM7XX_CLK_SWRSTC4,
210
+ case SRC_SBMR1:
142
+ NPCM7XX_CLK_PLLCON2,
211
+ return "SRC_SBMR1";
143
+ NPCM7XX_CLK_CLKDIV3,
212
+ case SRC_SRSR:
144
+ NPCM7XX_CLK_CORSTC,
213
+ return "SRC_SRSR";
145
+ NPCM7XX_CLK_PLLCONG,
214
+ case SRC_SISR:
146
+ NPCM7XX_CLK_AHBCKFI,
215
+ return "SRC_SISR";
147
+ NPCM7XX_CLK_SECCNT,
216
+ case SRC_SIMR:
148
+ NPCM7XX_CLK_CNTR25M,
217
+ return "SRC_SIMR";
149
+ NPCM7XX_CLK_REGS_END,
218
+ case SRC_SBMR2:
219
+ return "SRC_SBMR2";
220
+ case SRC_GPR1:
221
+ return "SRC_GPR1";
222
+ case SRC_GPR2:
223
+ return "SRC_GPR2";
224
+ case SRC_GPR3:
225
+ return "SRC_GPR3";
226
+ case SRC_GPR4:
227
+ return "SRC_GPR4";
228
+ case SRC_GPR5:
229
+ return "SRC_GPR5";
230
+ case SRC_GPR6:
231
+ return "SRC_GPR6";
232
+ case SRC_GPR7:
233
+ return "SRC_GPR7";
234
+ case SRC_GPR8:
235
+ return "SRC_GPR8";
236
+ case SRC_GPR9:
237
+ return "SRC_GPR9";
238
+ case SRC_GPR10:
239
+ return "SRC_GPR10";
240
+ default:
241
+ sprintf(unknown, "%u ?", reg);
242
+ return unknown;
243
+ }
244
+}
245
+
246
+static const VMStateDescription vmstate_imx7_src = {
247
+ .name = TYPE_IMX7_SRC,
248
+ .version_id = 1,
249
+ .minimum_version_id = 1,
250
+ .fields = (VMStateField[]) {
251
+ VMSTATE_UINT32_ARRAY(regs, IMX7SRCState, SRC_MAX),
252
+ VMSTATE_END_OF_LIST()
253
+ },
150
+};
254
+};
151
+
255
+
256
+static void imx7_src_reset(DeviceState *dev)
257
+{
258
+ IMX7SRCState *s = IMX7_SRC(dev);
259
+
260
+ memset(s->regs, 0, sizeof(s->regs));
261
+
262
+ /* Set reset values */
263
+ s->regs[SRC_SCR] = 0xA0;
264
+ s->regs[SRC_SRSR] = 0x1;
265
+ s->regs[SRC_SIMR] = 0x1F;
266
+}
267
+
268
+static uint64_t imx7_src_read(void *opaque, hwaddr offset, unsigned size)
269
+{
270
+ uint32_t value = 0;
271
+ IMX7SRCState *s = (IMX7SRCState *)opaque;
272
+ uint32_t index = offset >> 2;
273
+
274
+ if (index < SRC_MAX) {
275
+ value = s->regs[index];
276
+ } else {
277
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
278
+ HWADDR_PRIx "\n", TYPE_IMX7_SRC, __func__, offset);
279
+ }
280
+
281
+ trace_imx7_src_read(imx7_src_reg_name(index), value);
282
+
283
+ return value;
284
+}
285
+
286
+
152
+/*
287
+/*
153
+ * These reset values were taken from version 0.91 of the NPCM750R data sheet.
288
+ * The reset is asynchronous so we need to defer clearing the reset
154
+ *
289
+ * bit until the work is completed.
155
+ * All are loaded on power-up reset. CLKENx and SWRSTR should also be loaded on
156
+ * core domain reset, but this reset type is not yet supported by QEMU.
157
+ */
290
+ */
158
+static const uint32_t cold_reset_values[NPCM7XX_CLK_NR_REGS] = {
291
+
159
+ [NPCM7XX_CLK_CLKEN1] = 0xffffffff,
292
+struct SRCSCRResetInfo {
160
+ [NPCM7XX_CLK_CLKSEL] = 0x004aaaaa,
293
+ IMX7SRCState *s;
161
+ [NPCM7XX_CLK_CLKDIV1] = 0x5413f855,
294
+ uint32_t reset_bit;
162
+ [NPCM7XX_CLK_PLLCON0] = 0x00222101 | PLLCON_LOKI,
163
+ [NPCM7XX_CLK_PLLCON1] = 0x00202101 | PLLCON_LOKI,
164
+ [NPCM7XX_CLK_IPSRST1] = 0x00001000,
165
+ [NPCM7XX_CLK_IPSRST2] = 0x80000000,
166
+ [NPCM7XX_CLK_CLKEN2] = 0xffffffff,
167
+ [NPCM7XX_CLK_CLKDIV2] = 0xaa4f8f9f,
168
+ [NPCM7XX_CLK_CLKEN3] = 0xffffffff,
169
+ [NPCM7XX_CLK_IPSRST3] = 0x03000000,
170
+ [NPCM7XX_CLK_WD0RCR] = 0xffffffff,
171
+ [NPCM7XX_CLK_WD1RCR] = 0xffffffff,
172
+ [NPCM7XX_CLK_WD2RCR] = 0xffffffff,
173
+ [NPCM7XX_CLK_SWRSTC1] = 0x00000003,
174
+ [NPCM7XX_CLK_PLLCON2] = 0x00c02105 | PLLCON_LOKI,
175
+ [NPCM7XX_CLK_CORSTC] = 0x04000003,
176
+ [NPCM7XX_CLK_PLLCONG] = 0x01228606 | PLLCON_LOKI,
177
+ [NPCM7XX_CLK_AHBCKFI] = 0x000000c8,
178
+};
295
+};
179
+
296
+
180
+static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size)
297
+static void imx7_clear_reset_bit(CPUState *cpu, run_on_cpu_data data)
181
+{
298
+{
182
+ uint32_t reg = offset / sizeof(uint32_t);
299
+ struct SRCSCRResetInfo *ri = data.host_ptr;
183
+ NPCM7xxCLKState *s = opaque;
300
+ IMX7SRCState *s = ri->s;
184
+ int64_t now_ns;
301
+
185
+ uint32_t value = 0;
302
+ assert(qemu_mutex_iothread_locked());
186
+
303
+
187
+ if (reg >= NPCM7XX_CLK_NR_REGS) {
304
+ s->regs[SRC_A7RCR0] = deposit32(s->regs[SRC_A7RCR0], ri->reset_bit, 1, 0);
188
+ qemu_log_mask(LOG_GUEST_ERROR,
305
+
189
+ "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
306
+ trace_imx7_src_write(imx7_src_reg_name(SRC_A7RCR0), s->regs[SRC_A7RCR0]);
190
+ __func__, offset);
307
+
191
+ return 0;
308
+ g_free(ri);
192
+ }
309
+}
193
+
310
+
194
+ switch (reg) {
311
+static void imx7_defer_clear_reset_bit(uint32_t cpuid,
195
+ case NPCM7XX_CLK_SWRSTR:
312
+ IMX7SRCState *s,
196
+ qemu_log_mask(LOG_GUEST_ERROR,
313
+ uint32_t reset_shift)
197
+ "%s: register @ 0x%04" HWADDR_PRIx " is write-only\n",
314
+{
198
+ __func__, offset);
315
+ struct SRCSCRResetInfo *ri;
199
+ break;
316
+ CPUState *cpu = arm_get_cpu_by_id(cpuid);
200
+
317
+
201
+ case NPCM7XX_CLK_SECCNT:
318
+ if (!cpu) {
202
+ now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
203
+ value = (now_ns - s->ref_ns) / NANOSECONDS_PER_SECOND;
204
+ break;
205
+
206
+ case NPCM7XX_CLK_CNTR25M:
207
+ now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
208
+ /*
209
+ * This register counts 25 MHz cycles, updating every 640 ns. It rolls
210
+ * over to zero every second.
211
+ *
212
+ * The 4 LSBs are always zero: (1e9 / 640) << 4 = 25000000.
213
+ */
214
+ value = (((now_ns - s->ref_ns) / 640) << 4) % NPCM7XX_TIMER_REF_HZ;
215
+ break;
216
+
217
+ default:
218
+ value = s->regs[reg];
219
+ break;
220
+ };
221
+
222
+ trace_npcm7xx_clk_read(offset, value);
223
+
224
+ return value;
225
+}
226
+
227
+static void npcm7xx_clk_write(void *opaque, hwaddr offset,
228
+ uint64_t v, unsigned size)
229
+{
230
+ uint32_t reg = offset / sizeof(uint32_t);
231
+ NPCM7xxCLKState *s = opaque;
232
+ uint32_t value = v;
233
+
234
+ trace_npcm7xx_clk_write(offset, value);
235
+
236
+ if (reg >= NPCM7XX_CLK_NR_REGS) {
237
+ qemu_log_mask(LOG_GUEST_ERROR,
238
+ "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
239
+ __func__, offset);
240
+ return;
319
+ return;
241
+ }
320
+ }
242
+
321
+
243
+ switch (reg) {
322
+ ri = g_new(struct SRCSCRResetInfo, 1);
244
+ case NPCM7XX_CLK_SWRSTR:
323
+ ri->s = s;
245
+ qemu_log_mask(LOG_UNIMP, "%s: SW reset not implemented: 0x%02x\n",
324
+ ri->reset_bit = reset_shift;
246
+ __func__, value);
325
+
247
+ value = 0;
326
+ async_run_on_cpu(cpu, imx7_clear_reset_bit, RUN_ON_CPU_HOST_PTR(ri));
248
+ break;
327
+}
249
+
328
+
250
+ case NPCM7XX_CLK_PLLCON0:
329
+
251
+ case NPCM7XX_CLK_PLLCON1:
330
+static void imx7_src_write(void *opaque, hwaddr offset, uint64_t value,
252
+ case NPCM7XX_CLK_PLLCON2:
331
+ unsigned size)
253
+ case NPCM7XX_CLK_PLLCONG:
332
+{
254
+ if (value & PLLCON_PWDEN) {
333
+ IMX7SRCState *s = (IMX7SRCState *)opaque;
255
+ /* Power down -- clear lock and indicate loss of lock */
334
+ uint32_t index = offset >> 2;
256
+ value &= ~PLLCON_LOKI;
335
+ long unsigned int change_mask;
257
+ value |= PLLCON_LOKS;
336
+ uint32_t current_value = value;
258
+ } else {
337
+
259
+ /* Normal mode -- assume always locked */
338
+ if (index >= SRC_MAX) {
260
+ value |= PLLCON_LOKI;
339
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
261
+ /* Keep LOKS unchanged unless cleared by writing 1 */
340
+ HWADDR_PRIx "\n", TYPE_IMX7_SRC, __func__, offset);
262
+ if (value & PLLCON_LOKS) {
263
+ value &= ~PLLCON_LOKS;
264
+ } else {
265
+ value |= (value & PLLCON_LOKS);
266
+ }
267
+ }
268
+ break;
269
+
270
+ case NPCM7XX_CLK_CNTR25M:
271
+ qemu_log_mask(LOG_GUEST_ERROR,
272
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
273
+ __func__, offset);
274
+ return;
341
+ return;
275
+ }
342
+ }
276
+
343
+
277
+ s->regs[reg] = value;
344
+ trace_imx7_src_write(imx7_src_reg_name(SRC_A7RCR0), s->regs[SRC_A7RCR0]);
278
+}
345
+
279
+
346
+ change_mask = s->regs[index] ^ (uint32_t)current_value;
280
+static const struct MemoryRegionOps npcm7xx_clk_ops = {
347
+
281
+ .read = npcm7xx_clk_read,
348
+ switch (index) {
282
+ .write = npcm7xx_clk_write,
349
+ case SRC_A7RCR0:
283
+ .endianness = DEVICE_LITTLE_ENDIAN,
350
+ if (FIELD_EX32(change_mask, CORE0, RST)) {
284
+ .valid = {
351
+ arm_reset_cpu(0);
285
+ .min_access_size = 4,
352
+ imx7_defer_clear_reset_bit(0, s, R_CORE0_RST_SHIFT);
286
+ .max_access_size = 4,
353
+ }
287
+ .unaligned = false,
354
+ if (FIELD_EX32(change_mask, CORE1, RST)) {
355
+ arm_reset_cpu(1);
356
+ imx7_defer_clear_reset_bit(1, s, R_CORE1_RST_SHIFT);
357
+ }
358
+ s->regs[index] = current_value;
359
+ break;
360
+ case SRC_A7RCR1:
361
+ /*
362
+ * On real hardware when the system reset controller starts a
363
+ * secondary CPU it runs through some boot ROM code which reads
364
+ * the SRC_GPRX registers controlling the start address and branches
365
+ * to it.
366
+ * Here we are taking a short cut and branching directly to the
367
+ * requested address (we don't want to run the boot ROM code inside
368
+ * QEMU)
369
+ */
370
+ if (FIELD_EX32(change_mask, CORE1, ENABLE)) {
371
+ if (FIELD_EX32(current_value, CORE1, ENABLE)) {
372
+ /* CORE 1 is brought up */
373
+ arm_set_cpu_on(1, s->regs[SRC_GPR3], s->regs[SRC_GPR4],
374
+ 3, false);
375
+ } else {
376
+ /* CORE 1 is shut down */
377
+ arm_set_cpu_off(1);
378
+ }
379
+ /* We clear the reset bits as the processor changed state */
380
+ imx7_defer_clear_reset_bit(1, s, R_CORE1_RST_SHIFT);
381
+ clear_bit(R_CORE1_RST_SHIFT, &change_mask);
382
+ }
383
+ s->regs[index] = current_value;
384
+ break;
385
+ default:
386
+ s->regs[index] = current_value;
387
+ break;
388
+ }
389
+}
390
+
391
+static const struct MemoryRegionOps imx7_src_ops = {
392
+ .read = imx7_src_read,
393
+ .write = imx7_src_write,
394
+ .endianness = DEVICE_NATIVE_ENDIAN,
395
+ .valid = {
396
+ /*
397
+ * Our device would not work correctly if the guest was doing
398
+ * unaligned access. This might not be a limitation on the real
399
+ * device but in practice there is no reason for a guest to access
400
+ * this device unaligned.
401
+ */
402
+ .min_access_size = 4,
403
+ .max_access_size = 4,
404
+ .unaligned = false,
288
+ },
405
+ },
289
+};
406
+};
290
+
407
+
291
+static void npcm7xx_clk_enter_reset(Object *obj, ResetType type)
408
+static void imx7_src_realize(DeviceState *dev, Error **errp)
292
+{
409
+{
293
+ NPCM7xxCLKState *s = NPCM7XX_CLK(obj);
410
+ IMX7SRCState *s = IMX7_SRC(dev);
294
+
411
+
295
+ QEMU_BUILD_BUG_ON(sizeof(s->regs) != sizeof(cold_reset_values));
412
+ memory_region_init_io(&s->iomem, OBJECT(dev), &imx7_src_ops, s,
296
+
413
+ TYPE_IMX7_SRC, 0x1000);
297
+ switch (type) {
414
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
298
+ case RESET_TYPE_COLD:
415
+}
299
+ memcpy(s->regs, cold_reset_values, sizeof(cold_reset_values));
416
+
300
+ s->ref_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
417
+static void imx7_src_class_init(ObjectClass *klass, void *data)
301
+ return;
418
+{
302
+ }
419
+ DeviceClass *dc = DEVICE_CLASS(klass);
303
+
420
+
304
+ /*
421
+ dc->realize = imx7_src_realize;
305
+ * A small number of registers need to be reset on a core domain reset,
422
+ dc->reset = imx7_src_reset;
306
+ * but no such reset type exists yet.
423
+ dc->vmsd = &vmstate_imx7_src;
307
+ */
424
+ dc->desc = "i.MX6 System Reset Controller";
308
+ qemu_log_mask(LOG_UNIMP, "%s: reset type %d not implemented.",
425
+}
309
+ __func__, type);
426
+
310
+}
427
+static const TypeInfo imx7_src_info = {
311
+
428
+ .name = TYPE_IMX7_SRC,
312
+static void npcm7xx_clk_init(Object *obj)
429
+ .parent = TYPE_SYS_BUS_DEVICE,
313
+{
430
+ .instance_size = sizeof(IMX7SRCState),
314
+ NPCM7xxCLKState *s = NPCM7XX_CLK(obj);
431
+ .class_init = imx7_src_class_init,
315
+
316
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s,
317
+ TYPE_NPCM7XX_CLK, 4 * KiB);
318
+ sysbus_init_mmio(&s->parent, &s->iomem);
319
+}
320
+
321
+static const VMStateDescription vmstate_npcm7xx_clk = {
322
+ .name = "npcm7xx-clk",
323
+ .version_id = 0,
324
+ .minimum_version_id = 0,
325
+ .fields = (VMStateField[]) {
326
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxCLKState, NPCM7XX_CLK_NR_REGS),
327
+ VMSTATE_INT64(ref_ns, NPCM7xxCLKState),
328
+ VMSTATE_END_OF_LIST(),
329
+ },
330
+};
432
+};
331
+
433
+
332
+static void npcm7xx_clk_class_init(ObjectClass *klass, void *data)
434
+static void imx7_src_register_types(void)
333
+{
435
+{
334
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
436
+ type_register_static(&imx7_src_info);
335
+ DeviceClass *dc = DEVICE_CLASS(klass);
437
+}
336
+
438
+
337
+ QEMU_BUILD_BUG_ON(NPCM7XX_CLK_REGS_END > NPCM7XX_CLK_NR_REGS);
439
+type_init(imx7_src_register_types)
338
+
339
+ dc->desc = "NPCM7xx Clock Control Registers";
340
+ dc->vmsd = &vmstate_npcm7xx_clk;
341
+ rc->phases.enter = npcm7xx_clk_enter_reset;
342
+}
343
+
344
+static const TypeInfo npcm7xx_clk_info = {
345
+ .name = TYPE_NPCM7XX_CLK,
346
+ .parent = TYPE_SYS_BUS_DEVICE,
347
+ .instance_size = sizeof(NPCM7xxCLKState),
348
+ .instance_init = npcm7xx_clk_init,
349
+ .class_init = npcm7xx_clk_class_init,
350
+};
351
+
352
+static void npcm7xx_clk_register_type(void)
353
+{
354
+ type_register_static(&npcm7xx_clk_info);
355
+}
356
+type_init(npcm7xx_clk_register_type);
357
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
440
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
358
index XXXXXXX..XXXXXXX 100644
441
index XXXXXXX..XXXXXXX 100644
359
--- a/hw/misc/meson.build
442
--- a/hw/misc/meson.build
360
+++ b/hw/misc/meson.build
443
+++ b/hw/misc/meson.build
361
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_IMX', if_true: files(
444
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_IMX', if_true: files(
362
softmmu_ss.add(when: 'CONFIG_MILKYMIST', if_true: files('milkymist-hpdmc.c', 'milkymist-pfpu.c'))
445
'imx6_src.c',
363
softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c'))
446
'imx6ul_ccm.c',
364
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
447
'imx7_ccm.c',
365
+ 'npcm7xx_clk.c',
448
+ 'imx7_src.c',
366
'npcm7xx_gcr.c',
449
'imx7_gpr.c',
367
))
450
'imx7_snvs.c',
368
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files(
451
'imx_ccm.c',
369
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
452
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
370
index XXXXXXX..XXXXXXX 100644
453
index XXXXXXX..XXXXXXX 100644
371
--- a/hw/misc/trace-events
454
--- a/hw/misc/trace-events
372
+++ b/hw/misc/trace-events
455
+++ b/hw/misc/trace-events
373
@@ -XXX,XX +XXX,XX @@ mos6522_set_sr_int(void) "set sr_int"
456
@@ -XXX,XX +XXX,XX @@ ccm_clock_freq(uint32_t clock, uint32_t freq) "(Clock = %d) = %d"
374
mos6522_write(uint64_t addr, uint64_t val) "reg=0x%"PRIx64 " val=0x%"PRIx64
457
ccm_read_reg(const char *reg_name, uint32_t value) "reg[%s] <= 0x%" PRIx32
375
mos6522_read(uint64_t addr, unsigned val) "reg=0x%"PRIx64 " val=0x%x"
458
ccm_write_reg(const char *reg_name, uint32_t value) "reg[%s] => 0x%" PRIx32
376
459
377
+# npcm7xx_clk.c
460
+# imx7_src.c
378
+npcm7xx_clk_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
461
+imx7_src_read(const char *reg_name, uint32_t value) "reg[%s] => 0x%" PRIx32
379
+npcm7xx_clk_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
462
+imx7_src_write(const char *reg_name, uint32_t value) "reg[%s] <= 0x%" PRIx32
380
+
463
+
381
# npcm7xx_gcr.c
464
# iotkit-sysinfo.c
382
npcm7xx_gcr_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
465
iotkit_sysinfo_read(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysInfo read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
383
npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
466
iotkit_sysinfo_write(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysInfo write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
384
--
467
--
385
2.20.1
468
2.34.1
386
387
diff view generated by jsdifflib
1
Convert the insns using the 2reg_vcvt and 2reg_vcvt_f16 formats
1
The architecture requires (R_TYTWB) that an attempt to return from EL3
2
to pass the size through to the trans function as a MO_* value
2
when SCR_EL3.{NSE,NS} are {1,0} is an illegal exception return. (This
3
rather than the '0==f32, 1==f16' used in the fp 3-same encodings.
3
enforces that the CPU can't ever be executing below EL3 with the
4
NSE,NS bits indicating an invalid security state.)
5
6
We were missing this check; add it.
4
7
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200903133209.5141-3-peter.maydell@linaro.org
10
Message-id: 20230807150618.101357-1-peter.maydell@linaro.org
8
---
11
---
9
target/arm/neon-dp.decode | 3 +--
12
target/arm/tcg/helper-a64.c | 9 +++++++++
10
target/arm/translate-neon.c.inc | 4 ++--
13
1 file changed, 9 insertions(+)
11
2 files changed, 3 insertions(+), 4 deletions(-)
12
14
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
15
diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
17
--- a/target/arm/tcg/helper-a64.c
16
+++ b/target/arm/neon-dp.decode
18
+++ b/target/arm/tcg/helper-a64.c
17
@@ -XXX,XX +XXX,XX @@ VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
19
@@ -XXX,XX +XXX,XX @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
18
@2reg_shll_b .... ... . . . 001 shift:3 .... .... 0 . . . .... \
20
spsr &= ~PSTATE_SS;
19
&2reg_shift vm=%vm_dp vd=%vd_dp size=0 q=0
20
21
-# We use size=0 for fp32 and size=1 for fp16 to match the 3-same encodings.
22
@2reg_vcvt .... ... . . . 1 ..... .... .... . q:1 . . .... \
23
- &2reg_shift vm=%vm_dp vd=%vd_dp size=0 shift=%neon_rshift_i5
24
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=2 shift=%neon_rshift_i5
25
@2reg_vcvt_f16 .... ... . . . 11 .... .... .... . q:1 . . .... \
26
&2reg_shift vm=%vm_dp vd=%vd_dp size=1 shift=%neon_rshift_i4
27
28
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/translate-neon.c.inc
31
+++ b/target/arm/translate-neon.c.inc
32
@@ -XXX,XX +XXX,XX @@ static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a,
33
return false;
34
}
21
}
35
22
36
- if (a->size != 0) {
23
+ /*
37
+ if (a->size == MO_16) {
24
+ * FEAT_RME forbids return from EL3 with an invalid security state.
38
if (!dc_isar_feature(aa32_fp16_arith, s)) {
25
+ * We don't need an explicit check for FEAT_RME here because we enforce
39
return false;
26
+ * in scr_write() that you can't set the NSE bit without it.
40
}
27
+ */
41
@@ -XXX,XX +XXX,XX @@ static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a,
28
+ if (cur_el == 3 && (env->cp15.scr_el3 & (SCR_NS | SCR_NSE)) == SCR_NSE) {
42
return true;
29
+ goto illegal_return;
43
}
30
+ }
44
31
+
45
- fpst = fpstatus_ptr(a->size ? FPST_STD_F16 : FPST_STD);
32
new_el = el_from_spsr(spsr);
46
+ fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
33
if (new_el == -1) {
47
tcg_gen_gvec_2_ptr(rd_ofs, rm_ofs, fpst, vec_size, vec_size, a->shift, fn);
34
goto illegal_return;
48
tcg_temp_free_ptr(fpst);
49
return true;
50
--
35
--
51
2.20.1
36
2.34.1
52
53
diff view generated by jsdifflib
Deleted patch
1
The VCMLA and VCADD insns have a size field which is 0 for fp16
2
and 1 for fp32 (note that this is the reverse of the Neon 3-same
3
encoding!). Convert it to MO_* values in decode for consistency.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200903133209.5141-4-peter.maydell@linaro.org
8
---
9
target/arm/neon-shared.decode | 18 ++++++++++++------
10
target/arm/translate-neon.c.inc | 22 ++++++++++++----------
11
2 files changed, 24 insertions(+), 16 deletions(-)
12
13
diff --git a/target/arm/neon-shared.decode b/target/arm/neon-shared.decode
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-shared.decode
16
+++ b/target/arm/neon-shared.decode
17
@@ -XXX,XX +XXX,XX @@
18
%vd_dp 22:1 12:4
19
%vd_sp 12:4 22:1
20
21
-VCMLA 1111 110 rot:2 . 1 size:1 .... .... 1000 . q:1 . 0 .... \
22
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
23
+# For VCMLA/VCADD insns, convert the single-bit size field
24
+# which is 0 for fp16 and 1 for fp32 into a MO_* constant.
25
+# (Note that this is the reverse of the sense of the 1-bit size
26
+# field in the 3same_fp Neon insns.)
27
+%vcadd_size 20:1 !function=plus1
28
29
-VCADD 1111 110 rot:1 1 . 0 size:1 .... .... 1000 . q:1 . 0 .... \
30
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
31
+VCMLA 1111 110 rot:2 . 1 . .... .... 1000 . q:1 . 0 .... \
32
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp size=%vcadd_size
33
+
34
+VCADD 1111 110 rot:1 1 . 0 . .... .... 1000 . q:1 . 0 .... \
35
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp size=%vcadd_size
36
37
# VUDOT and VSDOT
38
VDOT 1111 110 00 . 10 .... .... 1101 . q:1 . u:1 .... \
39
@@ -XXX,XX +XXX,XX @@ VFML 1111 110 0 s:1 . 10 .... .... 1000 . 1 . 1 .... \
40
vm=%vm_dp vn=%vn_dp vd=%vd_dp q=1
41
42
VCMLA_scalar 1111 1110 0 . rot:2 .... .... 1000 . q:1 index:1 0 vm:4 \
43
- vn=%vn_dp vd=%vd_dp size=0
44
+ vn=%vn_dp vd=%vd_dp size=1
45
VCMLA_scalar 1111 1110 1 . rot:2 .... .... 1000 . q:1 . 0 .... \
46
- vm=%vm_dp vn=%vn_dp vd=%vd_dp size=1 index=0
47
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp size=2 index=0
48
49
VDOT_scalar 1111 1110 0 . 10 .... .... 1101 . q:1 index:1 u:1 rm:4 \
50
vm=%vm_dp vn=%vn_dp vd=%vd_dp
51
diff --git a/target/arm/translate-neon.c.inc b/target/arm/translate-neon.c.inc
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/translate-neon.c.inc
54
+++ b/target/arm/translate-neon.c.inc
55
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA(DisasContext *s, arg_VCMLA *a)
56
gen_helper_gvec_3_ptr *fn_gvec_ptr;
57
58
if (!dc_isar_feature(aa32_vcma, s)
59
- || (!a->size && !dc_isar_feature(aa32_fp16_arith, s))) {
60
+ || (a->size == MO_16 && !dc_isar_feature(aa32_fp16_arith, s))) {
61
return false;
62
}
63
64
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA(DisasContext *s, arg_VCMLA *a)
65
}
66
67
opr_sz = (1 + a->q) * 8;
68
- fpst = fpstatus_ptr(a->size == 0 ? FPST_STD_F16 : FPST_STD);
69
- fn_gvec_ptr = a->size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
70
+ fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
71
+ fn_gvec_ptr = (a->size == MO_16) ?
72
+ gen_helper_gvec_fcmlah : gen_helper_gvec_fcmlas;
73
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
74
vfp_reg_offset(1, a->vn),
75
vfp_reg_offset(1, a->vm),
76
@@ -XXX,XX +XXX,XX @@ static bool trans_VCADD(DisasContext *s, arg_VCADD *a)
77
gen_helper_gvec_3_ptr *fn_gvec_ptr;
78
79
if (!dc_isar_feature(aa32_vcma, s)
80
- || (!a->size && !dc_isar_feature(aa32_fp16_arith, s))) {
81
+ || (a->size == MO_16 && !dc_isar_feature(aa32_fp16_arith, s))) {
82
return false;
83
}
84
85
@@ -XXX,XX +XXX,XX @@ static bool trans_VCADD(DisasContext *s, arg_VCADD *a)
86
}
87
88
opr_sz = (1 + a->q) * 8;
89
- fpst = fpstatus_ptr(a->size == 0 ? FPST_STD_F16 : FPST_STD);
90
- fn_gvec_ptr = a->size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
91
+ fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
92
+ fn_gvec_ptr = (a->size == MO_16) ?
93
+ gen_helper_gvec_fcaddh : gen_helper_gvec_fcadds;
94
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
95
vfp_reg_offset(1, a->vn),
96
vfp_reg_offset(1, a->vm),
97
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA_scalar(DisasContext *s, arg_VCMLA_scalar *a)
98
if (!dc_isar_feature(aa32_vcma, s)) {
99
return false;
100
}
101
- if (a->size == 0 && !dc_isar_feature(aa32_fp16_arith, s)) {
102
+ if (a->size == MO_16 && !dc_isar_feature(aa32_fp16_arith, s)) {
103
return false;
104
}
105
106
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMLA_scalar(DisasContext *s, arg_VCMLA_scalar *a)
107
return true;
108
}
109
110
- fn_gvec_ptr = (a->size ? gen_helper_gvec_fcmlas_idx
111
- : gen_helper_gvec_fcmlah_idx);
112
+ fn_gvec_ptr = (a->size == MO_16) ?
113
+ gen_helper_gvec_fcmlah_idx : gen_helper_gvec_fcmlas_idx;
114
opr_sz = (1 + a->q) * 8;
115
- fpst = fpstatus_ptr(a->size == 0 ? FPST_STD_F16 : FPST_STD);
116
+ fpst = fpstatus_ptr(a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
117
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, a->vd),
118
vfp_reg_offset(1, a->vn),
119
vfp_reg_offset(1, a->vm),
120
--
121
2.20.1
122
123
diff view generated by jsdifflib
Deleted patch
1
We deprecated the support for KVM on 32-bit Arm hosts in time
2
for release 5.0, which means that our deprecation policy allows
3
us to drop it in release 5.2. Remove the code.
4
1
5
To repeat the rationale from the deprecation note: the Linux
6
kernel dropped support for 32-bit Arm KVM hosts in 5.7.
7
8
Running 32-bit guests on a 64-bit Arm host remains supported.
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
13
Message-id: 20200904154156.31943-2-peter.maydell@linaro.org
14
---
15
docs/system/deprecated.rst | 16 +-
16
configure | 2 +-
17
target/arm/kvm32.c | 595 -------------------------------------
18
target/arm/meson.build | 5 +-
19
4 files changed, 10 insertions(+), 608 deletions(-)
20
delete mode 100644 target/arm/kvm32.c
21
22
diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
23
index XXXXXXX..XXXXXXX 100644
24
--- a/docs/system/deprecated.rst
25
+++ b/docs/system/deprecated.rst
26
@@ -XXX,XX +XXX,XX @@ The ``compat`` property used to set backwards compatibility modes for
27
the processor has been deprecated. The ``max-cpu-compat`` property of
28
the ``pseries`` machine type should be used instead.
29
30
-KVM guest support on 32-bit Arm hosts (since 5.0)
31
-'''''''''''''''''''''''''''''''''''''''''''''''''
32
-
33
-The Linux kernel has dropped support for allowing 32-bit Arm systems
34
-to host KVM guests as of the 5.7 kernel. Accordingly, QEMU is deprecating
35
-its support for this configuration and will remove it in a future version.
36
-Running 32-bit guests on a 64-bit Arm host remains supported.
37
-
38
System emulator devices
39
-----------------------
40
41
@@ -XXX,XX +XXX,XX @@ should be used instead of the 1.09.1 version.
42
System emulator CPUS
43
--------------------
44
45
+KVM guest support on 32-bit Arm hosts (removed in 5.2)
46
+''''''''''''''''''''''''''''''''''''''''''''''''''''''
47
+
48
+The Linux kernel has dropped support for allowing 32-bit Arm systems
49
+to host KVM guests as of the 5.7 kernel. Accordingly, QEMU is deprecating
50
+its support for this configuration and will remove it in a future version.
51
+Running 32-bit guests on a 64-bit Arm host remains supported.
52
+
53
RISC-V ISA Specific CPUs (removed in 5.1)
54
'''''''''''''''''''''''''''''''''''''''''
55
56
diff --git a/configure b/configure
57
index XXXXXXX..XXXXXXX 100755
58
--- a/configure
59
+++ b/configure
60
@@ -XXX,XX +XXX,XX @@ supported_kvm_target() {
61
test "$kvm" = "yes" || return 1
62
glob "$1" "*-softmmu" || return 1
63
case "${1%-softmmu}:$cpu" in
64
- arm:arm | aarch64:aarch64 | \
65
+ aarch64:aarch64 | \
66
i386:i386 | i386:x86_64 | i386:x32 | \
67
x86_64:i386 | x86_64:x86_64 | x86_64:x32 | \
68
mips:mips | mipsel:mips | mips64:mips | mips64el:mips | \
69
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
70
deleted file mode 100644
71
index XXXXXXX..XXXXXXX
72
--- a/target/arm/kvm32.c
73
+++ /dev/null
74
@@ -XXX,XX +XXX,XX @@
75
-/*
76
- * ARM implementation of KVM hooks, 32 bit specific code.
77
- *
78
- * Copyright Christoffer Dall 2009-2010
79
- *
80
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
81
- * See the COPYING file in the top-level directory.
82
- *
83
- */
84
-
85
-#include "qemu/osdep.h"
86
-#include <sys/ioctl.h>
87
-
88
-#include <linux/kvm.h>
89
-
90
-#include "qemu-common.h"
91
-#include "cpu.h"
92
-#include "qemu/timer.h"
93
-#include "sysemu/runstate.h"
94
-#include "sysemu/kvm.h"
95
-#include "kvm_arm.h"
96
-#include "internals.h"
97
-#include "qemu/log.h"
98
-
99
-static int read_sys_reg32(int fd, uint32_t *pret, uint64_t id)
100
-{
101
- struct kvm_one_reg idreg = { .id = id, .addr = (uintptr_t)pret };
102
-
103
- assert((id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U32);
104
- return ioctl(fd, KVM_GET_ONE_REG, &idreg);
105
-}
106
-
107
-bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
108
-{
109
- /* Identify the feature bits corresponding to the host CPU, and
110
- * fill out the ARMHostCPUClass fields accordingly. To do this
111
- * we have to create a scratch VM, create a single CPU inside it,
112
- * and then query that CPU for the relevant ID registers.
113
- */
114
- int err = 0, fdarray[3];
115
- uint32_t midr, id_pfr0;
116
- uint64_t features = 0;
117
-
118
- /* Old kernels may not know about the PREFERRED_TARGET ioctl: however
119
- * we know these will only support creating one kind of guest CPU,
120
- * which is its preferred CPU type.
121
- */
122
- static const uint32_t cpus_to_try[] = {
123
- QEMU_KVM_ARM_TARGET_CORTEX_A15,
124
- QEMU_KVM_ARM_TARGET_NONE
125
- };
126
- /*
127
- * target = -1 informs kvm_arm_create_scratch_host_vcpu()
128
- * to use the preferred target
129
- */
130
- struct kvm_vcpu_init init = { .target = -1, };
131
-
132
- if (!kvm_arm_create_scratch_host_vcpu(cpus_to_try, fdarray, &init)) {
133
- return false;
134
- }
135
-
136
- ahcf->target = init.target;
137
-
138
- /* This is not strictly blessed by the device tree binding docs yet,
139
- * but in practice the kernel does not care about this string so
140
- * there is no point maintaining an KVM_ARM_TARGET_* -> string table.
141
- */
142
- ahcf->dtb_compatible = "arm,arm-v7";
143
-
144
- err |= read_sys_reg32(fdarray[2], &midr, ARM_CP15_REG32(0, 0, 0, 0));
145
- err |= read_sys_reg32(fdarray[2], &id_pfr0, ARM_CP15_REG32(0, 0, 1, 0));
146
-
147
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar0,
148
- ARM_CP15_REG32(0, 0, 2, 0));
149
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar1,
150
- ARM_CP15_REG32(0, 0, 2, 1));
151
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar2,
152
- ARM_CP15_REG32(0, 0, 2, 2));
153
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar3,
154
- ARM_CP15_REG32(0, 0, 2, 3));
155
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar4,
156
- ARM_CP15_REG32(0, 0, 2, 4));
157
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar5,
158
- ARM_CP15_REG32(0, 0, 2, 5));
159
- if (read_sys_reg32(fdarray[2], &ahcf->isar.id_isar6,
160
- ARM_CP15_REG32(0, 0, 2, 7))) {
161
- /*
162
- * Older kernels don't support reading ID_ISAR6. This register was
163
- * only introduced in ARMv8, so we can assume that it is zero on a
164
- * CPU that a kernel this old is running on.
165
- */
166
- ahcf->isar.id_isar6 = 0;
167
- }
168
-
169
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0,
170
- ARM_CP15_REG32(0, 0, 1, 2));
171
-
172
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr0,
173
- KVM_REG_ARM | KVM_REG_SIZE_U32 |
174
- KVM_REG_ARM_VFP | KVM_REG_ARM_VFP_MVFR0);
175
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr1,
176
- KVM_REG_ARM | KVM_REG_SIZE_U32 |
177
- KVM_REG_ARM_VFP | KVM_REG_ARM_VFP_MVFR1);
178
- /*
179
- * FIXME: There is not yet a way to read MVFR2.
180
- * Fortunately there is not yet anything in there that affects migration.
181
- */
182
-
183
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0,
184
- ARM_CP15_REG32(0, 0, 1, 4));
185
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr1,
186
- ARM_CP15_REG32(0, 0, 1, 5));
187
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr2,
188
- ARM_CP15_REG32(0, 0, 1, 6));
189
- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr3,
190
- ARM_CP15_REG32(0, 0, 1, 7));
191
- if (read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr4,
192
- ARM_CP15_REG32(0, 0, 2, 6))) {
193
- /*
194
- * Older kernels don't support reading ID_MMFR4 (a new in v8
195
- * register); assume it's zero.
196
- */
197
- ahcf->isar.id_mmfr4 = 0;
198
- }
199
-
200
- /*
201
- * There is no way to read DBGDIDR, because currently 32-bit KVM
202
- * doesn't implement debug at all. Leave it at zero.
203
- */
204
-
205
- kvm_arm_destroy_scratch_host_vcpu(fdarray);
206
-
207
- if (err < 0) {
208
- return false;
209
- }
210
-
211
- /* Now we've retrieved all the register information we can
212
- * set the feature bits based on the ID register fields.
213
- * We can assume any KVM supporting CPU is at least a v7
214
- * with VFPv3, virtualization extensions, and the generic
215
- * timers; this in turn implies most of the other feature
216
- * bits, but a few must be tested.
217
- */
218
- features |= 1ULL << ARM_FEATURE_V7VE;
219
- features |= 1ULL << ARM_FEATURE_GENERIC_TIMER;
220
-
221
- if (extract32(id_pfr0, 12, 4) == 1) {
222
- features |= 1ULL << ARM_FEATURE_THUMB2EE;
223
- }
224
- if (extract32(ahcf->isar.mvfr1, 12, 4) == 1) {
225
- features |= 1ULL << ARM_FEATURE_NEON;
226
- }
227
-
228
- ahcf->features = features;
229
-
230
- return true;
231
-}
232
-
233
-bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx)
234
-{
235
- /* Return true if the regidx is a register we should synchronize
236
- * via the cpreg_tuples array (ie is not a core reg we sync by
237
- * hand in kvm_arch_get/put_registers())
238
- */
239
- switch (regidx & KVM_REG_ARM_COPROC_MASK) {
240
- case KVM_REG_ARM_CORE:
241
- case KVM_REG_ARM_VFP:
242
- return false;
243
- default:
244
- return true;
245
- }
246
-}
247
-
248
-typedef struct CPRegStateLevel {
249
- uint64_t regidx;
250
- int level;
251
-} CPRegStateLevel;
252
-
253
-/* All coprocessor registers not listed in the following table are assumed to
254
- * be of the level KVM_PUT_RUNTIME_STATE. If a register should be written less
255
- * often, you must add it to this table with a state of either
256
- * KVM_PUT_RESET_STATE or KVM_PUT_FULL_STATE.
257
- */
258
-static const CPRegStateLevel non_runtime_cpregs[] = {
259
- { KVM_REG_ARM_TIMER_CNT, KVM_PUT_FULL_STATE },
260
-};
261
-
262
-int kvm_arm_cpreg_level(uint64_t regidx)
263
-{
264
- int i;
265
-
266
- for (i = 0; i < ARRAY_SIZE(non_runtime_cpregs); i++) {
267
- const CPRegStateLevel *l = &non_runtime_cpregs[i];
268
- if (l->regidx == regidx) {
269
- return l->level;
270
- }
271
- }
272
-
273
- return KVM_PUT_RUNTIME_STATE;
274
-}
275
-
276
-#define ARM_CPU_ID_MPIDR 0, 0, 0, 5
277
-
278
-int kvm_arch_init_vcpu(CPUState *cs)
279
-{
280
- int ret;
281
- uint64_t v;
282
- uint32_t mpidr;
283
- struct kvm_one_reg r;
284
- ARMCPU *cpu = ARM_CPU(cs);
285
-
286
- if (cpu->kvm_target == QEMU_KVM_ARM_TARGET_NONE) {
287
- fprintf(stderr, "KVM is not supported for this guest CPU type\n");
288
- return -EINVAL;
289
- }
290
-
291
- qemu_add_vm_change_state_handler(kvm_arm_vm_state_change, cs);
292
-
293
- /* Determine init features for this CPU */
294
- memset(cpu->kvm_init_features, 0, sizeof(cpu->kvm_init_features));
295
- if (cs->start_powered_off) {
296
- cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_POWER_OFF;
297
- }
298
- if (kvm_check_extension(cs->kvm_state, KVM_CAP_ARM_PSCI_0_2)) {
299
- cpu->psci_version = 2;
300
- cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_PSCI_0_2;
301
- }
302
-
303
- /* Do KVM_ARM_VCPU_INIT ioctl */
304
- ret = kvm_arm_vcpu_init(cs);
305
- if (ret) {
306
- return ret;
307
- }
308
-
309
- /* Query the kernel to make sure it supports 32 VFP
310
- * registers: QEMU's "cortex-a15" CPU is always a
311
- * VFP-D32 core. The simplest way to do this is just
312
- * to attempt to read register d31.
313
- */
314
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP | 31;
315
- r.addr = (uintptr_t)(&v);
316
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
317
- if (ret == -ENOENT) {
318
- return -EINVAL;
319
- }
320
-
321
- /*
322
- * When KVM is in use, PSCI is emulated in-kernel and not by qemu.
323
- * Currently KVM has its own idea about MPIDR assignment, so we
324
- * override our defaults with what we get from KVM.
325
- */
326
- ret = kvm_get_one_reg(cs, ARM_CP15_REG32(ARM_CPU_ID_MPIDR), &mpidr);
327
- if (ret) {
328
- return ret;
329
- }
330
- cpu->mp_affinity = mpidr & ARM32_AFFINITY_MASK;
331
-
332
- /* Check whether userspace can specify guest syndrome value */
333
- kvm_arm_init_serror_injection(cs);
334
-
335
- return kvm_arm_init_cpreg_list(cpu);
336
-}
337
-
338
-int kvm_arch_destroy_vcpu(CPUState *cs)
339
-{
340
-    return 0;
341
-}
342
-
343
-typedef struct Reg {
344
- uint64_t id;
345
- int offset;
346
-} Reg;
347
-
348
-#define COREREG(KERNELNAME, QEMUFIELD) \
349
- { \
350
- KVM_REG_ARM | KVM_REG_SIZE_U32 | \
351
- KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(KERNELNAME), \
352
- offsetof(CPUARMState, QEMUFIELD) \
353
- }
354
-
355
-#define VFPSYSREG(R) \
356
- { \
357
- KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP | \
358
- KVM_REG_ARM_VFP_##R, \
359
- offsetof(CPUARMState, vfp.xregs[ARM_VFP_##R]) \
360
- }
361
-
362
-/* Like COREREG, but handle fields which are in a uint64_t in CPUARMState. */
363
-#define COREREG64(KERNELNAME, QEMUFIELD) \
364
- { \
365
- KVM_REG_ARM | KVM_REG_SIZE_U32 | \
366
- KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(KERNELNAME), \
367
- offsetoflow32(CPUARMState, QEMUFIELD) \
368
- }
369
-
370
-static const Reg regs[] = {
371
- /* R0_usr .. R14_usr */
372
- COREREG(usr_regs.uregs[0], regs[0]),
373
- COREREG(usr_regs.uregs[1], regs[1]),
374
- COREREG(usr_regs.uregs[2], regs[2]),
375
- COREREG(usr_regs.uregs[3], regs[3]),
376
- COREREG(usr_regs.uregs[4], regs[4]),
377
- COREREG(usr_regs.uregs[5], regs[5]),
378
- COREREG(usr_regs.uregs[6], regs[6]),
379
- COREREG(usr_regs.uregs[7], regs[7]),
380
- COREREG(usr_regs.uregs[8], usr_regs[0]),
381
- COREREG(usr_regs.uregs[9], usr_regs[1]),
382
- COREREG(usr_regs.uregs[10], usr_regs[2]),
383
- COREREG(usr_regs.uregs[11], usr_regs[3]),
384
- COREREG(usr_regs.uregs[12], usr_regs[4]),
385
- COREREG(usr_regs.uregs[13], banked_r13[BANK_USRSYS]),
386
- COREREG(usr_regs.uregs[14], banked_r14[BANK_USRSYS]),
387
- /* R13, R14, SPSR for SVC, ABT, UND, IRQ banks */
388
- COREREG(svc_regs[0], banked_r13[BANK_SVC]),
389
- COREREG(svc_regs[1], banked_r14[BANK_SVC]),
390
- COREREG64(svc_regs[2], banked_spsr[BANK_SVC]),
391
- COREREG(abt_regs[0], banked_r13[BANK_ABT]),
392
- COREREG(abt_regs[1], banked_r14[BANK_ABT]),
393
- COREREG64(abt_regs[2], banked_spsr[BANK_ABT]),
394
- COREREG(und_regs[0], banked_r13[BANK_UND]),
395
- COREREG(und_regs[1], banked_r14[BANK_UND]),
396
- COREREG64(und_regs[2], banked_spsr[BANK_UND]),
397
- COREREG(irq_regs[0], banked_r13[BANK_IRQ]),
398
- COREREG(irq_regs[1], banked_r14[BANK_IRQ]),
399
- COREREG64(irq_regs[2], banked_spsr[BANK_IRQ]),
400
- /* R8_fiq .. R14_fiq and SPSR_fiq */
401
- COREREG(fiq_regs[0], fiq_regs[0]),
402
- COREREG(fiq_regs[1], fiq_regs[1]),
403
- COREREG(fiq_regs[2], fiq_regs[2]),
404
- COREREG(fiq_regs[3], fiq_regs[3]),
405
- COREREG(fiq_regs[4], fiq_regs[4]),
406
- COREREG(fiq_regs[5], banked_r13[BANK_FIQ]),
407
- COREREG(fiq_regs[6], banked_r14[BANK_FIQ]),
408
- COREREG64(fiq_regs[7], banked_spsr[BANK_FIQ]),
409
- /* R15 */
410
- COREREG(usr_regs.uregs[15], regs[15]),
411
- /* VFP system registers */
412
- VFPSYSREG(FPSID),
413
- VFPSYSREG(MVFR1),
414
- VFPSYSREG(MVFR0),
415
- VFPSYSREG(FPEXC),
416
- VFPSYSREG(FPINST),
417
- VFPSYSREG(FPINST2),
418
-};
419
-
420
-int kvm_arch_put_registers(CPUState *cs, int level)
421
-{
422
- ARMCPU *cpu = ARM_CPU(cs);
423
- CPUARMState *env = &cpu->env;
424
- struct kvm_one_reg r;
425
- int mode, bn;
426
- int ret, i;
427
- uint32_t cpsr, fpscr;
428
-
429
- /* Make sure the banked regs are properly set */
430
- mode = env->uncached_cpsr & CPSR_M;
431
- bn = bank_number(mode);
432
- if (mode == ARM_CPU_MODE_FIQ) {
433
- memcpy(env->fiq_regs, env->regs + 8, 5 * sizeof(uint32_t));
434
- } else {
435
- memcpy(env->usr_regs, env->regs + 8, 5 * sizeof(uint32_t));
436
- }
437
- env->banked_r13[bn] = env->regs[13];
438
- env->banked_spsr[bn] = env->spsr;
439
- env->banked_r14[r14_bank_number(mode)] = env->regs[14];
440
-
441
- /* Now we can safely copy stuff down to the kernel */
442
- for (i = 0; i < ARRAY_SIZE(regs); i++) {
443
- r.id = regs[i].id;
444
- r.addr = (uintptr_t)(env) + regs[i].offset;
445
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
446
- if (ret) {
447
- return ret;
448
- }
449
- }
450
-
451
- /* Special cases which aren't a single CPUARMState field */
452
- cpsr = cpsr_read(env);
453
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 |
454
- KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(usr_regs.ARM_cpsr);
455
- r.addr = (uintptr_t)(&cpsr);
456
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
457
- if (ret) {
458
- return ret;
459
- }
460
-
461
- /* VFP registers */
462
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
463
- for (i = 0; i < 32; i++) {
464
- r.addr = (uintptr_t)aa32_vfp_dreg(env, i);
465
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
466
- if (ret) {
467
- return ret;
468
- }
469
- r.id++;
470
- }
471
-
472
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP |
473
- KVM_REG_ARM_VFP_FPSCR;
474
- fpscr = vfp_get_fpscr(env);
475
- r.addr = (uintptr_t)&fpscr;
476
- ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
477
- if (ret) {
478
- return ret;
479
- }
480
-
481
- write_cpustate_to_list(cpu, true);
482
-
483
- if (!write_list_to_kvmstate(cpu, level)) {
484
- return EINVAL;
485
- }
486
-
487
- /*
488
- * Setting VCPU events should be triggered after syncing the registers
489
- * to avoid overwriting potential changes made by KVM upon calling
490
- * KVM_SET_VCPU_EVENTS ioctl
491
- */
492
- ret = kvm_put_vcpu_events(cpu);
493
- if (ret) {
494
- return ret;
495
- }
496
-
497
- kvm_arm_sync_mpstate_to_kvm(cpu);
498
-
499
- return ret;
500
-}
501
-
502
-int kvm_arch_get_registers(CPUState *cs)
503
-{
504
- ARMCPU *cpu = ARM_CPU(cs);
505
- CPUARMState *env = &cpu->env;
506
- struct kvm_one_reg r;
507
- int mode, bn;
508
- int ret, i;
509
- uint32_t cpsr, fpscr;
510
-
511
- for (i = 0; i < ARRAY_SIZE(regs); i++) {
512
- r.id = regs[i].id;
513
- r.addr = (uintptr_t)(env) + regs[i].offset;
514
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
515
- if (ret) {
516
- return ret;
517
- }
518
- }
519
-
520
- /* Special cases which aren't a single CPUARMState field */
521
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 |
522
- KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(usr_regs.ARM_cpsr);
523
- r.addr = (uintptr_t)(&cpsr);
524
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
525
- if (ret) {
526
- return ret;
527
- }
528
- cpsr_write(env, cpsr, 0xffffffff, CPSRWriteRaw);
529
-
530
- /* Make sure the current mode regs are properly set */
531
- mode = env->uncached_cpsr & CPSR_M;
532
- bn = bank_number(mode);
533
- if (mode == ARM_CPU_MODE_FIQ) {
534
- memcpy(env->regs + 8, env->fiq_regs, 5 * sizeof(uint32_t));
535
- } else {
536
- memcpy(env->regs + 8, env->usr_regs, 5 * sizeof(uint32_t));
537
- }
538
- env->regs[13] = env->banked_r13[bn];
539
- env->spsr = env->banked_spsr[bn];
540
- env->regs[14] = env->banked_r14[r14_bank_number(mode)];
541
-
542
- /* VFP registers */
543
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
544
- for (i = 0; i < 32; i++) {
545
- r.addr = (uintptr_t)aa32_vfp_dreg(env, i);
546
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
547
- if (ret) {
548
- return ret;
549
- }
550
- r.id++;
551
- }
552
-
553
- r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP |
554
- KVM_REG_ARM_VFP_FPSCR;
555
- r.addr = (uintptr_t)&fpscr;
556
- ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
557
- if (ret) {
558
- return ret;
559
- }
560
- vfp_set_fpscr(env, fpscr);
561
-
562
- ret = kvm_get_vcpu_events(cpu);
563
- if (ret) {
564
- return ret;
565
- }
566
-
567
- if (!write_kvmstate_to_list(cpu)) {
568
- return EINVAL;
569
- }
570
- /* Note that it's OK to have registers which aren't in CPUState,
571
- * so we can ignore a failure return here.
572
- */
573
- write_list_to_cpustate(cpu);
574
-
575
- kvm_arm_sync_mpstate_to_qemu(cpu);
576
-
577
- return 0;
578
-}
579
-
580
-int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
581
-{
582
- qemu_log_mask(LOG_UNIMP, "%s: guest debug not yet implemented\n", __func__);
583
- return -EINVAL;
584
-}
585
-
586
-int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
587
-{
588
- qemu_log_mask(LOG_UNIMP, "%s: guest debug not yet implemented\n", __func__);
589
- return -EINVAL;
590
-}
591
-
592
-bool kvm_arm_handle_debug(CPUState *cs, struct kvm_debug_exit_arch *debug_exit)
593
-{
594
- qemu_log_mask(LOG_UNIMP, "%s: guest debug not yet implemented\n", __func__);
595
- return false;
596
-}
597
-
598
-int kvm_arch_insert_hw_breakpoint(target_ulong addr,
599
- target_ulong len, int type)
600
-{
601
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
602
- return -EINVAL;
603
-}
604
-
605
-int kvm_arch_remove_hw_breakpoint(target_ulong addr,
606
- target_ulong len, int type)
607
-{
608
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
609
- return -EINVAL;
610
-}
611
-
612
-void kvm_arch_remove_all_hw_breakpoints(void)
613
-{
614
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
615
-}
616
-
617
-void kvm_arm_copy_hw_debug_data(struct kvm_guest_debug_arch *ptr)
618
-{
619
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
620
-}
621
-
622
-bool kvm_arm_hw_debug_active(CPUState *cs)
623
-{
624
- return false;
625
-}
626
-
627
-void kvm_arm_pmu_set_irq(CPUState *cs, int irq)
628
-{
629
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
630
-}
631
-
632
-void kvm_arm_pmu_init(CPUState *cs)
633
-{
634
- qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
635
-}
636
-
637
-#define ARM_REG_DFSR ARM_CP15_REG32(0, 5, 0, 0)
638
-#define ARM_REG_TTBCR ARM_CP15_REG32(0, 2, 0, 2)
639
-/*
640
- *DFSR:
641
- * TTBCR.EAE == 0
642
- * FS[4] - DFSR[10]
643
- * FS[3:0] - DFSR[3:0]
644
- * TTBCR.EAE == 1
645
- * FS, bits [5:0]
646
- */
647
-#define DFSR_FSC(lpae, v) \
648
- ((lpae) ? ((v) & 0x3F) : (((v) >> 6) | ((v) & 0x1F)))
649
-
650
-#define DFSC_EXTABT(lpae) ((lpae) ? 0x10 : 0x08)
651
-
652
-bool kvm_arm_verify_ext_dabt_pending(CPUState *cs)
653
-{
654
- uint32_t dfsr_val;
655
-
656
- if (!kvm_get_one_reg(cs, ARM_REG_DFSR, &dfsr_val)) {
657
- ARMCPU *cpu = ARM_CPU(cs);
658
- CPUARMState *env = &cpu->env;
659
- uint32_t ttbcr;
660
- int lpae = 0;
661
-
662
- if (!kvm_get_one_reg(cs, ARM_REG_TTBCR, &ttbcr)) {
663
- lpae = arm_feature(env, ARM_FEATURE_LPAE) && (ttbcr & TTBCR_EAE);
664
- }
665
- /* The verification is based on FS filed of the DFSR reg only*/
666
- return (DFSR_FSC(lpae, dfsr_val) == DFSC_EXTABT(lpae));
667
- }
668
- return false;
669
-}
670
diff --git a/target/arm/meson.build b/target/arm/meson.build
671
index XXXXXXX..XXXXXXX 100644
672
--- a/target/arm/meson.build
673
+++ b/target/arm/meson.build
674
@@ -XXX,XX +XXX,XX @@ arm_ss.add(zlib)
675
676
arm_ss.add(when: 'CONFIG_TCG', if_true: files('arm-semi.c'))
677
678
-kvm_ss = ss.source_set()
679
-kvm_ss.add(when: 'TARGET_AARCH64', if_true: files('kvm64.c'), if_false: files('kvm32.c'))
680
-arm_ss.add_all(when: 'CONFIG_KVM', if_true: kvm_ss)
681
-arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'), if_false: files('kvm-stub.c'))
682
+arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c', 'kvm64.c'), if_false: files('kvm-stub.c'))
683
684
arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
685
'cpu64.c',
686
--
687
2.20.1
688
689
diff view generated by jsdifflib
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
1
In the m48t59 device we almost always use 64-bit arithmetic when
2
dealing with time_t deltas. The one exception is in set_alarm(),
3
which currently uses a plain 'int' to hold the difference between two
4
time_t values. Switch to int64_t instead to avoid any possible
5
overflow issues.
2
6
3
Correct the GEMs tx/rx clocks to use the 125Mhz fixed-clock.
4
This matches the setup with the fixed-link 100Mbit PHY.
5
It also avoids the following warnings from the Linux kernel
6
driver:
7
8
eth0: unable to generate target frequency: 125000000 Hz
9
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
12
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
13
Message-id: 20200909174647.662864-2-edgar.iglesias@gmail.com
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
15
---
9
---
16
hw/arm/xlnx-versal-virt.c | 2 +-
10
hw/rtc/m48t59.c | 2 +-
17
1 file changed, 1 insertion(+), 1 deletion(-)
11
1 file changed, 1 insertion(+), 1 deletion(-)
18
12
19
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
13
diff --git a/hw/rtc/m48t59.c b/hw/rtc/m48t59.c
20
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/arm/xlnx-versal-virt.c
15
--- a/hw/rtc/m48t59.c
22
+++ b/hw/arm/xlnx-versal-virt.c
16
+++ b/hw/rtc/m48t59.c
23
@@ -XXX,XX +XXX,XX @@ static void fdt_add_gem_nodes(VersalVirt *s)
17
@@ -XXX,XX +XXX,XX @@ static void alarm_cb (void *opaque)
24
s->phandle.ethernet_phy[i]);
18
25
qemu_fdt_setprop_cells(s->fdt, name, "clocks",
19
static void set_alarm(M48t59State *NVRAM)
26
s->phandle.clk_25Mhz, s->phandle.clk_25Mhz,
20
{
27
- s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
21
- int diff;
28
+ s->phandle.clk_125Mhz, s->phandle.clk_125Mhz);
22
+ int64_t diff;
29
qemu_fdt_setprop(s->fdt, name, "clock-names",
23
if (NVRAM->alrm_timer != NULL) {
30
clocknames, sizeof(clocknames));
24
timer_del(NVRAM->alrm_timer);
31
qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
25
diff = qemu_timedate_diff(&NVRAM->alarm) - NVRAM->time_offset;
32
--
26
--
33
2.20.1
27
2.34.1
34
28
35
29
diff view generated by jsdifflib
1
Deprecate our lm32 target support. Michael Walle (former lm32 maintainer)
1
In the twl92230 device, use int64_t for the two state fields
2
suggested that we do this in 2019:
2
sec_offset and alm_sec, because we set these to values that
3
https://www.mail-archive.com/qemu-devel@nongnu.org/msg605024.html
3
are either time_t or differences between two time_t values.
4
because the only public user of the architecture is the many-years-dead
5
milkymist project. (The Linux port to lm32 was never merged upstream.)
6
4
7
In commit 4b4d96c776f552e (March 2020) we marked it as 'orphan' in
5
These fields aren't saved in vmstate anywhere, so we can
8
the MAINTAINERS file, but didn't officially deprecate it. Mark it
6
safely widen them.
9
deprecated now, with the intention of removing it from QEMU in
10
mid-2021 before the 6.1 release.
11
7
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Reviewed-by: Thomas Huth <thuth@redhat.com>
16
Acked-by: Michael Walle <michael@walle.cc>
17
Message-id: 20200827113259.25064-1-peter.maydell@linaro.org
18
---
10
---
19
docs/system/deprecated.rst | 8 ++++++++
11
hw/rtc/twl92230.c | 4 ++--
20
1 file changed, 8 insertions(+)
12
1 file changed, 2 insertions(+), 2 deletions(-)
21
13
22
diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
14
diff --git a/hw/rtc/twl92230.c b/hw/rtc/twl92230.c
23
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
24
--- a/docs/system/deprecated.rst
16
--- a/hw/rtc/twl92230.c
25
+++ b/docs/system/deprecated.rst
17
+++ b/hw/rtc/twl92230.c
26
@@ -XXX,XX +XXX,XX @@ The above, converted to the current supported format::
18
@@ -XXX,XX +XXX,XX @@ struct MenelausState {
27
linux-user mode CPUs
19
struct tm tm;
28
--------------------
20
struct tm new;
29
21
struct tm alm;
30
+``lm32`` CPUs (since 5.2.0)
22
- int sec_offset;
31
+'''''''''''''''''''''''''''
23
- int alm_sec;
32
+
24
+ int64_t sec_offset;
33
+The ``lm32`` guest CPU support is deprecated and will be removed in
25
+ int64_t alm_sec;
34
+a future version of QEMU. The only public user of this architecture
26
int next_comp;
35
+was the milkymist project, which has been dead for years; there was
27
} rtc;
36
+never an upstream Linux port.
28
uint16_t rtc_next_vmstate;
37
+
38
``unicore32`` CPUs (since 5.2.0)
39
''''''''''''''''''''''''''''''''
40
41
--
29
--
42
2.20.1
30
2.34.1
43
31
44
32
diff view generated by jsdifflib
1
Deprecate our Unicore32 target support:
1
In the aspeed_rtc device we store a difference between two time_t
2
* the Linux kernel dropped support for unicore32 in commit
2
values in an 'int'. This is not really correct when time_t could
3
05119217a9bd199c for its 5.9 release (with rationale in the
3
be 64 bits. Enlarge the field to 'int64_t'.
4
cover letter: https://lkml.org/lkml/2020/8/3/232 )
4
5
* there is apparently no upstream toolchain that can create unicore32
5
This is a migration compatibility break for the aspeed boards.
6
binaries
6
While we are changing the vmstate, remove the accidental
7
* the maintainer doesn't seem to have made any contributions to
7
duplicate of the offset field.
8
QEMU since the port first landed in 2012
9
* nobody else seems to have made changes to the unicore code except
10
for generic cleanups either
11
8
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
10
Reviewed-by: Cédric Le Goater <clg@kaod.org>
14
Message-id: 20200825172719.19422-1-peter.maydell@linaro.org
15
---
11
---
16
docs/system/deprecated.rst | 8 ++++++++
12
include/hw/rtc/aspeed_rtc.h | 2 +-
17
1 file changed, 8 insertions(+)
13
hw/rtc/aspeed_rtc.c | 5 ++---
14
2 files changed, 3 insertions(+), 4 deletions(-)
18
15
19
diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
16
diff --git a/include/hw/rtc/aspeed_rtc.h b/include/hw/rtc/aspeed_rtc.h
20
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
21
--- a/docs/system/deprecated.rst
18
--- a/include/hw/rtc/aspeed_rtc.h
22
+++ b/docs/system/deprecated.rst
19
+++ b/include/hw/rtc/aspeed_rtc.h
23
@@ -XXX,XX +XXX,XX @@ The above, converted to the current supported format::
20
@@ -XXX,XX +XXX,XX @@ struct AspeedRtcState {
24
linux-user mode CPUs
21
qemu_irq irq;
25
--------------------
22
26
23
uint32_t reg[0x18];
27
+``unicore32`` CPUs (since 5.2.0)
24
- int offset;
28
+''''''''''''''''''''''''''''''''
25
+ int64_t offset;
29
+
26
30
+The ``unicore32`` guest CPU support is deprecated and will be removed in
27
};
31
+a future version of QEMU. Support for this CPU was removed from the
28
32
+upstream Linux kernel, and there is no available upstream toolchain
29
diff --git a/hw/rtc/aspeed_rtc.c b/hw/rtc/aspeed_rtc.c
33
+to build binaries for it.
30
index XXXXXXX..XXXXXXX 100644
34
+
31
--- a/hw/rtc/aspeed_rtc.c
35
``tilegx`` CPUs (since 5.1.0)
32
+++ b/hw/rtc/aspeed_rtc.c
36
'''''''''''''''''''''''''''''
33
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps aspeed_rtc_ops = {
37
34
35
static const VMStateDescription vmstate_aspeed_rtc = {
36
.name = TYPE_ASPEED_RTC,
37
- .version_id = 1,
38
+ .version_id = 2,
39
.fields = (VMStateField[]) {
40
VMSTATE_UINT32_ARRAY(reg, AspeedRtcState, 0x18),
41
- VMSTATE_INT32(offset, AspeedRtcState),
42
- VMSTATE_INT32(offset, AspeedRtcState),
43
+ VMSTATE_INT64(offset, AspeedRtcState),
44
VMSTATE_END_OF_LIST()
45
}
46
};
38
--
47
--
39
2.20.1
48
2.34.1
40
49
41
50
diff view generated by jsdifflib
1
Implement a model of the MPS2 with the AN500 firmware. This is
1
The functions qemu_get_timedate() and qemu_timedate_diff() take
2
similar to the AN385, with the following differences:
2
and return a time offset as an integer. Coverity points out that
3
* Cortex-M7 CPU
3
means that when an RTC device implementation holds an offset
4
* PSRAM is at 0x6000_0000
4
as a time_t, as the m48t59 does, the time_t will get truncated.
5
* Ethernet is at 0xa000_0000
5
(CID 1507157, 1517772).
6
* No zbt_boot_ctrl remapping of the low 16K
6
7
(but QEMU doesn't implement this anyway)
7
The functions work with time_t internally, so make them use that type
8
* no "block RAM" at 0x01000000
8
in their APIs.
9
10
Note that this won't help any Y2038 issues where either the device
11
model itself is keeping the offset in a 32-bit integer, or where the
12
hardware under emulation has Y2038 or other rollover problems. If we
13
missed any cases of the former then hopefully Coverity will warn us
14
about them since after this patch we'd be truncating a time_t in
15
assignments from qemu_timedate_diff().)
9
16
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
Message-id: 20200903202048.15370-3-peter.maydell@linaro.org
13
---
19
---
14
docs/system/arm/mps2.rst | 6 ++--
20
include/sysemu/rtc.h | 4 ++--
15
hw/arm/mps2.c | 67 +++++++++++++++++++++++++++++++++-------
21
softmmu/rtc.c | 4 ++--
16
2 files changed, 60 insertions(+), 13 deletions(-)
22
2 files changed, 4 insertions(+), 4 deletions(-)
17
23
18
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
24
diff --git a/include/sysemu/rtc.h b/include/sysemu/rtc.h
19
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
20
--- a/docs/system/arm/mps2.rst
26
--- a/include/sysemu/rtc.h
21
+++ b/docs/system/arm/mps2.rst
27
+++ b/include/sysemu/rtc.h
22
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@
23
-Arm MPS2 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
29
* The behaviour of the clock whose value this function returns will
24
-================================================================================================
30
* depend on the -rtc command line option passed by the user.
25
+Arm MPS2 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
31
*/
26
+================================================================================================================
32
-void qemu_get_timedate(struct tm *tm, int offset);
27
33
+void qemu_get_timedate(struct tm *tm, time_t offset);
28
These board models all use Arm M-profile CPUs.
34
29
35
/**
30
@@ -XXX,XX +XXX,XX @@ QEMU models the following FPGA images:
36
* qemu_timedate_diff: Return difference between a struct tm and the RTC
31
Cortex-M3 as documented in ARM Application Note AN385
37
@@ -XXX,XX +XXX,XX @@ void qemu_get_timedate(struct tm *tm, int offset);
32
``mps2-an386``
38
* a timestamp one hour further ahead than the current RTC time
33
Cortex-M4 as documented in ARM Application Note AN386
39
* then this function will return 3600.
34
+``mps2-an500``
40
*/
35
+ Cortex-M7 as documented in ARM Application Note AN500
41
-int qemu_timedate_diff(struct tm *tm);
36
``mps2-an511``
42
+time_t qemu_timedate_diff(struct tm *tm);
37
Cortex-M3 'DesignStart' as documented in AN511
43
38
``mps2-an505``
44
#endif
39
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
45
diff --git a/softmmu/rtc.c b/softmmu/rtc.c
40
index XXXXXXX..XXXXXXX 100644
46
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/arm/mps2.c
47
--- a/softmmu/rtc.c
42
+++ b/hw/arm/mps2.c
48
+++ b/softmmu/rtc.c
43
@@ -XXX,XX +XXX,XX @@
49
@@ -XXX,XX +XXX,XX @@ static time_t qemu_ref_timedate(QEMUClockType clock)
44
* We model the following FPGA images:
50
return value;
45
* "mps2-an385" -- Cortex-M3 as documented in ARM Application Note AN385
46
* "mps2-an386" -- Cortex-M4 as documented in ARM Application Note AN386
47
+ * "mps2-an500" -- Cortex-M7 as documented in ARM Application Note AN500
48
* "mps2-an511" -- Cortex-M3 'DesignStart' as documented in AN511
49
*
50
* Links to the TRM for the board itself and to the various Application
51
@@ -XXX,XX +XXX,XX @@
52
typedef enum MPS2FPGAType {
53
FPGA_AN385,
54
FPGA_AN386,
55
+ FPGA_AN500,
56
FPGA_AN511,
57
} MPS2FPGAType;
58
59
@@ -XXX,XX +XXX,XX @@ struct MPS2MachineClass {
60
MachineClass parent;
61
MPS2FPGAType fpga_type;
62
uint32_t scc_id;
63
+ bool has_block_ram;
64
+ hwaddr ethernet_base;
65
+ hwaddr psram_base;
66
};
67
typedef struct MPS2MachineClass MPS2MachineClass;
68
69
@@ -XXX,XX +XXX,XX @@ typedef struct MPS2MachineState MPS2MachineState;
70
#define TYPE_MPS2_MACHINE "mps2"
71
#define TYPE_MPS2_AN385_MACHINE MACHINE_TYPE_NAME("mps2-an385")
72
#define TYPE_MPS2_AN386_MACHINE MACHINE_TYPE_NAME("mps2-an386")
73
+#define TYPE_MPS2_AN500_MACHINE MACHINE_TYPE_NAME("mps2-an500")
74
#define TYPE_MPS2_AN511_MACHINE MACHINE_TYPE_NAME("mps2-an511")
75
76
DECLARE_OBJ_CHECKERS(MPS2MachineState, MPS2MachineClass,
77
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
78
*
79
* AN385/AN386/AN511:
80
* 0x21000000 .. 0x21ffffff : PSRAM (16MB)
81
- * AN385/AN386 only:
82
+ * AN385/AN386/AN500:
83
* 0x00000000 .. 0x003fffff : ZBT SSRAM1
84
* 0x00400000 .. 0x007fffff : mirror of ZBT SSRAM1
85
* 0x20000000 .. 0x203fffff : ZBT SSRAM 2&3
86
* 0x20400000 .. 0x207fffff : mirror of ZBT SSRAM 2&3
87
+ * AN385/AN386 only:
88
* 0x01000000 .. 0x01003fff : block RAM (16K)
89
* 0x01004000 .. 0x01007fff : mirror of above
90
* 0x01008000 .. 0x0100bfff : mirror of above
91
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
92
* 0x00400000 .. 0x007fffff : ZBT SSRAM1
93
* 0x20000000 .. 0x2001ffff : SRAM
94
* 0x20400000 .. 0x207fffff : ZBT SSRAM 2&3
95
+ * AN500 only:
96
+ * 0x60000000 .. 0x60ffffff : PSRAM (16MB)
97
*
98
* The AN385/AN386 has a feature where the lowest 16K can be mapped
99
* either to the bottom of the ZBT SSRAM1 or to the block RAM.
100
* This is of no use for QEMU so we don't implement it (as if
101
* zbt_boot_ctrl is always zero).
102
*/
103
- memory_region_add_subregion(system_memory, 0x21000000, machine->ram);
104
+ memory_region_add_subregion(system_memory, mmc->psram_base, machine->ram);
105
106
- switch (mmc->fpga_type) {
107
- case FPGA_AN385:
108
- case FPGA_AN386:
109
- make_ram(&mms->ssram1, "mps.ssram1", 0x0, 0x400000);
110
- make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x400000);
111
- make_ram(&mms->ssram23, "mps.ssram23", 0x20000000, 0x400000);
112
- make_ram_alias(&mms->ssram23_m, "mps.ssram23_m",
113
- &mms->ssram23, 0x20400000);
114
+ if (mmc->has_block_ram) {
115
make_ram(&mms->blockram, "mps.blockram", 0x01000000, 0x4000);
116
make_ram_alias(&mms->blockram_m1, "mps.blockram_m1",
117
&mms->blockram, 0x01004000);
118
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
119
&mms->blockram, 0x01008000);
120
make_ram_alias(&mms->blockram_m3, "mps.blockram_m3",
121
&mms->blockram, 0x0100c000);
122
+ }
123
+
124
+ switch (mmc->fpga_type) {
125
+ case FPGA_AN385:
126
+ case FPGA_AN386:
127
+ case FPGA_AN500:
128
+ make_ram(&mms->ssram1, "mps.ssram1", 0x0, 0x400000);
129
+ make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x400000);
130
+ make_ram(&mms->ssram23, "mps.ssram23", 0x20000000, 0x400000);
131
+ make_ram_alias(&mms->ssram23_m, "mps.ssram23_m",
132
+ &mms->ssram23, 0x20400000);
133
break;
134
case FPGA_AN511:
135
make_ram(&mms->blockram, "mps.blockram", 0x0, 0x40000);
136
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
137
switch (mmc->fpga_type) {
138
case FPGA_AN385:
139
case FPGA_AN386:
140
+ case FPGA_AN500:
141
qdev_prop_set_uint32(armv7m, "num-irq", 32);
142
break;
143
case FPGA_AN511:
144
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
145
switch (mmc->fpga_type) {
146
case FPGA_AN385:
147
case FPGA_AN386:
148
+ case FPGA_AN500:
149
{
150
/* The overflow IRQs for UARTs 0, 1 and 2 are ORed together.
151
* Overflow for UARTs 4 and 5 doesn't trigger any interrupt.
152
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
153
/* In hardware this is a LAN9220; the LAN9118 is software compatible
154
* except that it doesn't support the checksum-offload feature.
155
*/
156
- lan9118_init(&nd_table[0], 0x40200000,
157
+ lan9118_init(&nd_table[0], mmc->ethernet_base,
158
qdev_get_gpio_in(armv7m,
159
mmc->fpga_type == FPGA_AN511 ? 47 : 13));
160
161
@@ -XXX,XX +XXX,XX @@ static void mps2_an385_class_init(ObjectClass *oc, void *data)
162
mmc->fpga_type = FPGA_AN385;
163
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m3");
164
mmc->scc_id = 0x41043850;
165
+ mmc->psram_base = 0x21000000;
166
+ mmc->ethernet_base = 0x40200000;
167
+ mmc->has_block_ram = true;
168
}
51
}
169
52
170
static void mps2_an386_class_init(ObjectClass *oc, void *data)
53
-void qemu_get_timedate(struct tm *tm, int offset)
171
@@ -XXX,XX +XXX,XX @@ static void mps2_an386_class_init(ObjectClass *oc, void *data)
54
+void qemu_get_timedate(struct tm *tm, time_t offset)
172
mmc->fpga_type = FPGA_AN386;
55
{
173
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m4");
56
time_t ti = qemu_ref_timedate(rtc_clock);
174
mmc->scc_id = 0x41043860;
57
175
+ mmc->psram_base = 0x21000000;
58
@@ -XXX,XX +XXX,XX @@ void qemu_get_timedate(struct tm *tm, int offset)
176
+ mmc->ethernet_base = 0x40200000;
59
}
177
+ mmc->has_block_ram = true;
178
+}
179
+
180
+static void mps2_an500_class_init(ObjectClass *oc, void *data)
181
+{
182
+ MachineClass *mc = MACHINE_CLASS(oc);
183
+ MPS2MachineClass *mmc = MPS2_MACHINE_CLASS(oc);
184
+
185
+ mc->desc = "ARM MPS2 with AN500 FPGA image for Cortex-M7";
186
+ mmc->fpga_type = FPGA_AN500;
187
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m7");
188
+ mmc->scc_id = 0x41045000;
189
+ mmc->psram_base = 0x60000000;
190
+ mmc->ethernet_base = 0xa0000000;
191
+ mmc->has_block_ram = false;
192
}
60
}
193
61
194
static void mps2_an511_class_init(ObjectClass *oc, void *data)
62
-int qemu_timedate_diff(struct tm *tm)
195
@@ -XXX,XX +XXX,XX @@ static void mps2_an511_class_init(ObjectClass *oc, void *data)
63
+time_t qemu_timedate_diff(struct tm *tm)
196
mmc->fpga_type = FPGA_AN511;
64
{
197
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m3");
65
time_t seconds;
198
mmc->scc_id = 0x41045110;
199
+ mmc->psram_base = 0x21000000;
200
+ mmc->ethernet_base = 0x40200000;
201
+ mmc->has_block_ram = false;
202
}
203
204
static const TypeInfo mps2_info = {
205
@@ -XXX,XX +XXX,XX @@ static const TypeInfo mps2_an386_info = {
206
.class_init = mps2_an386_class_init,
207
};
208
209
+static const TypeInfo mps2_an500_info = {
210
+ .name = TYPE_MPS2_AN500_MACHINE,
211
+ .parent = TYPE_MPS2_MACHINE,
212
+ .class_init = mps2_an500_class_init,
213
+};
214
+
215
static const TypeInfo mps2_an511_info = {
216
.name = TYPE_MPS2_AN511_MACHINE,
217
.parent = TYPE_MPS2_MACHINE,
218
@@ -XXX,XX +XXX,XX @@ static void mps2_machine_init(void)
219
type_register_static(&mps2_info);
220
type_register_static(&mps2_an385_info);
221
type_register_static(&mps2_an386_info);
222
+ type_register_static(&mps2_an500_info);
223
type_register_static(&mps2_an511_info);
224
}
225
66
226
--
67
--
227
2.20.1
68
2.34.1
228
69
229
70
diff view generated by jsdifflib
1
Now that 32-bit KVM host support is gone, KVM can never
1
Where architecturally one ARM_FEATURE_X flag implies another
2
be enabled unless CONFIG_AARCH64 is true, and some code
2
ARM_FEATURE_Y, we allow the CPU init function to only set X, and then
3
paths are no longer reachable and can be deleted.
3
set Y for it. Currently we do this in two places -- we set a few
4
flags in arm_cpu_post_init() because we need them to decide which
5
properties to create on the CPU object, and then we do the rest in
6
arm_cpu_realizefn(). However, this is fragile, because it's easy to
7
add a new property and not notice that this means that an X-implies-Y
8
check now has to move from realize to post-init.
9
10
As a specific example, the pmsav7-dregion property is conditional
11
on ARM_FEATURE_PMSA && ARM_FEATURE_V7, which means it won't appear
12
on the Cortex-M33 and -M55, because they set ARM_FEATURE_V8 and
13
rely on V8-implies-V7, which doesn't happen until the realizefn.
14
15
Move all of these X-implies-Y checks into a new function, which
16
we call at the top of arm_cpu_post_init(), so the feature bits
17
are available at that point.
18
19
This does now give us the reverse issue, that if there's a feature
20
bit which is enabled or disabled by the setting of a property then
21
then X-implies-Y features that are dependent on that property need to
22
be in realize, not in this new function. But the only one of those
23
is the "EL3 implies VBAR" which is already in the right place, so
24
putting things this way round seems better to me.
4
25
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
27
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
28
Message-id: 20230724174335.2150499-2-peter.maydell@linaro.org
8
Message-id: 20200904154156.31943-3-peter.maydell@linaro.org
9
---
29
---
10
target/arm/kvm-consts.h | 7 ---
30
target/arm/cpu.c | 179 +++++++++++++++++++++++++----------------------
11
target/arm/kvm_arm.h | 6 ---
31
1 file changed, 97 insertions(+), 82 deletions(-)
12
target/arm/cpu.c | 101 +++++++++++++++++++---------------------
32
13
target/arm/kvm.c | 7 ---
14
4 files changed, 47 insertions(+), 74 deletions(-)
15
16
diff --git a/target/arm/kvm-consts.h b/target/arm/kvm-consts.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/kvm-consts.h
19
+++ b/target/arm/kvm-consts.h
20
@@ -XXX,XX +XXX,XX @@ MISMATCH_CHECK(QEMU_PSCI_RET_DISABLED, PSCI_RET_DISABLED);
21
*/
22
#define QEMU_KVM_ARM_TARGET_NONE UINT_MAX
23
24
-#ifdef TARGET_AARCH64
25
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_AEM_V8, KVM_ARM_TARGET_AEM_V8);
26
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_FOUNDATION_V8, KVM_ARM_TARGET_FOUNDATION_V8);
27
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A57, KVM_ARM_TARGET_CORTEX_A57);
28
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_XGENE_POTENZA, KVM_ARM_TARGET_XGENE_POTENZA);
29
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A53, KVM_ARM_TARGET_CORTEX_A53);
30
-#else
31
-MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A15, KVM_ARM_TARGET_CORTEX_A15);
32
-MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A7, KVM_ARM_TARGET_CORTEX_A7);
33
-#endif
34
35
#define CP_REG_ARM64 0x6000000000000000ULL
36
#define CP_REG_ARM_COPROC_MASK 0x000000000FFF0000
37
@@ -XXX,XX +XXX,XX @@ MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A7, KVM_ARM_TARGET_CORTEX_A7);
38
/* No kernel define but it's useful to QEMU */
39
#define CP_REG_ARM64_SYSREG_CP (CP_REG_ARM64_SYSREG >> CP_REG_ARM_COPROC_SHIFT)
40
41
-#ifdef TARGET_AARCH64
42
MISMATCH_CHECK(CP_REG_ARM64, KVM_REG_ARM64);
43
MISMATCH_CHECK(CP_REG_ARM_COPROC_MASK, KVM_REG_ARM_COPROC_MASK);
44
MISMATCH_CHECK(CP_REG_ARM_COPROC_SHIFT, KVM_REG_ARM_COPROC_SHIFT);
45
@@ -XXX,XX +XXX,XX @@ MISMATCH_CHECK(CP_REG_ARM64_SYSREG_CRM_MASK, KVM_REG_ARM64_SYSREG_CRM_MASK);
46
MISMATCH_CHECK(CP_REG_ARM64_SYSREG_CRM_SHIFT, KVM_REG_ARM64_SYSREG_CRM_SHIFT);
47
MISMATCH_CHECK(CP_REG_ARM64_SYSREG_OP2_MASK, KVM_REG_ARM64_SYSREG_OP2_MASK);
48
MISMATCH_CHECK(CP_REG_ARM64_SYSREG_OP2_SHIFT, KVM_REG_ARM64_SYSREG_OP2_SHIFT);
49
-#endif
50
51
#undef MISMATCH_CHECK
52
53
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
54
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/kvm_arm.h
56
+++ b/target/arm/kvm_arm.h
57
@@ -XXX,XX +XXX,XX @@ static inline const char *gic_class_name(void)
58
static inline const char *gicv3_class_name(void)
59
{
60
if (kvm_irqchip_in_kernel()) {
61
-#ifdef TARGET_AARCH64
62
return "kvm-arm-gicv3";
63
-#else
64
- error_report("KVM GICv3 acceleration is not supported on this "
65
- "platform");
66
- exit(1);
67
-#endif
68
} else {
69
if (kvm_enabled()) {
70
error_report("Userspace GICv3 is not supported with KVM");
71
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
33
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
72
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
73
--- a/target/arm/cpu.c
35
--- a/target/arm/cpu.c
74
+++ b/target/arm/cpu.c
36
+++ b/target/arm/cpu.c
75
@@ -XXX,XX +XXX,XX @@ static void cortex_a15_initfn(Object *obj)
37
@@ -XXX,XX +XXX,XX @@ unsigned int gt_cntfrq_period_ns(ARMCPU *cpu)
38
NANOSECONDS_PER_SECOND / cpu->gt_cntfrq_hz : 1;
76
}
39
}
77
40
78
#ifndef TARGET_AARCH64
41
+static void arm_cpu_propagate_feature_implications(ARMCPU *cpu)
79
-/* -cpu max: if KVM is enabled, like -cpu host (best possible with this host);
42
+{
80
- * otherwise, a CPU with as many features enabled as our emulation supports.
43
+ CPUARMState *env = &cpu->env;
81
+/*
44
+ bool no_aa32 = false;
82
+ * -cpu max: a CPU with as many features enabled as our emulation supports.
45
+
83
* The version of '-cpu max' for qemu-system-aarch64 is defined in cpu64.c;
46
+ /*
84
- * this only needs to handle 32 bits.
47
+ * Some features automatically imply others: set the feature
85
+ * this only needs to handle 32 bits, and need not care about KVM.
48
+ * bits explicitly for these cases.
86
*/
49
+ */
87
static void arm_max_initfn(Object *obj)
50
+
51
+ if (arm_feature(env, ARM_FEATURE_M)) {
52
+ set_feature(env, ARM_FEATURE_PMSA);
53
+ }
54
+
55
+ if (arm_feature(env, ARM_FEATURE_V8)) {
56
+ if (arm_feature(env, ARM_FEATURE_M)) {
57
+ set_feature(env, ARM_FEATURE_V7);
58
+ } else {
59
+ set_feature(env, ARM_FEATURE_V7VE);
60
+ }
61
+ }
62
+
63
+ /*
64
+ * There exist AArch64 cpus without AArch32 support. When KVM
65
+ * queries ID_ISAR0_EL1 on such a host, the value is UNKNOWN.
66
+ * Similarly, we cannot check ID_AA64PFR0 without AArch64 support.
67
+ * As a general principle, we also do not make ID register
68
+ * consistency checks anywhere unless using TCG, because only
69
+ * for TCG would a consistency-check failure be a QEMU bug.
70
+ */
71
+ if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
72
+ no_aa32 = !cpu_isar_feature(aa64_aa32, cpu);
73
+ }
74
+
75
+ if (arm_feature(env, ARM_FEATURE_V7VE)) {
76
+ /*
77
+ * v7 Virtualization Extensions. In real hardware this implies
78
+ * EL2 and also the presence of the Security Extensions.
79
+ * For QEMU, for backwards-compatibility we implement some
80
+ * CPUs or CPU configs which have no actual EL2 or EL3 but do
81
+ * include the various other features that V7VE implies.
82
+ * Presence of EL2 itself is ARM_FEATURE_EL2, and of the
83
+ * Security Extensions is ARM_FEATURE_EL3.
84
+ */
85
+ assert(!tcg_enabled() || no_aa32 ||
86
+ cpu_isar_feature(aa32_arm_div, cpu));
87
+ set_feature(env, ARM_FEATURE_LPAE);
88
+ set_feature(env, ARM_FEATURE_V7);
89
+ }
90
+ if (arm_feature(env, ARM_FEATURE_V7)) {
91
+ set_feature(env, ARM_FEATURE_VAPA);
92
+ set_feature(env, ARM_FEATURE_THUMB2);
93
+ set_feature(env, ARM_FEATURE_MPIDR);
94
+ if (!arm_feature(env, ARM_FEATURE_M)) {
95
+ set_feature(env, ARM_FEATURE_V6K);
96
+ } else {
97
+ set_feature(env, ARM_FEATURE_V6);
98
+ }
99
+
100
+ /*
101
+ * Always define VBAR for V7 CPUs even if it doesn't exist in
102
+ * non-EL3 configs. This is needed by some legacy boards.
103
+ */
104
+ set_feature(env, ARM_FEATURE_VBAR);
105
+ }
106
+ if (arm_feature(env, ARM_FEATURE_V6K)) {
107
+ set_feature(env, ARM_FEATURE_V6);
108
+ set_feature(env, ARM_FEATURE_MVFR);
109
+ }
110
+ if (arm_feature(env, ARM_FEATURE_V6)) {
111
+ set_feature(env, ARM_FEATURE_V5);
112
+ if (!arm_feature(env, ARM_FEATURE_M)) {
113
+ assert(!tcg_enabled() || no_aa32 ||
114
+ cpu_isar_feature(aa32_jazelle, cpu));
115
+ set_feature(env, ARM_FEATURE_AUXCR);
116
+ }
117
+ }
118
+ if (arm_feature(env, ARM_FEATURE_V5)) {
119
+ set_feature(env, ARM_FEATURE_V4T);
120
+ }
121
+ if (arm_feature(env, ARM_FEATURE_LPAE)) {
122
+ set_feature(env, ARM_FEATURE_V7MP);
123
+ }
124
+ if (arm_feature(env, ARM_FEATURE_CBAR_RO)) {
125
+ set_feature(env, ARM_FEATURE_CBAR);
126
+ }
127
+ if (arm_feature(env, ARM_FEATURE_THUMB2) &&
128
+ !arm_feature(env, ARM_FEATURE_M)) {
129
+ set_feature(env, ARM_FEATURE_THUMB_DSP);
130
+ }
131
+}
132
+
133
void arm_cpu_post_init(Object *obj)
88
{
134
{
89
ARMCPU *cpu = ARM_CPU(obj);
135
ARMCPU *cpu = ARM_CPU(obj);
90
136
91
- if (kvm_enabled()) {
137
- /* M profile implies PMSA. We have to do this here rather than
92
- kvm_arm_set_cpu_features_from_host(cpu);
138
- * in realize with the other feature-implication checks because
93
- } else {
139
- * we look at the PMSA bit to see if we should add some properties.
94
- cortex_a15_initfn(obj);
140
+ /*
95
+ cortex_a15_initfn(obj);
141
+ * Some features imply others. Figure this out now, because we
96
142
+ * are going to look at the feature bits in deciding which
97
- /* old-style VFP short-vector support */
143
+ * properties to add.
98
- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
144
*/
99
+ /* old-style VFP short-vector support */
145
- if (arm_feature(&cpu->env, ARM_FEATURE_M)) {
100
+ cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
146
- set_feature(&cpu->env, ARM_FEATURE_PMSA);
101
147
- }
102
#ifdef CONFIG_USER_ONLY
148
+ arm_cpu_propagate_feature_implications(cpu);
103
- /* We don't set these in system emulation mode for the moment,
149
104
- * since we don't correctly set (all of) the ID registers to
150
if (arm_feature(&cpu->env, ARM_FEATURE_CBAR) ||
105
- * advertise them.
151
arm_feature(&cpu->env, ARM_FEATURE_CBAR_RO)) {
152
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
153
CPUARMState *env = &cpu->env;
154
int pagebits;
155
Error *local_err = NULL;
156
- bool no_aa32 = false;
157
158
/* Use pc-relative instructions in system-mode */
159
#ifndef CONFIG_USER_ONLY
160
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
161
cpu->isar.id_isar3 = u;
162
}
163
164
- /* Some features automatically imply others: */
165
- if (arm_feature(env, ARM_FEATURE_V8)) {
166
- if (arm_feature(env, ARM_FEATURE_M)) {
167
- set_feature(env, ARM_FEATURE_V7);
168
- } else {
169
- set_feature(env, ARM_FEATURE_V7VE);
170
- }
171
- }
172
-
173
- /*
174
- * There exist AArch64 cpus without AArch32 support. When KVM
175
- * queries ID_ISAR0_EL1 on such a host, the value is UNKNOWN.
176
- * Similarly, we cannot check ID_AA64PFR0 without AArch64 support.
177
- * As a general principle, we also do not make ID register
178
- * consistency checks anywhere unless using TCG, because only
179
- * for TCG would a consistency-check failure be a QEMU bug.
180
- */
181
- if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
182
- no_aa32 = !cpu_isar_feature(aa64_aa32, cpu);
183
- }
184
-
185
- if (arm_feature(env, ARM_FEATURE_V7VE)) {
186
- /* v7 Virtualization Extensions. In real hardware this implies
187
- * EL2 and also the presence of the Security Extensions.
188
- * For QEMU, for backwards-compatibility we implement some
189
- * CPUs or CPU configs which have no actual EL2 or EL3 but do
190
- * include the various other features that V7VE implies.
191
- * Presence of EL2 itself is ARM_FEATURE_EL2, and of the
192
- * Security Extensions is ARM_FEATURE_EL3.
106
- */
193
- */
107
- set_feature(&cpu->env, ARM_FEATURE_V8);
194
- assert(!tcg_enabled() || no_aa32 ||
108
- {
195
- cpu_isar_feature(aa32_arm_div, cpu));
109
- uint32_t t;
196
- set_feature(env, ARM_FEATURE_LPAE);
110
+ /*
197
- set_feature(env, ARM_FEATURE_V7);
111
+ * We don't set these in system emulation mode for the moment,
198
- }
112
+ * since we don't correctly set (all of) the ID registers to
199
- if (arm_feature(env, ARM_FEATURE_V7)) {
113
+ * advertise them.
200
- set_feature(env, ARM_FEATURE_VAPA);
114
+ */
201
- set_feature(env, ARM_FEATURE_THUMB2);
115
+ set_feature(&cpu->env, ARM_FEATURE_V8);
202
- set_feature(env, ARM_FEATURE_MPIDR);
116
+ {
203
- if (!arm_feature(env, ARM_FEATURE_M)) {
117
+ uint32_t t;
204
- set_feature(env, ARM_FEATURE_V6K);
118
205
- } else {
119
- t = cpu->isar.id_isar5;
206
- set_feature(env, ARM_FEATURE_V6);
120
- t = FIELD_DP32(t, ID_ISAR5, AES, 2);
121
- t = FIELD_DP32(t, ID_ISAR5, SHA1, 1);
122
- t = FIELD_DP32(t, ID_ISAR5, SHA2, 1);
123
- t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
124
- t = FIELD_DP32(t, ID_ISAR5, RDM, 1);
125
- t = FIELD_DP32(t, ID_ISAR5, VCMA, 1);
126
- cpu->isar.id_isar5 = t;
127
+ t = cpu->isar.id_isar5;
128
+ t = FIELD_DP32(t, ID_ISAR5, AES, 2);
129
+ t = FIELD_DP32(t, ID_ISAR5, SHA1, 1);
130
+ t = FIELD_DP32(t, ID_ISAR5, SHA2, 1);
131
+ t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
132
+ t = FIELD_DP32(t, ID_ISAR5, RDM, 1);
133
+ t = FIELD_DP32(t, ID_ISAR5, VCMA, 1);
134
+ cpu->isar.id_isar5 = t;
135
136
- t = cpu->isar.id_isar6;
137
- t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
138
- t = FIELD_DP32(t, ID_ISAR6, DP, 1);
139
- t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
140
- t = FIELD_DP32(t, ID_ISAR6, SB, 1);
141
- t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
142
- cpu->isar.id_isar6 = t;
143
+ t = cpu->isar.id_isar6;
144
+ t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
145
+ t = FIELD_DP32(t, ID_ISAR6, DP, 1);
146
+ t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
147
+ t = FIELD_DP32(t, ID_ISAR6, SB, 1);
148
+ t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
149
+ cpu->isar.id_isar6 = t;
150
151
- t = cpu->isar.mvfr1;
152
- t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */
153
- t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
154
- cpu->isar.mvfr1 = t;
155
+ t = cpu->isar.mvfr1;
156
+ t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */
157
+ t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */
158
+ cpu->isar.mvfr1 = t;
159
160
- t = cpu->isar.mvfr2;
161
- t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
162
- t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
163
- cpu->isar.mvfr2 = t;
164
+ t = cpu->isar.mvfr2;
165
+ t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
166
+ t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
167
+ cpu->isar.mvfr2 = t;
168
169
- t = cpu->isar.id_mmfr3;
170
- t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
171
- cpu->isar.id_mmfr3 = t;
172
+ t = cpu->isar.id_mmfr3;
173
+ t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
174
+ cpu->isar.id_mmfr3 = t;
175
176
- t = cpu->isar.id_mmfr4;
177
- t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
178
- t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
179
- t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
180
- t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
181
- cpu->isar.id_mmfr4 = t;
182
- }
207
- }
183
-#endif
208
-
184
+ t = cpu->isar.id_mmfr4;
209
- /* Always define VBAR for V7 CPUs even if it doesn't exist in
185
+ t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
210
- * non-EL3 configs. This is needed by some legacy boards.
186
+ t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
211
- */
187
+ t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
212
- set_feature(env, ARM_FEATURE_VBAR);
188
+ t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
213
- }
189
+ cpu->isar.id_mmfr4 = t;
214
- if (arm_feature(env, ARM_FEATURE_V6K)) {
190
}
215
- set_feature(env, ARM_FEATURE_V6);
191
+#endif
216
- set_feature(env, ARM_FEATURE_MVFR);
192
}
217
- }
193
#endif
218
- if (arm_feature(env, ARM_FEATURE_V6)) {
194
219
- set_feature(env, ARM_FEATURE_V5);
195
@@ -XXX,XX +XXX,XX @@ static void arm_host_initfn(Object *obj)
220
- if (!arm_feature(env, ARM_FEATURE_M)) {
196
221
- assert(!tcg_enabled() || no_aa32 ||
197
static const TypeInfo host_arm_cpu_type_info = {
222
- cpu_isar_feature(aa32_jazelle, cpu));
198
.name = TYPE_ARM_HOST_CPU,
223
- set_feature(env, ARM_FEATURE_AUXCR);
199
-#ifdef TARGET_AARCH64
224
- }
200
.parent = TYPE_AARCH64_CPU,
225
- }
201
-#else
226
- if (arm_feature(env, ARM_FEATURE_V5)) {
202
- .parent = TYPE_ARM_CPU,
227
- set_feature(env, ARM_FEATURE_V4T);
203
-#endif
228
- }
204
.instance_init = arm_host_initfn,
229
- if (arm_feature(env, ARM_FEATURE_LPAE)) {
205
};
230
- set_feature(env, ARM_FEATURE_V7MP);
206
231
- }
207
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
232
- if (arm_feature(env, ARM_FEATURE_CBAR_RO)) {
208
index XXXXXXX..XXXXXXX 100644
233
- set_feature(env, ARM_FEATURE_CBAR);
209
--- a/target/arm/kvm.c
234
- }
210
+++ b/target/arm/kvm.c
235
- if (arm_feature(env, ARM_FEATURE_THUMB2) &&
211
@@ -XXX,XX +XXX,XX @@ int kvm_arch_process_async_events(CPUState *cs)
236
- !arm_feature(env, ARM_FEATURE_M)) {
212
return 0;
237
- set_feature(env, ARM_FEATURE_THUMB_DSP);
213
}
238
- }
214
239
215
-/* The #ifdef protections are until 32bit headers are imported and can
240
/*
216
- * be removed once both 32 and 64 bit reach feature parity.
241
* We rely on no XScale CPU having VFP so we can use the same bits in the
217
- */
218
void kvm_arch_update_guest_debug(CPUState *cs, struct kvm_guest_debug *dbg)
219
{
220
-#ifdef KVM_GUESTDBG_USE_SW_BP
221
if (kvm_sw_breakpoints_active(cs)) {
222
dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP;
223
}
224
-#endif
225
-#ifdef KVM_GUESTDBG_USE_HW
226
if (kvm_arm_hw_debug_active(cs)) {
227
dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW;
228
kvm_arm_copy_hw_debug_data(&dbg->arch);
229
}
230
-#endif
231
}
232
233
void kvm_arch_init_irq_routing(KVMState *s)
234
--
242
--
235
2.20.1
243
2.34.1
236
237
diff view generated by jsdifflib
1
From: Havard Skinnemoen <hskinnemoen@google.com>
1
M-profile CPUs generally allow configuration of the number of MPU
2
regions that they have. We don't currently model this, so our
3
implementations of some of the board models provide CPUs with the
4
wrong number of regions. RTOSes like Zephyr that hardcode the
5
expected number of regions may therefore not run on the model if they
6
are set up to run on real hardware.
2
7
3
The Nuvoton NPCM7xx SoC family are used to implement Baseboard
8
Add properties mpu-ns-regions and mpu-s-regions to the ARMV7M object,
4
Management Controllers in servers. While the family includes four SoCs,
9
matching the ability of hardware to configure the number of Secure
5
this patch implements limited support for two of them: NPCM730 (targeted
10
and NonSecure regions separately. Our actual CPU implementation
6
for Data Center applications) and NPCM750 (targeted for Enterprise
11
doesn't currently support that, and it happens that none of the MPS
7
applications).
12
boards we model set the number of regions differently for Secure vs
13
NonSecure, so we provide an interface to the boards and SoCs that
14
won't need to change if we ever do add that functionality in future,
15
but make it an error to configure the two properties to different
16
values.
8
17
9
This patch includes little more than the bare minimum needed to boot a
18
(The property name on the CPU is the somewhat misnamed-for-M-profile
10
Linux kernel built with NPCM7xx support in direct-kernel mode:
19
"pmsav7-dregion", so we don't follow that naming convention for
20
the properties here. The TRM doesn't say what the CPU configuration
21
variable names are, so we pick something, and follow the lowercase
22
convention we already have for properties here.)
11
23
12
- Two Cortex-A9 CPU cores with built-in periperhals.
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
- Global Configuration Registers.
25
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
14
- Clock Management.
26
Message-id: 20230724174335.2150499-3-peter.maydell@linaro.org
15
- 3 Timer Modules with 5 timers each.
27
---
16
- 4 serial ports.
28
include/hw/arm/armv7m.h | 8 ++++++++
29
hw/arm/armv7m.c | 21 +++++++++++++++++++++
30
2 files changed, 29 insertions(+)
17
31
18
The chips themselves have a lot more features, some of which will be
32
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
19
added to the model at a later stage.
33
index XXXXXXX..XXXXXXX 100644
20
34
--- a/include/hw/arm/armv7m.h
21
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
35
+++ b/include/hw/arm/armv7m.h
22
Reviewed-by: Joel Stanley <joel@jms.id.au>
36
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(ARMv7MState, ARMV7M)
23
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
37
* + Property "vfp": enable VFP (forwarded to CPU object)
24
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
38
* + Property "dsp": enable DSP (forwarded to CPU object)
25
Tested-by: Alexander Bulekov <alxndr@bu.edu>
39
* + Property "enable-bitband": expose bitbanded IO
26
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
40
+ * + Property "mpu-ns-regions": number of Non-Secure MPU regions (forwarded
27
Message-id: 20200911052101.2602693-5-hskinnemoen@google.com
41
+ * to CPU object pmsav7-dregion property; default is whatever the default
28
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
42
+ * for the CPU is)
29
---
43
+ * + Property "mpu-s-regions": number of Secure MPU regions (default is
30
include/hw/arm/npcm7xx.h | 85 ++++++++
44
+ * whatever the default for the CPU is; must currently be set to the same
31
hw/arm/npcm7xx.c | 407 +++++++++++++++++++++++++++++++++++++++
45
+ * value as mpu-ns-regions if the CPU implements the Security Extension)
32
hw/arm/Kconfig | 5 +
46
* + Clock input "refclk" is the external reference clock for the systick timers
33
hw/arm/meson.build | 1 +
47
* + Clock input "cpuclk" is the main CPU clock
34
4 files changed, 498 insertions(+)
48
*/
35
create mode 100644 include/hw/arm/npcm7xx.h
49
@@ -XXX,XX +XXX,XX @@ struct ARMv7MState {
36
create mode 100644 hw/arm/npcm7xx.c
50
Object *idau;
37
51
uint32_t init_svtor;
38
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
52
uint32_t init_nsvtor;
39
new file mode 100644
53
+ uint32_t mpu_ns_regions;
40
index XXXXXXX..XXXXXXX
54
+ uint32_t mpu_s_regions;
41
--- /dev/null
55
bool enable_bitband;
42
+++ b/include/hw/arm/npcm7xx.h
56
bool start_powered_off;
43
@@ -XXX,XX +XXX,XX @@
57
bool vfp;
44
+/*
58
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
45
+ * Nuvoton NPCM7xx SoC family.
59
index XXXXXXX..XXXXXXX 100644
46
+ *
60
--- a/hw/arm/armv7m.c
47
+ * Copyright 2020 Google LLC
61
+++ b/hw/arm/armv7m.c
48
+ *
62
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
49
+ * This program is free software; you can redistribute it and/or modify it
63
}
50
+ * under the terms of the GNU General Public License as published by the
64
}
51
+ * Free Software Foundation; either version 2 of the License, or
65
52
+ * (at your option) any later version.
53
+ *
54
+ * This program is distributed in the hope that it will be useful, but WITHOUT
55
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
56
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
57
+ * for more details.
58
+ */
59
+#ifndef NPCM7XX_H
60
+#define NPCM7XX_H
61
+
62
+#include "hw/boards.h"
63
+#include "hw/cpu/a9mpcore.h"
64
+#include "hw/misc/npcm7xx_clk.h"
65
+#include "hw/misc/npcm7xx_gcr.h"
66
+#include "hw/timer/npcm7xx_timer.h"
67
+#include "target/arm/cpu.h"
68
+
69
+#define NPCM7XX_MAX_NUM_CPUS (2)
70
+
71
+/* The first half of the address space is reserved for DDR4 DRAM. */
72
+#define NPCM7XX_DRAM_BA (0x00000000)
73
+#define NPCM7XX_DRAM_SZ (2 * GiB)
74
+
75
+/* Magic addresses for setting up direct kernel booting and SMP boot stubs. */
76
+#define NPCM7XX_LOADER_START (0x00000000) /* Start of SDRAM */
77
+#define NPCM7XX_SMP_LOADER_START (0xffff0000) /* Boot ROM */
78
+#define NPCM7XX_SMP_BOOTREG_ADDR (0xf080013c) /* GCR.SCRPAD */
79
+#define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100) /* GIC within A9 */
80
+
81
+typedef struct NPCM7xxState {
82
+ DeviceState parent;
83
+
84
+ ARMCPU cpu[NPCM7XX_MAX_NUM_CPUS];
85
+ A9MPPrivState a9mpcore;
86
+
87
+ MemoryRegion sram;
88
+ MemoryRegion irom;
89
+ MemoryRegion ram3;
90
+ MemoryRegion *dram;
91
+
92
+ NPCM7xxGCRState gcr;
93
+ NPCM7xxCLKState clk;
94
+ NPCM7xxTimerCtrlState tim[3];
95
+} NPCM7xxState;
96
+
97
+#define TYPE_NPCM7XX "npcm7xx"
98
+#define NPCM7XX(obj) OBJECT_CHECK(NPCM7xxState, (obj), TYPE_NPCM7XX)
99
+
100
+#define TYPE_NPCM730 "npcm730"
101
+#define TYPE_NPCM750 "npcm750"
102
+
103
+typedef struct NPCM7xxClass {
104
+ DeviceClass parent;
105
+
106
+ /* Bitmask of modules that are permanently disabled on this chip. */
107
+ uint32_t disabled_modules;
108
+ /* Number of CPU cores enabled in this SoC class (may be 1 or 2). */
109
+ uint32_t num_cpus;
110
+} NPCM7xxClass;
111
+
112
+#define NPCM7XX_CLASS(klass) \
113
+ OBJECT_CLASS_CHECK(NPCM7xxClass, (klass), TYPE_NPCM7XX)
114
+#define NPCM7XX_GET_CLASS(obj) \
115
+ OBJECT_GET_CLASS(NPCM7xxClass, (obj), TYPE_NPCM7XX)
116
+
117
+/**
118
+ * npcm7xx_load_kernel - Loads memory with everything needed to boot
119
+ * @machine - The machine containing the SoC to be booted.
120
+ * @soc - The SoC containing the CPU to be booted.
121
+ *
122
+ * This will set up the ARM boot info structure for the specific NPCM7xx
123
+ * derivative and call arm_load_kernel() to set up loading of the kernel, etc.
124
+ * into memory, if requested by the user.
125
+ */
126
+void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc);
127
+
128
+#endif /* NPCM7XX_H */
129
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
130
new file mode 100644
131
index XXXXXXX..XXXXXXX
132
--- /dev/null
133
+++ b/hw/arm/npcm7xx.c
134
@@ -XXX,XX +XXX,XX @@
135
+/*
136
+ * Nuvoton NPCM7xx SoC family.
137
+ *
138
+ * Copyright 2020 Google LLC
139
+ *
140
+ * This program is free software; you can redistribute it and/or modify it
141
+ * under the terms of the GNU General Public License as published by the
142
+ * Free Software Foundation; either version 2 of the License, or
143
+ * (at your option) any later version.
144
+ *
145
+ * This program is distributed in the hope that it will be useful, but WITHOUT
146
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
147
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
148
+ * for more details.
149
+ */
150
+
151
+#include "qemu/osdep.h"
152
+
153
+#include "exec/address-spaces.h"
154
+#include "hw/arm/boot.h"
155
+#include "hw/arm/npcm7xx.h"
156
+#include "hw/char/serial.h"
157
+#include "hw/loader.h"
158
+#include "hw/misc/unimp.h"
159
+#include "hw/qdev-properties.h"
160
+#include "qapi/error.h"
161
+#include "qemu/units.h"
162
+#include "sysemu/sysemu.h"
163
+
164
+/*
165
+ * This covers the whole MMIO space. We'll use this to catch any MMIO accesses
166
+ * that aren't handled by any device.
167
+ */
168
+#define NPCM7XX_MMIO_BA (0x80000000)
169
+#define NPCM7XX_MMIO_SZ (0x7ffd0000)
170
+
171
+/* Core system modules. */
172
+#define NPCM7XX_L2C_BA (0xf03fc000)
173
+#define NPCM7XX_CPUP_BA (0xf03fe000)
174
+#define NPCM7XX_GCR_BA (0xf0800000)
175
+#define NPCM7XX_CLK_BA (0xf0801000)
176
+
177
+/* Internal AHB SRAM */
178
+#define NPCM7XX_RAM3_BA (0xc0008000)
179
+#define NPCM7XX_RAM3_SZ (4 * KiB)
180
+
181
+/* Memory blocks at the end of the address space */
182
+#define NPCM7XX_RAM2_BA (0xfffd0000)
183
+#define NPCM7XX_RAM2_SZ (128 * KiB)
184
+#define NPCM7XX_ROM_BA (0xffff0000)
185
+#define NPCM7XX_ROM_SZ (64 * KiB)
186
+
187
+/*
188
+ * Interrupt lines going into the GIC. This does not include internal Cortex-A9
189
+ * interrupts.
190
+ */
191
+enum NPCM7xxInterrupt {
192
+ NPCM7XX_UART0_IRQ = 2,
193
+ NPCM7XX_UART1_IRQ,
194
+ NPCM7XX_UART2_IRQ,
195
+ NPCM7XX_UART3_IRQ,
196
+ NPCM7XX_TIMER0_IRQ = 32, /* Timer Module 0 */
197
+ NPCM7XX_TIMER1_IRQ,
198
+ NPCM7XX_TIMER2_IRQ,
199
+ NPCM7XX_TIMER3_IRQ,
200
+ NPCM7XX_TIMER4_IRQ,
201
+ NPCM7XX_TIMER5_IRQ, /* Timer Module 1 */
202
+ NPCM7XX_TIMER6_IRQ,
203
+ NPCM7XX_TIMER7_IRQ,
204
+ NPCM7XX_TIMER8_IRQ,
205
+ NPCM7XX_TIMER9_IRQ,
206
+ NPCM7XX_TIMER10_IRQ, /* Timer Module 2 */
207
+ NPCM7XX_TIMER11_IRQ,
208
+ NPCM7XX_TIMER12_IRQ,
209
+ NPCM7XX_TIMER13_IRQ,
210
+ NPCM7XX_TIMER14_IRQ,
211
+};
212
+
213
+/* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */
214
+#define NPCM7XX_NUM_IRQ (160)
215
+
216
+/* Register base address for each Timer Module */
217
+static const hwaddr npcm7xx_tim_addr[] = {
218
+ 0xf0008000,
219
+ 0xf0009000,
220
+ 0xf000a000,
221
+};
222
+
223
+/* Register base address for each 16550 UART */
224
+static const hwaddr npcm7xx_uart_addr[] = {
225
+ 0xf0001000,
226
+ 0xf0002000,
227
+ 0xf0003000,
228
+ 0xf0004000,
229
+};
230
+
231
+static void npcm7xx_write_secondary_boot(ARMCPU *cpu,
232
+ const struct arm_boot_info *info)
233
+{
234
+ /*
66
+ /*
235
+ * The default smpboot stub halts the secondary CPU with a 'wfi'
67
+ * Real M-profile hardware can be configured with a different number of
236
+ * instruction, but the arch/arm/mach-npcm/platsmp.c in the Linux kernel
68
+ * MPU regions for Secure vs NonSecure. QEMU's CPU implementation doesn't
237
+ * does not send an IPI to wake it up, so the second CPU fails to boot. So
69
+ * support that yet, so catch attempts to select that.
238
+ * we need to provide our own smpboot stub that can not use 'wfi', it has
239
+ * to spin the secondary CPU until the first CPU writes to the SCRPAD reg.
240
+ */
70
+ */
241
+ uint32_t smpboot[] = {
71
+ if (arm_feature(&s->cpu->env, ARM_FEATURE_M_SECURITY) &&
242
+ 0xe59f2018, /* ldr r2, bootreg_addr */
72
+ s->mpu_ns_regions != s->mpu_s_regions) {
243
+ 0xe3a00000, /* mov r0, #0 */
73
+ error_setg(errp,
244
+ 0xe5820000, /* str r0, [r2] */
74
+ "mpu-ns-regions and mpu-s-regions properties must have the same value");
245
+ 0xe320f002, /* wfe */
246
+ 0xe5921000, /* ldr r1, [r2] */
247
+ 0xe1110001, /* tst r1, r1 */
248
+ 0x0afffffb, /* beq <wfe> */
249
+ 0xe12fff11, /* bx r1 */
250
+ NPCM7XX_SMP_BOOTREG_ADDR,
251
+ };
252
+ int i;
253
+
254
+ for (i = 0; i < ARRAY_SIZE(smpboot); i++) {
255
+ smpboot[i] = tswap32(smpboot[i]);
256
+ }
257
+
258
+ rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
259
+ NPCM7XX_SMP_LOADER_START);
260
+}
261
+
262
+static struct arm_boot_info npcm7xx_binfo = {
263
+ .loader_start = NPCM7XX_LOADER_START,
264
+ .smp_loader_start = NPCM7XX_SMP_LOADER_START,
265
+ .smp_bootreg_addr = NPCM7XX_SMP_BOOTREG_ADDR,
266
+ .gic_cpu_if_addr = NPCM7XX_GIC_CPU_IF_ADDR,
267
+ .write_secondary_boot = npcm7xx_write_secondary_boot,
268
+ .board_id = -1,
269
+};
270
+
271
+void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
272
+{
273
+ NPCM7xxClass *sc = NPCM7XX_GET_CLASS(soc);
274
+
275
+ npcm7xx_binfo.ram_size = machine->ram_size;
276
+ npcm7xx_binfo.nb_cpus = sc->num_cpus;
277
+
278
+ arm_load_kernel(&soc->cpu[0], machine, &npcm7xx_binfo);
279
+}
280
+
281
+static qemu_irq npcm7xx_irq(NPCM7xxState *s, int n)
282
+{
283
+ return qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
284
+}
285
+
286
+static void npcm7xx_init(Object *obj)
287
+{
288
+ NPCM7xxState *s = NPCM7XX(obj);
289
+ int i;
290
+
291
+ for (i = 0; i < NPCM7XX_MAX_NUM_CPUS; i++) {
292
+ object_initialize_child(obj, "cpu[*]", &s->cpu[i],
293
+ ARM_CPU_TYPE_NAME("cortex-a9"));
294
+ }
295
+
296
+ object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
297
+ object_initialize_child(obj, "gcr", &s->gcr, TYPE_NPCM7XX_GCR);
298
+ object_property_add_alias(obj, "power-on-straps", OBJECT(&s->gcr),
299
+ "power-on-straps");
300
+ object_initialize_child(obj, "clk", &s->clk, TYPE_NPCM7XX_CLK);
301
+
302
+ for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
303
+ object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
304
+ }
305
+}
306
+
307
+static void npcm7xx_realize(DeviceState *dev, Error **errp)
308
+{
309
+ NPCM7xxState *s = NPCM7XX(dev);
310
+ NPCM7xxClass *nc = NPCM7XX_GET_CLASS(s);
311
+ int i;
312
+
313
+ if (memory_region_size(s->dram) > NPCM7XX_DRAM_SZ) {
314
+ error_setg(errp, "%s: NPCM7xx cannot address more than %" PRIu64
315
+ " MiB of DRAM", __func__, NPCM7XX_DRAM_SZ / MiB);
316
+ return;
75
+ return;
317
+ }
76
+ }
318
+
77
+ if (s->mpu_ns_regions != UINT_MAX &&
319
+ /* CPUs */
78
+ object_property_find(OBJECT(s->cpu), "pmsav7-dregion")) {
320
+ for (i = 0; i < nc->num_cpus; i++) {
79
+ if (!object_property_set_uint(OBJECT(s->cpu), "pmsav7-dregion",
321
+ object_property_set_int(OBJECT(&s->cpu[i]), "mp-affinity",
80
+ s->mpu_ns_regions, errp)) {
322
+ arm_cpu_mp_affinity(i, NPCM7XX_MAX_NUM_CPUS),
323
+ &error_abort);
324
+ object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar",
325
+ NPCM7XX_GIC_CPU_IF_ADDR, &error_abort);
326
+ object_property_set_bool(OBJECT(&s->cpu[i]), "reset-hivecs", true,
327
+ &error_abort);
328
+
329
+ /* Disable security extensions. */
330
+ object_property_set_bool(OBJECT(&s->cpu[i]), "has_el3", false,
331
+ &error_abort);
332
+
333
+ if (!qdev_realize(DEVICE(&s->cpu[i]), NULL, errp)) {
334
+ return;
81
+ return;
335
+ }
82
+ }
336
+ }
83
+ }
337
+
84
+
338
+ /* A9MPCORE peripherals. Can only fail if we pass bad parameters here. */
85
/*
339
+ object_property_set_int(OBJECT(&s->a9mpcore), "num-cpu", nc->num_cpus,
86
* Tell the CPU where the NVIC is; it will fail realize if it doesn't
340
+ &error_abort);
87
* have one. Similarly, tell the NVIC where its CPU is.
341
+ object_property_set_int(OBJECT(&s->a9mpcore), "num-irq", NPCM7XX_NUM_IRQ,
88
@@ -XXX,XX +XXX,XX @@ static Property armv7m_properties[] = {
342
+ &error_abort);
89
false),
343
+ sysbus_realize(SYS_BUS_DEVICE(&s->a9mpcore), &error_abort);
90
DEFINE_PROP_BOOL("vfp", ARMv7MState, vfp, true),
344
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->a9mpcore), 0, NPCM7XX_CPUP_BA);
91
DEFINE_PROP_BOOL("dsp", ARMv7MState, dsp, true),
345
+
92
+ DEFINE_PROP_UINT32("mpu-ns-regions", ARMv7MState, mpu_ns_regions, UINT_MAX),
346
+ for (i = 0; i < nc->num_cpus; i++) {
93
+ DEFINE_PROP_UINT32("mpu-s-regions", ARMv7MState, mpu_s_regions, UINT_MAX),
347
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->a9mpcore), i,
94
DEFINE_PROP_END_OF_LIST(),
348
+ qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_IRQ));
95
};
349
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->a9mpcore), i + nc->num_cpus,
96
350
+ qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_FIQ));
351
+ }
352
+
353
+ /* L2 cache controller */
354
+ sysbus_create_simple("l2x0", NPCM7XX_L2C_BA, NULL);
355
+
356
+ /* System Global Control Registers (GCR). Can fail due to user input. */
357
+ object_property_set_int(OBJECT(&s->gcr), "disabled-modules",
358
+ nc->disabled_modules, &error_abort);
359
+ object_property_add_const_link(OBJECT(&s->gcr), "dram-mr", OBJECT(s->dram));
360
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->gcr), errp)) {
361
+ return;
362
+ }
363
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gcr), 0, NPCM7XX_GCR_BA);
364
+
365
+ /* Clock Control Registers (CLK). Cannot fail. */
366
+ sysbus_realize(SYS_BUS_DEVICE(&s->clk), &error_abort);
367
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->clk), 0, NPCM7XX_CLK_BA);
368
+
369
+ /* Timer Modules (TIM). Cannot fail. */
370
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
371
+ for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
372
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->tim[i]);
373
+ int first_irq;
374
+ int j;
375
+
376
+ sysbus_realize(sbd, &error_abort);
377
+ sysbus_mmio_map(sbd, 0, npcm7xx_tim_addr[i]);
378
+
379
+ first_irq = NPCM7XX_TIMER0_IRQ + i * NPCM7XX_TIMERS_PER_CTRL;
380
+ for (j = 0; j < NPCM7XX_TIMERS_PER_CTRL; j++) {
381
+ qemu_irq irq = npcm7xx_irq(s, first_irq + j);
382
+ sysbus_connect_irq(sbd, j, irq);
383
+ }
384
+ }
385
+
386
+ /* UART0..3 (16550 compatible) */
387
+ for (i = 0; i < ARRAY_SIZE(npcm7xx_uart_addr); i++) {
388
+ serial_mm_init(get_system_memory(), npcm7xx_uart_addr[i], 2,
389
+ npcm7xx_irq(s, NPCM7XX_UART0_IRQ + i), 115200,
390
+ serial_hd(i), DEVICE_LITTLE_ENDIAN);
391
+ }
392
+
393
+ /* RAM2 (SRAM) */
394
+ memory_region_init_ram(&s->sram, OBJECT(dev), "ram2",
395
+ NPCM7XX_RAM2_SZ, &error_abort);
396
+ memory_region_add_subregion(get_system_memory(), NPCM7XX_RAM2_BA, &s->sram);
397
+
398
+ /* RAM3 (SRAM) */
399
+ memory_region_init_ram(&s->ram3, OBJECT(dev), "ram3",
400
+ NPCM7XX_RAM3_SZ, &error_abort);
401
+ memory_region_add_subregion(get_system_memory(), NPCM7XX_RAM3_BA, &s->ram3);
402
+
403
+ /* Internal ROM */
404
+ memory_region_init_rom(&s->irom, OBJECT(dev), "irom", NPCM7XX_ROM_SZ,
405
+ &error_abort);
406
+ memory_region_add_subregion(get_system_memory(), NPCM7XX_ROM_BA, &s->irom);
407
+
408
+ create_unimplemented_device("npcm7xx.shm", 0xc0001000, 4 * KiB);
409
+ create_unimplemented_device("npcm7xx.vdmx", 0xe0800000, 4 * KiB);
410
+ create_unimplemented_device("npcm7xx.pcierc", 0xe1000000, 64 * KiB);
411
+ create_unimplemented_device("npcm7xx.kcs", 0xf0007000, 4 * KiB);
412
+ create_unimplemented_device("npcm7xx.rng", 0xf000b000, 4 * KiB);
413
+ create_unimplemented_device("npcm7xx.adc", 0xf000c000, 4 * KiB);
414
+ create_unimplemented_device("npcm7xx.gfxi", 0xf000e000, 4 * KiB);
415
+ create_unimplemented_device("npcm7xx.gpio[0]", 0xf0010000, 4 * KiB);
416
+ create_unimplemented_device("npcm7xx.gpio[1]", 0xf0011000, 4 * KiB);
417
+ create_unimplemented_device("npcm7xx.gpio[2]", 0xf0012000, 4 * KiB);
418
+ create_unimplemented_device("npcm7xx.gpio[3]", 0xf0013000, 4 * KiB);
419
+ create_unimplemented_device("npcm7xx.gpio[4]", 0xf0014000, 4 * KiB);
420
+ create_unimplemented_device("npcm7xx.gpio[5]", 0xf0015000, 4 * KiB);
421
+ create_unimplemented_device("npcm7xx.gpio[6]", 0xf0016000, 4 * KiB);
422
+ create_unimplemented_device("npcm7xx.gpio[7]", 0xf0017000, 4 * KiB);
423
+ create_unimplemented_device("npcm7xx.smbus[0]", 0xf0080000, 4 * KiB);
424
+ create_unimplemented_device("npcm7xx.smbus[1]", 0xf0081000, 4 * KiB);
425
+ create_unimplemented_device("npcm7xx.smbus[2]", 0xf0082000, 4 * KiB);
426
+ create_unimplemented_device("npcm7xx.smbus[3]", 0xf0083000, 4 * KiB);
427
+ create_unimplemented_device("npcm7xx.smbus[4]", 0xf0084000, 4 * KiB);
428
+ create_unimplemented_device("npcm7xx.smbus[5]", 0xf0085000, 4 * KiB);
429
+ create_unimplemented_device("npcm7xx.smbus[6]", 0xf0086000, 4 * KiB);
430
+ create_unimplemented_device("npcm7xx.smbus[7]", 0xf0087000, 4 * KiB);
431
+ create_unimplemented_device("npcm7xx.smbus[8]", 0xf0088000, 4 * KiB);
432
+ create_unimplemented_device("npcm7xx.smbus[9]", 0xf0089000, 4 * KiB);
433
+ create_unimplemented_device("npcm7xx.smbus[10]", 0xf008a000, 4 * KiB);
434
+ create_unimplemented_device("npcm7xx.smbus[11]", 0xf008b000, 4 * KiB);
435
+ create_unimplemented_device("npcm7xx.smbus[12]", 0xf008c000, 4 * KiB);
436
+ create_unimplemented_device("npcm7xx.smbus[13]", 0xf008d000, 4 * KiB);
437
+ create_unimplemented_device("npcm7xx.smbus[14]", 0xf008e000, 4 * KiB);
438
+ create_unimplemented_device("npcm7xx.smbus[15]", 0xf008f000, 4 * KiB);
439
+ create_unimplemented_device("npcm7xx.espi", 0xf009f000, 4 * KiB);
440
+ create_unimplemented_device("npcm7xx.peci", 0xf0100000, 4 * KiB);
441
+ create_unimplemented_device("npcm7xx.siox[1]", 0xf0101000, 4 * KiB);
442
+ create_unimplemented_device("npcm7xx.siox[2]", 0xf0102000, 4 * KiB);
443
+ create_unimplemented_device("npcm7xx.pwm[0]", 0xf0103000, 4 * KiB);
444
+ create_unimplemented_device("npcm7xx.pwm[1]", 0xf0104000, 4 * KiB);
445
+ create_unimplemented_device("npcm7xx.mft[0]", 0xf0180000, 4 * KiB);
446
+ create_unimplemented_device("npcm7xx.mft[1]", 0xf0181000, 4 * KiB);
447
+ create_unimplemented_device("npcm7xx.mft[2]", 0xf0182000, 4 * KiB);
448
+ create_unimplemented_device("npcm7xx.mft[3]", 0xf0183000, 4 * KiB);
449
+ create_unimplemented_device("npcm7xx.mft[4]", 0xf0184000, 4 * KiB);
450
+ create_unimplemented_device("npcm7xx.mft[5]", 0xf0185000, 4 * KiB);
451
+ create_unimplemented_device("npcm7xx.mft[6]", 0xf0186000, 4 * KiB);
452
+ create_unimplemented_device("npcm7xx.mft[7]", 0xf0187000, 4 * KiB);
453
+ create_unimplemented_device("npcm7xx.pspi1", 0xf0200000, 4 * KiB);
454
+ create_unimplemented_device("npcm7xx.pspi2", 0xf0201000, 4 * KiB);
455
+ create_unimplemented_device("npcm7xx.ahbpci", 0xf0400000, 1 * MiB);
456
+ create_unimplemented_device("npcm7xx.mcphy", 0xf05f0000, 64 * KiB);
457
+ create_unimplemented_device("npcm7xx.gmac1", 0xf0802000, 8 * KiB);
458
+ create_unimplemented_device("npcm7xx.gmac2", 0xf0804000, 8 * KiB);
459
+ create_unimplemented_device("npcm7xx.ehci", 0xf0806000, 4 * KiB);
460
+ create_unimplemented_device("npcm7xx.ohci", 0xf0807000, 4 * KiB);
461
+ create_unimplemented_device("npcm7xx.vcd", 0xf0810000, 64 * KiB);
462
+ create_unimplemented_device("npcm7xx.ece", 0xf0820000, 8 * KiB);
463
+ create_unimplemented_device("npcm7xx.vdma", 0xf0822000, 8 * KiB);
464
+ create_unimplemented_device("npcm7xx.emc1", 0xf0825000, 4 * KiB);
465
+ create_unimplemented_device("npcm7xx.emc2", 0xf0826000, 4 * KiB);
466
+ create_unimplemented_device("npcm7xx.usbd[0]", 0xf0830000, 4 * KiB);
467
+ create_unimplemented_device("npcm7xx.usbd[1]", 0xf0831000, 4 * KiB);
468
+ create_unimplemented_device("npcm7xx.usbd[2]", 0xf0832000, 4 * KiB);
469
+ create_unimplemented_device("npcm7xx.usbd[3]", 0xf0833000, 4 * KiB);
470
+ create_unimplemented_device("npcm7xx.usbd[4]", 0xf0834000, 4 * KiB);
471
+ create_unimplemented_device("npcm7xx.usbd[5]", 0xf0835000, 4 * KiB);
472
+ create_unimplemented_device("npcm7xx.usbd[6]", 0xf0836000, 4 * KiB);
473
+ create_unimplemented_device("npcm7xx.usbd[7]", 0xf0837000, 4 * KiB);
474
+ create_unimplemented_device("npcm7xx.usbd[8]", 0xf0838000, 4 * KiB);
475
+ create_unimplemented_device("npcm7xx.usbd[9]", 0xf0839000, 4 * KiB);
476
+ create_unimplemented_device("npcm7xx.sd", 0xf0840000, 8 * KiB);
477
+ create_unimplemented_device("npcm7xx.mmc", 0xf0842000, 8 * KiB);
478
+ create_unimplemented_device("npcm7xx.pcimbx", 0xf0848000, 512 * KiB);
479
+ create_unimplemented_device("npcm7xx.aes", 0xf0858000, 4 * KiB);
480
+ create_unimplemented_device("npcm7xx.des", 0xf0859000, 4 * KiB);
481
+ create_unimplemented_device("npcm7xx.sha", 0xf085a000, 4 * KiB);
482
+ create_unimplemented_device("npcm7xx.secacc", 0xf085b000, 4 * KiB);
483
+ create_unimplemented_device("npcm7xx.spixcs0", 0xf8000000, 16 * MiB);
484
+ create_unimplemented_device("npcm7xx.spixcs1", 0xf9000000, 16 * MiB);
485
+ create_unimplemented_device("npcm7xx.spix", 0xfb001000, 4 * KiB);
486
+}
487
+
488
+static Property npcm7xx_properties[] = {
489
+ DEFINE_PROP_LINK("dram-mr", NPCM7xxState, dram, TYPE_MEMORY_REGION,
490
+ MemoryRegion *),
491
+ DEFINE_PROP_END_OF_LIST(),
492
+};
493
+
494
+static void npcm7xx_class_init(ObjectClass *oc, void *data)
495
+{
496
+ DeviceClass *dc = DEVICE_CLASS(oc);
497
+
498
+ dc->realize = npcm7xx_realize;
499
+ dc->user_creatable = false;
500
+ device_class_set_props(dc, npcm7xx_properties);
501
+}
502
+
503
+static void npcm730_class_init(ObjectClass *oc, void *data)
504
+{
505
+ NPCM7xxClass *nc = NPCM7XX_CLASS(oc);
506
+
507
+ /* NPCM730 is optimized for data center use, so no graphics, etc. */
508
+ nc->disabled_modules = 0x00300395;
509
+ nc->num_cpus = 2;
510
+}
511
+
512
+static void npcm750_class_init(ObjectClass *oc, void *data)
513
+{
514
+ NPCM7xxClass *nc = NPCM7XX_CLASS(oc);
515
+
516
+ /* NPCM750 has 2 cores and a full set of peripherals */
517
+ nc->disabled_modules = 0x00000000;
518
+ nc->num_cpus = 2;
519
+}
520
+
521
+static const TypeInfo npcm7xx_soc_types[] = {
522
+ {
523
+ .name = TYPE_NPCM7XX,
524
+ .parent = TYPE_DEVICE,
525
+ .instance_size = sizeof(NPCM7xxState),
526
+ .instance_init = npcm7xx_init,
527
+ .class_size = sizeof(NPCM7xxClass),
528
+ .class_init = npcm7xx_class_init,
529
+ .abstract = true,
530
+ }, {
531
+ .name = TYPE_NPCM730,
532
+ .parent = TYPE_NPCM7XX,
533
+ .class_init = npcm730_class_init,
534
+ }, {
535
+ .name = TYPE_NPCM750,
536
+ .parent = TYPE_NPCM7XX,
537
+ .class_init = npcm750_class_init,
538
+ },
539
+};
540
+
541
+DEFINE_TYPES(npcm7xx_soc_types);
542
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
543
index XXXXXXX..XXXXXXX 100644
544
--- a/hw/arm/Kconfig
545
+++ b/hw/arm/Kconfig
546
@@ -XXX,XX +XXX,XX @@ config XLNX_VERSAL
547
548
config NPCM7XX
549
bool
550
+ select A9MPCORE
551
+ select ARM_GIC
552
+ select PL310 # cache controller
553
+ select SERIAL
554
+ select UNIMP
555
556
config FSL_IMX25
557
bool
558
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
559
index XXXXXXX..XXXXXXX 100644
560
--- a/hw/arm/meson.build
561
+++ b/hw/arm/meson.build
562
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'CONFIG_MICROBIT', if_true: files('microbit.c'))
563
arm_ss.add(when: 'CONFIG_MUSICPAL', if_true: files('musicpal.c'))
564
arm_ss.add(when: 'CONFIG_NETDUINO2', if_true: files('netduino2.c'))
565
arm_ss.add(when: 'CONFIG_NETDUINOPLUS2', if_true: files('netduinoplus2.c'))
566
+arm_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx.c'))
567
arm_ss.add(when: 'CONFIG_NSERIES', if_true: files('nseries.c'))
568
arm_ss.add(when: 'CONFIG_SX1', if_true: files('omap_sx1.c'))
569
arm_ss.add(when: 'CONFIG_CHEETAH', if_true: files('palm.c'))
570
--
97
--
571
2.20.1
98
2.34.1
572
99
573
100
diff view generated by jsdifflib
1
Implement a model of the MPS2 with the AN386 firmware. This is
1
The IoTKit, SSE200 and SSE300 all default to 8 MPU regions. The
2
essentially identical to the AN385 firmware, but it has a
2
MPS2/MPS3 FPGA images don't override these except in the case of
3
Cortex-M4 rather than a Cortex-M3.
3
AN547, which uses 16 MPU regions.
4
4
5
Define properties on the ARMSSE object for the MPU regions (using the
6
same names as the documented RTL configuration settings, and
7
following the pattern we already have for this device of using
8
all-caps names as the RTL does), and set them in the board code.
9
10
We don't actually need to override the default except on AN547,
11
but it's simpler code to have the board code set them always
12
rather than tracking which board subtypes want to set them to
13
a non-default value separately from what that value is.
14
15
Tho overall effect is that for mps2-an505, mps2-an521 and mps3-an524
16
we now correctly use 8 MPU regions, while mps3-an547 stays at its
17
current 16 regions.
18
19
It's possible some guest code wrongly depended on the previous
20
incorrectly modeled number of memory regions. (Such guest code
21
should ideally check the number of regions via the MPU_TYPE
22
register.) The old behaviour can be obtained with additional
23
-global arguments to QEMU:
24
25
For mps2-an521 and mps2-an524:
26
-global sse-200.CPU0_MPU_NS=16 -global sse-200.CPU0_MPU_S=16 -global sse-200.CPU1_MPU_NS=16 -global sse-200.CPU1_MPU_S=16
27
28
For mps2-an505:
29
-global sse-200.CPU0_MPU_NS=16 -global sse-200.CPU0_MPU_S=16
30
31
NB that the way the implementation allows this use of -global
32
is slightly fragile: if the board code explicitly sets the
33
properties on the sse-200 object, this overrides the -global
34
command line option. So we rely on:
35
- the boards that need fixing all happen to use the SSE defaults
36
- we can write the board code to only set the property if it
37
is different from the default, rather than having all boards
38
explicitly set the property
39
- the board that does need to use a non-default value happens
40
to need to set it to the same value (16) we previously used
41
This works, but there are some kinds of refactoring of the
42
mps2-tz.c code that would break the support for -global here.
43
44
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1772
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
45
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
46
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
47
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20200903202048.15370-2-peter.maydell@linaro.org
48
Message-id: 20230724174335.2150499-4-peter.maydell@linaro.org
9
---
49
---
10
docs/system/arm/mps2.rst | 8 +++++---
50
include/hw/arm/armsse.h | 5 +++++
11
hw/arm/mps2.c | 34 +++++++++++++++++++++++++++++-----
51
hw/arm/armsse.c | 16 ++++++++++++++++
12
2 files changed, 34 insertions(+), 8 deletions(-)
52
hw/arm/mps2-tz.c | 29 +++++++++++++++++++++++++++++
13
53
3 files changed, 50 insertions(+)
14
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
54
55
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
15
index XXXXXXX..XXXXXXX 100644
56
index XXXXXXX..XXXXXXX 100644
16
--- a/docs/system/arm/mps2.rst
57
--- a/include/hw/arm/armsse.h
17
+++ b/docs/system/arm/mps2.rst
58
+++ b/include/hw/arm/armsse.h
18
@@ -XXX,XX +XXX,XX @@
59
@@ -XXX,XX +XXX,XX @@
19
-Arm MPS2 boards (``mps2-an385``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
60
* (matching the hardware) is that for CPU0 in an IoTKit and CPU1 in an
20
-================================================================================
61
* SSE-200 both are present; CPU0 in an SSE-200 has neither.
21
+Arm MPS2 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
62
* Since the IoTKit has only one CPU, it does not have the CPU1_* properties.
22
+================================================================================================
63
+ * + QOM properties "CPU0_MPU_NS", "CPU0_MPU_S", "CPU1_MPU_NS" and "CPU1_MPU_S"
23
64
+ * which set the number of MPU regions on the CPUs. If there is only one
24
These board models all use Arm M-profile CPUs.
65
+ * CPU the CPU1 properties are not present.
25
66
* + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts for CPU 0,
26
@@ -XXX,XX +XXX,XX @@ QEMU models the following FPGA images:
67
* which are wired to its NVIC lines 32 .. n+32
27
68
* + Named GPIO inputs "EXP_CPU1_IRQ" 0..n are the expansion interrupts for
28
``mps2-an385``
69
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
29
Cortex-M3 as documented in ARM Application Note AN385
70
uint32_t exp_numirq;
30
+``mps2-an386``
71
uint32_t sram_addr_width;
31
+ Cortex-M4 as documented in ARM Application Note AN386
72
uint32_t init_svtor;
32
``mps2-an511``
73
+ uint32_t cpu_mpu_ns[SSE_MAX_CPUS];
33
Cortex-M3 'DesignStart' as documented in AN511
74
+ uint32_t cpu_mpu_s[SSE_MAX_CPUS];
34
``mps2-an505``
75
bool cpu_fpu[SSE_MAX_CPUS];
35
@@ -XXX,XX +XXX,XX @@ QEMU models the following FPGA images:
76
bool cpu_dsp[SSE_MAX_CPUS];
36
77
};
37
Differences between QEMU and real hardware:
78
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
38
39
-- AN385 remapping of low 16K of memory to either ZBT SSRAM1 or to
40
+- AN385/AN386 remapping of low 16K of memory to either ZBT SSRAM1 or to
41
block RAM is unimplemented (QEMU always maps this to ZBT SSRAM1, as
42
if zbt_boot_ctrl is always zero)
43
- QEMU provides a LAN9118 ethernet rather than LAN9220; the only guest
44
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
45
index XXXXXXX..XXXXXXX 100644
79
index XXXXXXX..XXXXXXX 100644
46
--- a/hw/arm/mps2.c
80
--- a/hw/arm/armsse.c
47
+++ b/hw/arm/mps2.c
81
+++ b/hw/arm/armsse.c
48
@@ -XXX,XX +XXX,XX @@
82
@@ -XXX,XX +XXX,XX @@ static Property iotkit_properties[] = {
49
* as seen by the guest depend significantly on the FPGA image.
83
DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
50
* We model the following FPGA images:
84
DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], true),
51
* "mps2-an385" -- Cortex-M3 as documented in ARM Application Note AN385
85
DEFINE_PROP_BOOL("CPU0_DSP", ARMSSE, cpu_dsp[0], true),
52
+ * "mps2-an386" -- Cortex-M4 as documented in ARM Application Note AN386
86
+ DEFINE_PROP_UINT32("CPU0_MPU_NS", ARMSSE, cpu_mpu_ns[0], 8),
53
* "mps2-an511" -- Cortex-M3 'DesignStart' as documented in AN511
87
+ DEFINE_PROP_UINT32("CPU0_MPU_S", ARMSSE, cpu_mpu_s[0], 8),
54
*
88
DEFINE_PROP_END_OF_LIST()
55
* Links to the TRM for the board itself and to the various Application
89
};
56
@@ -XXX,XX +XXX,XX @@
90
57
91
@@ -XXX,XX +XXX,XX @@ static Property sse200_properties[] = {
58
typedef enum MPS2FPGAType {
92
DEFINE_PROP_BOOL("CPU0_DSP", ARMSSE, cpu_dsp[0], false),
59
FPGA_AN385,
93
DEFINE_PROP_BOOL("CPU1_FPU", ARMSSE, cpu_fpu[1], true),
60
+ FPGA_AN386,
94
DEFINE_PROP_BOOL("CPU1_DSP", ARMSSE, cpu_dsp[1], true),
61
FPGA_AN511,
95
+ DEFINE_PROP_UINT32("CPU0_MPU_NS", ARMSSE, cpu_mpu_ns[0], 8),
62
} MPS2FPGAType;
96
+ DEFINE_PROP_UINT32("CPU0_MPU_S", ARMSSE, cpu_mpu_s[0], 8),
63
97
+ DEFINE_PROP_UINT32("CPU1_MPU_NS", ARMSSE, cpu_mpu_ns[1], 8),
64
@@ -XXX,XX +XXX,XX @@ typedef struct MPS2MachineState MPS2MachineState;
98
+ DEFINE_PROP_UINT32("CPU1_MPU_S", ARMSSE, cpu_mpu_s[1], 8),
65
99
DEFINE_PROP_END_OF_LIST()
66
#define TYPE_MPS2_MACHINE "mps2"
100
};
67
#define TYPE_MPS2_AN385_MACHINE MACHINE_TYPE_NAME("mps2-an385")
101
68
+#define TYPE_MPS2_AN386_MACHINE MACHINE_TYPE_NAME("mps2-an386")
102
@@ -XXX,XX +XXX,XX @@ static Property sse300_properties[] = {
69
#define TYPE_MPS2_AN511_MACHINE MACHINE_TYPE_NAME("mps2-an511")
103
DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
70
104
DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], true),
71
DECLARE_OBJ_CHECKERS(MPS2MachineState, MPS2MachineClass,
105
DEFINE_PROP_BOOL("CPU0_DSP", ARMSSE, cpu_dsp[0], true),
72
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
106
+ DEFINE_PROP_UINT32("CPU0_MPU_NS", ARMSSE, cpu_mpu_ns[0], 8),
73
* tradeoffs. For QEMU they're all just RAM, though. We arbitrarily
107
+ DEFINE_PROP_UINT32("CPU0_MPU_S", ARMSSE, cpu_mpu_s[0], 8),
74
* call the 16MB our "system memory", as it's the largest lump.
108
DEFINE_PROP_END_OF_LIST()
75
*
109
};
76
- * Common to both boards:
110
77
- * 0x21000000..0x21ffffff : PSRAM (16MB)
111
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
78
- * AN385 only:
112
return;
79
+ * AN385/AN386/AN511:
113
}
80
+ * 0x21000000 .. 0x21ffffff : PSRAM (16MB)
114
}
81
+ * AN385/AN386 only:
115
+ if (!object_property_set_uint(cpuobj, "mpu-ns-regions",
82
* 0x00000000 .. 0x003fffff : ZBT SSRAM1
116
+ s->cpu_mpu_ns[i], errp)) {
83
* 0x00400000 .. 0x007fffff : mirror of ZBT SSRAM1
117
+ return;
84
* 0x20000000 .. 0x203fffff : ZBT SSRAM 2&3
118
+ }
85
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
119
+ if (!object_property_set_uint(cpuobj, "mpu-s-regions",
86
* 0x20000000 .. 0x2001ffff : SRAM
120
+ s->cpu_mpu_s[i], errp)) {
87
* 0x20400000 .. 0x207fffff : ZBT SSRAM 2&3
121
+ return;
88
*
122
+ }
89
- * The AN385 has a feature where the lowest 16K can be mapped
123
90
+ * The AN385/AN386 has a feature where the lowest 16K can be mapped
124
if (i > 0) {
91
* either to the bottom of the ZBT SSRAM1 or to the block RAM.
125
memory_region_add_subregion_overlap(&s->cpu_container[i], 0,
92
* This is of no use for QEMU so we don't implement it (as if
126
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
93
* zbt_boot_ctrl is always zero).
127
index XXXXXXX..XXXXXXX 100644
94
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
128
--- a/hw/arm/mps2-tz.c
95
129
+++ b/hw/arm/mps2-tz.c
96
switch (mmc->fpga_type) {
130
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
97
case FPGA_AN385:
131
int uart_overflow_irq; /* number of the combined UART overflow IRQ */
98
+ case FPGA_AN386:
132
uint32_t init_svtor; /* init-svtor setting for SSE */
99
make_ram(&mms->ssram1, "mps.ssram1", 0x0, 0x400000);
133
uint32_t sram_addr_width; /* SRAM_ADDR_WIDTH setting for SSE */
100
make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x400000);
134
+ uint32_t cpu0_mpu_ns; /* CPU0_MPU_NS setting for SSE */
101
make_ram(&mms->ssram23, "mps.ssram23", 0x20000000, 0x400000);
135
+ uint32_t cpu0_mpu_s; /* CPU0_MPU_S setting for SSE */
102
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
136
+ uint32_t cpu1_mpu_ns; /* CPU1_MPU_NS setting for SSE */
103
armv7m = DEVICE(&mms->armv7m);
137
+ uint32_t cpu1_mpu_s; /* CPU1_MPU_S setting for SSE */
104
switch (mmc->fpga_type) {
138
const RAMInfo *raminfo;
105
case FPGA_AN385:
139
const char *armsse_type;
106
+ case FPGA_AN386:
140
uint32_t boot_ram_size; /* size of ram at address 0; 0 == find in raminfo */
107
qdev_prop_set_uint32(armv7m, "num-irq", 32);
141
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
108
break;
142
#define MPS3_DDR_SIZE (2 * GiB)
109
case FPGA_AN511:
143
#endif
110
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
144
111
145
+/* For cpu{0,1}_mpu_{ns,s}, means "leave at SSE's default value" */
112
switch (mmc->fpga_type) {
146
+#define MPU_REGION_DEFAULT UINT32_MAX
113
case FPGA_AN385:
114
+ case FPGA_AN386:
115
{
116
/* The overflow IRQs for UARTs 0, 1 and 2 are ORed together.
117
* Overflow for UARTs 4 and 5 doesn't trigger any interrupt.
118
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
119
*/
120
lan9118_init(&nd_table[0], 0x40200000,
121
qdev_get_gpio_in(armv7m,
122
- mmc->fpga_type == FPGA_AN385 ? 13 : 47));
123
+ mmc->fpga_type == FPGA_AN511 ? 47 : 13));
124
125
system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
126
127
@@ -XXX,XX +XXX,XX @@ static void mps2_an385_class_init(ObjectClass *oc, void *data)
128
mmc->scc_id = 0x41043850;
129
}
130
131
+static void mps2_an386_class_init(ObjectClass *oc, void *data)
132
+{
133
+ MachineClass *mc = MACHINE_CLASS(oc);
134
+ MPS2MachineClass *mmc = MPS2_MACHINE_CLASS(oc);
135
+
147
+
136
+ mc->desc = "ARM MPS2 with AN386 FPGA image for Cortex-M4";
148
static const uint32_t an505_oscclk[] = {
137
+ mmc->fpga_type = FPGA_AN386;
149
40000000,
138
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m4");
150
24580000,
139
+ mmc->scc_id = 0x41043860;
151
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
140
+}
152
OBJECT(system_memory), &error_abort);
141
+
153
qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", mmc->numirq);
142
static void mps2_an511_class_init(ObjectClass *oc, void *data)
154
qdev_prop_set_uint32(iotkitdev, "init-svtor", mmc->init_svtor);
155
+ if (mmc->cpu0_mpu_ns != MPU_REGION_DEFAULT) {
156
+ qdev_prop_set_uint32(iotkitdev, "CPU0_MPU_NS", mmc->cpu0_mpu_ns);
157
+ }
158
+ if (mmc->cpu0_mpu_s != MPU_REGION_DEFAULT) {
159
+ qdev_prop_set_uint32(iotkitdev, "CPU0_MPU_S", mmc->cpu0_mpu_s);
160
+ }
161
+ if (object_property_find(OBJECT(iotkitdev), "CPU1_MPU_NS")) {
162
+ if (mmc->cpu1_mpu_ns != MPU_REGION_DEFAULT) {
163
+ qdev_prop_set_uint32(iotkitdev, "CPU1_MPU_NS", mmc->cpu1_mpu_ns);
164
+ }
165
+ if (mmc->cpu1_mpu_s != MPU_REGION_DEFAULT) {
166
+ qdev_prop_set_uint32(iotkitdev, "CPU1_MPU_S", mmc->cpu1_mpu_s);
167
+ }
168
+ }
169
qdev_prop_set_uint32(iotkitdev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width);
170
qdev_connect_clock_in(iotkitdev, "MAINCLK", mms->sysclk);
171
qdev_connect_clock_in(iotkitdev, "S32KCLK", mms->s32kclk);
172
@@ -XXX,XX +XXX,XX @@ static void mps2tz_class_init(ObjectClass *oc, void *data)
143
{
173
{
144
MachineClass *mc = MACHINE_CLASS(oc);
174
MachineClass *mc = MACHINE_CLASS(oc);
145
@@ -XXX,XX +XXX,XX @@ static const TypeInfo mps2_an385_info = {
175
IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(oc);
146
.class_init = mps2_an385_class_init,
176
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
147
};
177
148
178
mc->init = mps2tz_common_init;
149
+static const TypeInfo mps2_an386_info = {
179
mc->reset = mps2_machine_reset;
150
+ .name = TYPE_MPS2_AN386_MACHINE,
180
iic->check = mps2_tz_idau_check;
151
+ .parent = TYPE_MPS2_MACHINE,
152
+ .class_init = mps2_an386_class_init,
153
+};
154
+
181
+
155
static const TypeInfo mps2_an511_info = {
182
+ /* Most machines leave these at the SSE defaults */
156
.name = TYPE_MPS2_AN511_MACHINE,
183
+ mmc->cpu0_mpu_ns = MPU_REGION_DEFAULT;
157
.parent = TYPE_MPS2_MACHINE,
184
+ mmc->cpu0_mpu_s = MPU_REGION_DEFAULT;
158
@@ -XXX,XX +XXX,XX @@ static void mps2_machine_init(void)
185
+ mmc->cpu1_mpu_ns = MPU_REGION_DEFAULT;
159
{
186
+ mmc->cpu1_mpu_s = MPU_REGION_DEFAULT;
160
type_register_static(&mps2_info);
161
type_register_static(&mps2_an385_info);
162
+ type_register_static(&mps2_an386_info);
163
type_register_static(&mps2_an511_info);
164
}
187
}
165
188
189
static void mps2tz_set_default_ram_info(MPS2TZMachineClass *mmc)
190
@@ -XXX,XX +XXX,XX @@ static void mps3tz_an547_class_init(ObjectClass *oc, void *data)
191
mmc->numirq = 96;
192
mmc->uart_overflow_irq = 48;
193
mmc->init_svtor = 0x00000000;
194
+ mmc->cpu0_mpu_s = mmc->cpu0_mpu_ns = 16;
195
mmc->sram_addr_width = 21;
196
mmc->raminfo = an547_raminfo;
197
mmc->armsse_type = TYPE_SSE300;
166
--
198
--
167
2.20.1
199
2.34.1
168
200
169
201
diff view generated by jsdifflib
Deleted patch
1
Make the list of MPS2 boards consistent in the phrasing of each
2
entry, use the correct casing of "Arm", and move the mps2-an511
3
entry so the list is in numeric order.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20200903202048.15370-4-peter.maydell@linaro.org
8
---
9
docs/system/arm/mps2.rst | 14 +++++++-------
10
1 file changed, 7 insertions(+), 7 deletions(-)
11
12
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
13
index XXXXXXX..XXXXXXX 100644
14
--- a/docs/system/arm/mps2.rst
15
+++ b/docs/system/arm/mps2.rst
16
@@ -XXX,XX +XXX,XX @@ as seen by the guest depend significantly on the FPGA image.
17
QEMU models the following FPGA images:
18
19
``mps2-an385``
20
- Cortex-M3 as documented in ARM Application Note AN385
21
+ Cortex-M3 as documented in Arm Application Note AN385
22
``mps2-an386``
23
- Cortex-M4 as documented in ARM Application Note AN386
24
+ Cortex-M4 as documented in Arm Application Note AN386
25
``mps2-an500``
26
- Cortex-M7 as documented in ARM Application Note AN500
27
-``mps2-an511``
28
- Cortex-M3 'DesignStart' as documented in AN511
29
+ Cortex-M7 as documented in Arm Application Note AN500
30
``mps2-an505``
31
- Cortex-M33 as documented in ARM Application Note AN505
32
+ Cortex-M33 as documented in Arm Application Note AN505
33
+``mps2-an511``
34
+ Cortex-M3 'DesignStart' as documented in Arm Application Note AN511
35
``mps2-an521``
36
- Dual Cortex-M33 as documented in Application Note AN521
37
+ Dual Cortex-M33 as documented in Arm Application Note AN521
38
39
Differences between QEMU and real hardware:
40
41
--
42
2.20.1
43
44
diff view generated by jsdifflib
Deleted patch
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
1
3
Implement a device model for the System Global Control Registers in the
4
NPCM730 and NPCM750 BMC SoCs.
5
6
This is primarily used to enable SMP boot (the boot ROM spins reading
7
the SCRPAD register) and DDR memory initialization; other registers are
8
best effort for now.
9
10
The reset values of the MDLR and PWRON registers are determined by the
11
SoC variant (730 vs 750) and board straps respectively.
12
13
Reviewed-by: Joel Stanley <joel@jms.id.au>
14
Reviewed-by: Cédric Le Goater <clg@kaod.org>
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Tested-by: Alexander Bulekov <alxndr@bu.edu>
18
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
19
Message-id: 20200911052101.2602693-2-hskinnemoen@google.com
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
22
include/hw/misc/npcm7xx_gcr.h | 43 ++++++
23
hw/misc/npcm7xx_gcr.c | 269 ++++++++++++++++++++++++++++++++++
24
MAINTAINERS | 8 +
25
hw/arm/Kconfig | 3 +
26
hw/misc/meson.build | 3 +
27
hw/misc/trace-events | 4 +
28
6 files changed, 330 insertions(+)
29
create mode 100644 include/hw/misc/npcm7xx_gcr.h
30
create mode 100644 hw/misc/npcm7xx_gcr.c
31
32
diff --git a/include/hw/misc/npcm7xx_gcr.h b/include/hw/misc/npcm7xx_gcr.h
33
new file mode 100644
34
index XXXXXXX..XXXXXXX
35
--- /dev/null
36
+++ b/include/hw/misc/npcm7xx_gcr.h
37
@@ -XXX,XX +XXX,XX @@
38
+/*
39
+ * Nuvoton NPCM7xx System Global Control Registers.
40
+ *
41
+ * Copyright 2020 Google LLC
42
+ *
43
+ * This program is free software; you can redistribute it and/or modify it
44
+ * under the terms of the GNU General Public License as published by the
45
+ * Free Software Foundation; either version 2 of the License, or
46
+ * (at your option) any later version.
47
+ *
48
+ * This program is distributed in the hope that it will be useful, but WITHOUT
49
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
50
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
51
+ * for more details.
52
+ */
53
+#ifndef NPCM7XX_GCR_H
54
+#define NPCM7XX_GCR_H
55
+
56
+#include "exec/memory.h"
57
+#include "hw/sysbus.h"
58
+
59
+/*
60
+ * Number of registers in our device state structure. Don't change this without
61
+ * incrementing the version_id in the vmstate.
62
+ */
63
+#define NPCM7XX_GCR_NR_REGS (0x148 / sizeof(uint32_t))
64
+
65
+typedef struct NPCM7xxGCRState {
66
+ SysBusDevice parent;
67
+
68
+ MemoryRegion iomem;
69
+
70
+ uint32_t regs[NPCM7XX_GCR_NR_REGS];
71
+
72
+ uint32_t reset_pwron;
73
+ uint32_t reset_mdlr;
74
+ uint32_t reset_intcr3;
75
+} NPCM7xxGCRState;
76
+
77
+#define TYPE_NPCM7XX_GCR "npcm7xx-gcr"
78
+#define NPCM7XX_GCR(obj) OBJECT_CHECK(NPCM7xxGCRState, (obj), TYPE_NPCM7XX_GCR)
79
+
80
+#endif /* NPCM7XX_GCR_H */
81
diff --git a/hw/misc/npcm7xx_gcr.c b/hw/misc/npcm7xx_gcr.c
82
new file mode 100644
83
index XXXXXXX..XXXXXXX
84
--- /dev/null
85
+++ b/hw/misc/npcm7xx_gcr.c
86
@@ -XXX,XX +XXX,XX @@
87
+/*
88
+ * Nuvoton NPCM7xx System Global Control Registers.
89
+ *
90
+ * Copyright 2020 Google LLC
91
+ *
92
+ * This program is free software; you can redistribute it and/or modify it
93
+ * under the terms of the GNU General Public License as published by the
94
+ * Free Software Foundation; either version 2 of the License, or
95
+ * (at your option) any later version.
96
+ *
97
+ * This program is distributed in the hope that it will be useful, but WITHOUT
98
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
99
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
100
+ * for more details.
101
+ */
102
+
103
+#include "qemu/osdep.h"
104
+
105
+#include "hw/misc/npcm7xx_gcr.h"
106
+#include "hw/qdev-properties.h"
107
+#include "migration/vmstate.h"
108
+#include "qapi/error.h"
109
+#include "qemu/cutils.h"
110
+#include "qemu/log.h"
111
+#include "qemu/module.h"
112
+#include "qemu/units.h"
113
+
114
+#include "trace.h"
115
+
116
+#define NPCM7XX_GCR_MIN_DRAM_SIZE (128 * MiB)
117
+#define NPCM7XX_GCR_MAX_DRAM_SIZE (2 * GiB)
118
+
119
+enum NPCM7xxGCRRegisters {
120
+ NPCM7XX_GCR_PDID,
121
+ NPCM7XX_GCR_PWRON,
122
+ NPCM7XX_GCR_MFSEL1 = 0x0c / sizeof(uint32_t),
123
+ NPCM7XX_GCR_MFSEL2,
124
+ NPCM7XX_GCR_MISCPE,
125
+ NPCM7XX_GCR_SPSWC = 0x038 / sizeof(uint32_t),
126
+ NPCM7XX_GCR_INTCR,
127
+ NPCM7XX_GCR_INTSR,
128
+ NPCM7XX_GCR_HIFCR = 0x050 / sizeof(uint32_t),
129
+ NPCM7XX_GCR_INTCR2 = 0x060 / sizeof(uint32_t),
130
+ NPCM7XX_GCR_MFSEL3,
131
+ NPCM7XX_GCR_SRCNT,
132
+ NPCM7XX_GCR_RESSR,
133
+ NPCM7XX_GCR_RLOCKR1,
134
+ NPCM7XX_GCR_FLOCKR1,
135
+ NPCM7XX_GCR_DSCNT,
136
+ NPCM7XX_GCR_MDLR,
137
+ NPCM7XX_GCR_SCRPAD3,
138
+ NPCM7XX_GCR_SCRPAD2,
139
+ NPCM7XX_GCR_DAVCLVLR = 0x098 / sizeof(uint32_t),
140
+ NPCM7XX_GCR_INTCR3,
141
+ NPCM7XX_GCR_VSINTR = 0x0ac / sizeof(uint32_t),
142
+ NPCM7XX_GCR_MFSEL4,
143
+ NPCM7XX_GCR_CPBPNTR = 0x0c4 / sizeof(uint32_t),
144
+ NPCM7XX_GCR_CPCTL = 0x0d0 / sizeof(uint32_t),
145
+ NPCM7XX_GCR_CP2BST,
146
+ NPCM7XX_GCR_B2CPNT,
147
+ NPCM7XX_GCR_CPPCTL,
148
+ NPCM7XX_GCR_I2CSEGSEL,
149
+ NPCM7XX_GCR_I2CSEGCTL,
150
+ NPCM7XX_GCR_VSRCR,
151
+ NPCM7XX_GCR_MLOCKR,
152
+ NPCM7XX_GCR_SCRPAD = 0x013c / sizeof(uint32_t),
153
+ NPCM7XX_GCR_USB1PHYCTL,
154
+ NPCM7XX_GCR_USB2PHYCTL,
155
+ NPCM7XX_GCR_REGS_END,
156
+};
157
+
158
+static const uint32_t cold_reset_values[NPCM7XX_GCR_NR_REGS] = {
159
+ [NPCM7XX_GCR_PDID] = 0x04a92750, /* Poleg A1 */
160
+ [NPCM7XX_GCR_MISCPE] = 0x0000ffff,
161
+ [NPCM7XX_GCR_SPSWC] = 0x00000003,
162
+ [NPCM7XX_GCR_INTCR] = 0x0000035e,
163
+ [NPCM7XX_GCR_HIFCR] = 0x0000004e,
164
+ [NPCM7XX_GCR_INTCR2] = (1U << 19), /* DDR initialized */
165
+ [NPCM7XX_GCR_RESSR] = 0x80000000,
166
+ [NPCM7XX_GCR_DSCNT] = 0x000000c0,
167
+ [NPCM7XX_GCR_DAVCLVLR] = 0x5a00f3cf,
168
+ [NPCM7XX_GCR_SCRPAD] = 0x00000008,
169
+ [NPCM7XX_GCR_USB1PHYCTL] = 0x034730e4,
170
+ [NPCM7XX_GCR_USB2PHYCTL] = 0x034730e4,
171
+};
172
+
173
+static uint64_t npcm7xx_gcr_read(void *opaque, hwaddr offset, unsigned size)
174
+{
175
+ uint32_t reg = offset / sizeof(uint32_t);
176
+ NPCM7xxGCRState *s = opaque;
177
+
178
+ if (reg >= NPCM7XX_GCR_NR_REGS) {
179
+ qemu_log_mask(LOG_GUEST_ERROR,
180
+ "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
181
+ __func__, offset);
182
+ return 0;
183
+ }
184
+
185
+ trace_npcm7xx_gcr_read(offset, s->regs[reg]);
186
+
187
+ return s->regs[reg];
188
+}
189
+
190
+static void npcm7xx_gcr_write(void *opaque, hwaddr offset,
191
+ uint64_t v, unsigned size)
192
+{
193
+ uint32_t reg = offset / sizeof(uint32_t);
194
+ NPCM7xxGCRState *s = opaque;
195
+ uint32_t value = v;
196
+
197
+ trace_npcm7xx_gcr_write(offset, value);
198
+
199
+ if (reg >= NPCM7XX_GCR_NR_REGS) {
200
+ qemu_log_mask(LOG_GUEST_ERROR,
201
+ "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
202
+ __func__, offset);
203
+ return;
204
+ }
205
+
206
+ switch (reg) {
207
+ case NPCM7XX_GCR_PDID:
208
+ case NPCM7XX_GCR_PWRON:
209
+ case NPCM7XX_GCR_INTSR:
210
+ qemu_log_mask(LOG_GUEST_ERROR,
211
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
212
+ __func__, offset);
213
+ return;
214
+
215
+ case NPCM7XX_GCR_RESSR:
216
+ case NPCM7XX_GCR_CP2BST:
217
+ /* Write 1 to clear */
218
+ value = s->regs[reg] & ~value;
219
+ break;
220
+
221
+ case NPCM7XX_GCR_RLOCKR1:
222
+ case NPCM7XX_GCR_MDLR:
223
+ /* Write 1 to set */
224
+ value |= s->regs[reg];
225
+ break;
226
+ };
227
+
228
+ s->regs[reg] = value;
229
+}
230
+
231
+static const struct MemoryRegionOps npcm7xx_gcr_ops = {
232
+ .read = npcm7xx_gcr_read,
233
+ .write = npcm7xx_gcr_write,
234
+ .endianness = DEVICE_LITTLE_ENDIAN,
235
+ .valid = {
236
+ .min_access_size = 4,
237
+ .max_access_size = 4,
238
+ .unaligned = false,
239
+ },
240
+};
241
+
242
+static void npcm7xx_gcr_enter_reset(Object *obj, ResetType type)
243
+{
244
+ NPCM7xxGCRState *s = NPCM7XX_GCR(obj);
245
+
246
+ QEMU_BUILD_BUG_ON(sizeof(s->regs) != sizeof(cold_reset_values));
247
+
248
+ switch (type) {
249
+ case RESET_TYPE_COLD:
250
+ memcpy(s->regs, cold_reset_values, sizeof(s->regs));
251
+ s->regs[NPCM7XX_GCR_PWRON] = s->reset_pwron;
252
+ s->regs[NPCM7XX_GCR_MDLR] = s->reset_mdlr;
253
+ s->regs[NPCM7XX_GCR_INTCR3] = s->reset_intcr3;
254
+ break;
255
+ }
256
+}
257
+
258
+static void npcm7xx_gcr_realize(DeviceState *dev, Error **errp)
259
+{
260
+ ERRP_GUARD();
261
+ NPCM7xxGCRState *s = NPCM7XX_GCR(dev);
262
+ uint64_t dram_size;
263
+ Object *obj;
264
+
265
+ obj = object_property_get_link(OBJECT(dev), "dram-mr", errp);
266
+ if (!obj) {
267
+ error_prepend(errp, "%s: required dram-mr link not found: ", __func__);
268
+ return;
269
+ }
270
+ dram_size = memory_region_size(MEMORY_REGION(obj));
271
+ if (!is_power_of_2(dram_size) ||
272
+ dram_size < NPCM7XX_GCR_MIN_DRAM_SIZE ||
273
+ dram_size > NPCM7XX_GCR_MAX_DRAM_SIZE) {
274
+ g_autofree char *sz = size_to_str(dram_size);
275
+ g_autofree char *min_sz = size_to_str(NPCM7XX_GCR_MIN_DRAM_SIZE);
276
+ g_autofree char *max_sz = size_to_str(NPCM7XX_GCR_MAX_DRAM_SIZE);
277
+ error_setg(errp, "%s: unsupported DRAM size %s", __func__, sz);
278
+ error_append_hint(errp,
279
+ "DRAM size must be a power of two between %s and %s,"
280
+ " inclusive.\n", min_sz, max_sz);
281
+ return;
282
+ }
283
+
284
+ /* Power-on reset value */
285
+ s->reset_intcr3 = 0x00001002;
286
+
287
+ /*
288
+ * The GMMAP (Graphics Memory Map) field is used by u-boot to detect the
289
+ * DRAM size, and is normally initialized by the boot block as part of DRAM
290
+ * training. However, since we don't have a complete emulation of the
291
+ * memory controller and try to make it look like it has already been
292
+ * initialized, the boot block will skip this initialization, and we need
293
+ * to make sure this field is set correctly up front.
294
+ *
295
+ * WARNING: some versions of u-boot only looks at bits 8 and 9, so 2 GiB of
296
+ * DRAM will be interpreted as 128 MiB.
297
+ *
298
+ * https://github.com/Nuvoton-Israel/u-boot/blob/2aef993bd2aafeb5408dbaad0f3ce099ee40c4aa/board/nuvoton/poleg/poleg.c#L244
299
+ */
300
+ s->reset_intcr3 |= ctz64(dram_size / NPCM7XX_GCR_MIN_DRAM_SIZE) << 8;
301
+}
302
+
303
+static void npcm7xx_gcr_init(Object *obj)
304
+{
305
+ NPCM7xxGCRState *s = NPCM7XX_GCR(obj);
306
+
307
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_gcr_ops, s,
308
+ TYPE_NPCM7XX_GCR, 4 * KiB);
309
+ sysbus_init_mmio(&s->parent, &s->iomem);
310
+}
311
+
312
+static const VMStateDescription vmstate_npcm7xx_gcr = {
313
+ .name = "npcm7xx-gcr",
314
+ .version_id = 0,
315
+ .minimum_version_id = 0,
316
+ .fields = (VMStateField[]) {
317
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxGCRState, NPCM7XX_GCR_NR_REGS),
318
+ VMSTATE_END_OF_LIST(),
319
+ },
320
+};
321
+
322
+static Property npcm7xx_gcr_properties[] = {
323
+ DEFINE_PROP_UINT32("disabled-modules", NPCM7xxGCRState, reset_mdlr, 0),
324
+ DEFINE_PROP_UINT32("power-on-straps", NPCM7xxGCRState, reset_pwron, 0),
325
+ DEFINE_PROP_END_OF_LIST(),
326
+};
327
+
328
+static void npcm7xx_gcr_class_init(ObjectClass *klass, void *data)
329
+{
330
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
331
+ DeviceClass *dc = DEVICE_CLASS(klass);
332
+
333
+ QEMU_BUILD_BUG_ON(NPCM7XX_GCR_REGS_END > NPCM7XX_GCR_NR_REGS);
334
+
335
+ dc->desc = "NPCM7xx System Global Control Registers";
336
+ dc->realize = npcm7xx_gcr_realize;
337
+ dc->vmsd = &vmstate_npcm7xx_gcr;
338
+ rc->phases.enter = npcm7xx_gcr_enter_reset;
339
+
340
+ device_class_set_props(dc, npcm7xx_gcr_properties);
341
+}
342
+
343
+static const TypeInfo npcm7xx_gcr_info = {
344
+ .name = TYPE_NPCM7XX_GCR,
345
+ .parent = TYPE_SYS_BUS_DEVICE,
346
+ .instance_size = sizeof(NPCM7xxGCRState),
347
+ .instance_init = npcm7xx_gcr_init,
348
+ .class_init = npcm7xx_gcr_class_init,
349
+};
350
+
351
+static void npcm7xx_gcr_register_type(void)
352
+{
353
+ type_register_static(&npcm7xx_gcr_info);
354
+}
355
+type_init(npcm7xx_gcr_register_type);
356
diff --git a/MAINTAINERS b/MAINTAINERS
357
index XXXXXXX..XXXXXXX 100644
358
--- a/MAINTAINERS
359
+++ b/MAINTAINERS
360
@@ -XXX,XX +XXX,XX @@ S: Odd Fixes
361
F: hw/arm/musicpal.c
362
F: docs/system/arm/musicpal.rst
363
364
+Nuvoton NPCM7xx
365
+M: Havard Skinnemoen <hskinnemoen@google.com>
366
+M: Tyrone Ting <kfting@nuvoton.com>
367
+L: qemu-arm@nongnu.org
368
+S: Supported
369
+F: hw/*/npcm7xx*
370
+F: include/hw/*/npcm7xx*
371
+
372
nSeries
373
M: Andrzej Zaborowski <balrogg@gmail.com>
374
M: Peter Maydell <peter.maydell@linaro.org>
375
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
376
index XXXXXXX..XXXXXXX 100644
377
--- a/hw/arm/Kconfig
378
+++ b/hw/arm/Kconfig
379
@@ -XXX,XX +XXX,XX @@ config XLNX_VERSAL
380
select VIRTIO_MMIO
381
select UNIMP
382
383
+config NPCM7XX
384
+ bool
385
+
386
config FSL_IMX25
387
bool
388
select IMX
389
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
390
index XXXXXXX..XXXXXXX 100644
391
--- a/hw/misc/meson.build
392
+++ b/hw/misc/meson.build
393
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_IMX', if_true: files(
394
))
395
softmmu_ss.add(when: 'CONFIG_MILKYMIST', if_true: files('milkymist-hpdmc.c', 'milkymist-pfpu.c'))
396
softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c'))
397
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
398
+ 'npcm7xx_gcr.c',
399
+))
400
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files(
401
'omap_clk.c',
402
'omap_gpmc.c',
403
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
404
index XXXXXXX..XXXXXXX 100644
405
--- a/hw/misc/trace-events
406
+++ b/hw/misc/trace-events
407
@@ -XXX,XX +XXX,XX @@ mos6522_set_sr_int(void) "set sr_int"
408
mos6522_write(uint64_t addr, uint64_t val) "reg=0x%"PRIx64 " val=0x%"PRIx64
409
mos6522_read(uint64_t addr, unsigned val) "reg=0x%"PRIx64 " val=0x%x"
410
411
+# npcm7xx_gcr.c
412
+npcm7xx_gcr_read(uint64_t offset, uint32_t value) " offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
413
+npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
414
+
415
# stm32f4xx_syscfg.c
416
stm32f4xx_syscfg_set_irq(int gpio, int line, int level) "Interupt: GPIO: %d, Line: %d; Level: %d"
417
stm32f4xx_pulse_exti(int irq) "Pulse EXTI: %d"
418
--
419
2.20.1
420
421
diff view generated by jsdifflib
Deleted patch
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
1
3
The NPCM730 and NPCM750 SoCs have three timer modules each holding five
4
timers and some shared registers (e.g. interrupt status).
5
6
Each timer runs at 25 MHz divided by a prescaler, and counts down from a
7
configurable initial value to zero. When zero is reached, the interrupt
8
flag for the timer is set, and the timer is disabled (one-shot mode) or
9
reloaded from its initial value (periodic mode).
10
11
This implementation is sufficient to boot a Linux kernel configured for
12
NPCM750. Note that the kernel does not seem to actually turn on the
13
interrupts.
14
15
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
16
Reviewed-by: Joel Stanley <joel@jms.id.au>
17
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Tested-by: Alexander Bulekov <alxndr@bu.edu>
19
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
21
Message-id: 20200911052101.2602693-4-hskinnemoen@google.com
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
---
24
include/hw/timer/npcm7xx_timer.h | 78 +++++
25
hw/timer/npcm7xx_timer.c | 543 +++++++++++++++++++++++++++++++
26
hw/timer/meson.build | 1 +
27
hw/timer/trace-events | 5 +
28
4 files changed, 627 insertions(+)
29
create mode 100644 include/hw/timer/npcm7xx_timer.h
30
create mode 100644 hw/timer/npcm7xx_timer.c
31
32
diff --git a/include/hw/timer/npcm7xx_timer.h b/include/hw/timer/npcm7xx_timer.h
33
new file mode 100644
34
index XXXXXXX..XXXXXXX
35
--- /dev/null
36
+++ b/include/hw/timer/npcm7xx_timer.h
37
@@ -XXX,XX +XXX,XX @@
38
+/*
39
+ * Nuvoton NPCM7xx Timer Controller
40
+ *
41
+ * Copyright 2020 Google LLC
42
+ *
43
+ * This program is free software; you can redistribute it and/or modify it
44
+ * under the terms of the GNU General Public License as published by the
45
+ * Free Software Foundation; either version 2 of the License, or
46
+ * (at your option) any later version.
47
+ *
48
+ * This program is distributed in the hope that it will be useful, but WITHOUT
49
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
50
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
51
+ * for more details.
52
+ */
53
+#ifndef NPCM7XX_TIMER_H
54
+#define NPCM7XX_TIMER_H
55
+
56
+#include "exec/memory.h"
57
+#include "hw/sysbus.h"
58
+#include "qemu/timer.h"
59
+
60
+/* Each Timer Module (TIM) instance holds five 25 MHz timers. */
61
+#define NPCM7XX_TIMERS_PER_CTRL (5)
62
+
63
+/*
64
+ * Number of registers in our device state structure. Don't change this without
65
+ * incrementing the version_id in the vmstate.
66
+ */
67
+#define NPCM7XX_TIMER_NR_REGS (0x54 / sizeof(uint32_t))
68
+
69
+typedef struct NPCM7xxTimerCtrlState NPCM7xxTimerCtrlState;
70
+
71
+/**
72
+ * struct NPCM7xxTimer - Individual timer state.
73
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
74
+ * @qtimer: QEMU timer that notifies us on expiration.
75
+ * @expires_ns: Absolute virtual expiration time.
76
+ * @remaining_ns: Remaining time until expiration if timer is paused.
77
+ * @tcsr: The Timer Control and Status Register.
78
+ * @ticr: The Timer Initial Count Register.
79
+ */
80
+typedef struct NPCM7xxTimer {
81
+ NPCM7xxTimerCtrlState *ctrl;
82
+
83
+ qemu_irq irq;
84
+ QEMUTimer qtimer;
85
+ int64_t expires_ns;
86
+ int64_t remaining_ns;
87
+
88
+ uint32_t tcsr;
89
+ uint32_t ticr;
90
+} NPCM7xxTimer;
91
+
92
+/**
93
+ * struct NPCM7xxTimerCtrlState - Timer Module device state.
94
+ * @parent: System bus device.
95
+ * @iomem: Memory region through which registers are accessed.
96
+ * @tisr: The Timer Interrupt Status Register.
97
+ * @wtcr: The Watchdog Timer Control Register.
98
+ * @timer: The five individual timers managed by this module.
99
+ */
100
+struct NPCM7xxTimerCtrlState {
101
+ SysBusDevice parent;
102
+
103
+ MemoryRegion iomem;
104
+
105
+ uint32_t tisr;
106
+ uint32_t wtcr;
107
+
108
+ NPCM7xxTimer timer[NPCM7XX_TIMERS_PER_CTRL];
109
+};
110
+
111
+#define TYPE_NPCM7XX_TIMER "npcm7xx-timer"
112
+#define NPCM7XX_TIMER(obj) \
113
+ OBJECT_CHECK(NPCM7xxTimerCtrlState, (obj), TYPE_NPCM7XX_TIMER)
114
+
115
+#endif /* NPCM7XX_TIMER_H */
116
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
117
new file mode 100644
118
index XXXXXXX..XXXXXXX
119
--- /dev/null
120
+++ b/hw/timer/npcm7xx_timer.c
121
@@ -XXX,XX +XXX,XX @@
122
+/*
123
+ * Nuvoton NPCM7xx Timer Controller
124
+ *
125
+ * Copyright 2020 Google LLC
126
+ *
127
+ * This program is free software; you can redistribute it and/or modify it
128
+ * under the terms of the GNU General Public License as published by the
129
+ * Free Software Foundation; either version 2 of the License, or
130
+ * (at your option) any later version.
131
+ *
132
+ * This program is distributed in the hope that it will be useful, but WITHOUT
133
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
134
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
135
+ * for more details.
136
+ */
137
+
138
+#include "qemu/osdep.h"
139
+
140
+#include "hw/irq.h"
141
+#include "hw/misc/npcm7xx_clk.h"
142
+#include "hw/timer/npcm7xx_timer.h"
143
+#include "migration/vmstate.h"
144
+#include "qemu/bitops.h"
145
+#include "qemu/error-report.h"
146
+#include "qemu/log.h"
147
+#include "qemu/module.h"
148
+#include "qemu/timer.h"
149
+#include "qemu/units.h"
150
+#include "trace.h"
151
+
152
+/* 32-bit register indices. */
153
+enum NPCM7xxTimerRegisters {
154
+ NPCM7XX_TIMER_TCSR0,
155
+ NPCM7XX_TIMER_TCSR1,
156
+ NPCM7XX_TIMER_TICR0,
157
+ NPCM7XX_TIMER_TICR1,
158
+ NPCM7XX_TIMER_TDR0,
159
+ NPCM7XX_TIMER_TDR1,
160
+ NPCM7XX_TIMER_TISR,
161
+ NPCM7XX_TIMER_WTCR,
162
+ NPCM7XX_TIMER_TCSR2,
163
+ NPCM7XX_TIMER_TCSR3,
164
+ NPCM7XX_TIMER_TICR2,
165
+ NPCM7XX_TIMER_TICR3,
166
+ NPCM7XX_TIMER_TDR2,
167
+ NPCM7XX_TIMER_TDR3,
168
+ NPCM7XX_TIMER_TCSR4 = 0x0040 / sizeof(uint32_t),
169
+ NPCM7XX_TIMER_TICR4 = 0x0048 / sizeof(uint32_t),
170
+ NPCM7XX_TIMER_TDR4 = 0x0050 / sizeof(uint32_t),
171
+ NPCM7XX_TIMER_REGS_END,
172
+};
173
+
174
+/* Register field definitions. */
175
+#define NPCM7XX_TCSR_CEN BIT(30)
176
+#define NPCM7XX_TCSR_IE BIT(29)
177
+#define NPCM7XX_TCSR_PERIODIC BIT(27)
178
+#define NPCM7XX_TCSR_CRST BIT(26)
179
+#define NPCM7XX_TCSR_CACT BIT(25)
180
+#define NPCM7XX_TCSR_RSVD 0x01ffff00
181
+#define NPCM7XX_TCSR_PRESCALE_START 0
182
+#define NPCM7XX_TCSR_PRESCALE_LEN 8
183
+
184
+/*
185
+ * Returns the index of timer in the tc->timer array. This can be used to
186
+ * locate the registers that belong to this timer.
187
+ */
188
+static int npcm7xx_timer_index(NPCM7xxTimerCtrlState *tc, NPCM7xxTimer *timer)
189
+{
190
+ int index = timer - tc->timer;
191
+
192
+ g_assert(index >= 0 && index < NPCM7XX_TIMERS_PER_CTRL);
193
+
194
+ return index;
195
+}
196
+
197
+/* Return the value by which to divide the reference clock rate. */
198
+static uint32_t npcm7xx_tcsr_prescaler(uint32_t tcsr)
199
+{
200
+ return extract32(tcsr, NPCM7XX_TCSR_PRESCALE_START,
201
+ NPCM7XX_TCSR_PRESCALE_LEN) + 1;
202
+}
203
+
204
+/* Convert a timer cycle count to a time interval in nanoseconds. */
205
+static int64_t npcm7xx_timer_count_to_ns(NPCM7xxTimer *t, uint32_t count)
206
+{
207
+ int64_t ns = count;
208
+
209
+ ns *= NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ;
210
+ ns *= npcm7xx_tcsr_prescaler(t->tcsr);
211
+
212
+ return ns;
213
+}
214
+
215
+/* Convert a time interval in nanoseconds to a timer cycle count. */
216
+static uint32_t npcm7xx_timer_ns_to_count(NPCM7xxTimer *t, int64_t ns)
217
+{
218
+ int64_t count;
219
+
220
+ count = ns / (NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ);
221
+ count /= npcm7xx_tcsr_prescaler(t->tcsr);
222
+
223
+ return count;
224
+}
225
+
226
+/*
227
+ * Raise the interrupt line if there's a pending interrupt and interrupts are
228
+ * enabled for this timer. If not, lower it.
229
+ */
230
+static void npcm7xx_timer_check_interrupt(NPCM7xxTimer *t)
231
+{
232
+ NPCM7xxTimerCtrlState *tc = t->ctrl;
233
+ int index = npcm7xx_timer_index(tc, t);
234
+ bool pending = (t->tcsr & NPCM7XX_TCSR_IE) && (tc->tisr & BIT(index));
235
+
236
+ qemu_set_irq(t->irq, pending);
237
+ trace_npcm7xx_timer_irq(DEVICE(tc)->canonical_path, index, pending);
238
+}
239
+
240
+/* Start or resume the timer. */
241
+static void npcm7xx_timer_start(NPCM7xxTimer *t)
242
+{
243
+ int64_t now;
244
+
245
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
246
+ t->expires_ns = now + t->remaining_ns;
247
+ timer_mod(&t->qtimer, t->expires_ns);
248
+}
249
+
250
+/*
251
+ * Called when the counter reaches zero. Sets the interrupt flag, and either
252
+ * restarts or disables the timer.
253
+ */
254
+static void npcm7xx_timer_reached_zero(NPCM7xxTimer *t)
255
+{
256
+ NPCM7xxTimerCtrlState *tc = t->ctrl;
257
+ int index = npcm7xx_timer_index(tc, t);
258
+
259
+ tc->tisr |= BIT(index);
260
+
261
+ if (t->tcsr & NPCM7XX_TCSR_PERIODIC) {
262
+ t->remaining_ns = npcm7xx_timer_count_to_ns(t, t->ticr);
263
+ if (t->tcsr & NPCM7XX_TCSR_CEN) {
264
+ npcm7xx_timer_start(t);
265
+ }
266
+ } else {
267
+ t->tcsr &= ~(NPCM7XX_TCSR_CEN | NPCM7XX_TCSR_CACT);
268
+ }
269
+
270
+ npcm7xx_timer_check_interrupt(t);
271
+}
272
+
273
+/* Stop counting. Record the time remaining so we can continue later. */
274
+static void npcm7xx_timer_pause(NPCM7xxTimer *t)
275
+{
276
+ int64_t now;
277
+
278
+ timer_del(&t->qtimer);
279
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
280
+ t->remaining_ns = t->expires_ns - now;
281
+ if (t->remaining_ns <= 0) {
282
+ npcm7xx_timer_reached_zero(t);
283
+ }
284
+}
285
+
286
+/*
287
+ * Restart the timer from its initial value. If the timer was enabled and stays
288
+ * enabled, adjust the QEMU timer according to the new count. If the timer is
289
+ * transitioning from disabled to enabled, the caller is expected to start the
290
+ * timer later.
291
+ */
292
+static void npcm7xx_timer_restart(NPCM7xxTimer *t, uint32_t old_tcsr)
293
+{
294
+ t->remaining_ns = npcm7xx_timer_count_to_ns(t, t->ticr);
295
+
296
+ if (old_tcsr & t->tcsr & NPCM7XX_TCSR_CEN) {
297
+ npcm7xx_timer_start(t);
298
+ }
299
+}
300
+
301
+/* Register read and write handlers */
302
+
303
+static uint32_t npcm7xx_timer_read_tdr(NPCM7xxTimer *t)
304
+{
305
+ if (t->tcsr & NPCM7XX_TCSR_CEN) {
306
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
307
+
308
+ return npcm7xx_timer_ns_to_count(t, t->expires_ns - now);
309
+ }
310
+
311
+ return npcm7xx_timer_ns_to_count(t, t->remaining_ns);
312
+}
313
+
314
+static void npcm7xx_timer_write_tcsr(NPCM7xxTimer *t, uint32_t new_tcsr)
315
+{
316
+ uint32_t old_tcsr = t->tcsr;
317
+ uint32_t tdr;
318
+
319
+ if (new_tcsr & NPCM7XX_TCSR_RSVD) {
320
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: reserved bits in 0x%08x ignored\n",
321
+ __func__, new_tcsr);
322
+ new_tcsr &= ~NPCM7XX_TCSR_RSVD;
323
+ }
324
+ if (new_tcsr & NPCM7XX_TCSR_CACT) {
325
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: read-only bits in 0x%08x ignored\n",
326
+ __func__, new_tcsr);
327
+ new_tcsr &= ~NPCM7XX_TCSR_CACT;
328
+ }
329
+ if ((new_tcsr & NPCM7XX_TCSR_CRST) && (new_tcsr & NPCM7XX_TCSR_CEN)) {
330
+ qemu_log_mask(LOG_GUEST_ERROR,
331
+ "%s: both CRST and CEN set; ignoring CEN.\n",
332
+ __func__);
333
+ new_tcsr &= ~NPCM7XX_TCSR_CEN;
334
+ }
335
+
336
+ /* Calculate the value of TDR before potentially changing the prescaler. */
337
+ tdr = npcm7xx_timer_read_tdr(t);
338
+
339
+ t->tcsr = (t->tcsr & NPCM7XX_TCSR_CACT) | new_tcsr;
340
+
341
+ if (npcm7xx_tcsr_prescaler(old_tcsr) != npcm7xx_tcsr_prescaler(new_tcsr)) {
342
+ /* Recalculate time remaining based on the current TDR value. */
343
+ t->remaining_ns = npcm7xx_timer_count_to_ns(t, tdr);
344
+ if (old_tcsr & t->tcsr & NPCM7XX_TCSR_CEN) {
345
+ npcm7xx_timer_start(t);
346
+ }
347
+ }
348
+
349
+ if ((old_tcsr ^ new_tcsr) & NPCM7XX_TCSR_IE) {
350
+ npcm7xx_timer_check_interrupt(t);
351
+ }
352
+ if (new_tcsr & NPCM7XX_TCSR_CRST) {
353
+ npcm7xx_timer_restart(t, old_tcsr);
354
+ t->tcsr &= ~NPCM7XX_TCSR_CRST;
355
+ }
356
+ if ((old_tcsr ^ new_tcsr) & NPCM7XX_TCSR_CEN) {
357
+ if (new_tcsr & NPCM7XX_TCSR_CEN) {
358
+ t->tcsr |= NPCM7XX_TCSR_CACT;
359
+ npcm7xx_timer_start(t);
360
+ } else {
361
+ t->tcsr &= ~NPCM7XX_TCSR_CACT;
362
+ npcm7xx_timer_pause(t);
363
+ }
364
+ }
365
+}
366
+
367
+static void npcm7xx_timer_write_ticr(NPCM7xxTimer *t, uint32_t new_ticr)
368
+{
369
+ t->ticr = new_ticr;
370
+
371
+ npcm7xx_timer_restart(t, t->tcsr);
372
+}
373
+
374
+static void npcm7xx_timer_write_tisr(NPCM7xxTimerCtrlState *s, uint32_t value)
375
+{
376
+ int i;
377
+
378
+ s->tisr &= ~value;
379
+ for (i = 0; i < ARRAY_SIZE(s->timer); i++) {
380
+ if (value & (1U << i)) {
381
+ npcm7xx_timer_check_interrupt(&s->timer[i]);
382
+ }
383
+ }
384
+}
385
+
386
+static hwaddr npcm7xx_tcsr_index(hwaddr reg)
387
+{
388
+ switch (reg) {
389
+ case NPCM7XX_TIMER_TCSR0:
390
+ return 0;
391
+ case NPCM7XX_TIMER_TCSR1:
392
+ return 1;
393
+ case NPCM7XX_TIMER_TCSR2:
394
+ return 2;
395
+ case NPCM7XX_TIMER_TCSR3:
396
+ return 3;
397
+ case NPCM7XX_TIMER_TCSR4:
398
+ return 4;
399
+ default:
400
+ g_assert_not_reached();
401
+ }
402
+}
403
+
404
+static hwaddr npcm7xx_ticr_index(hwaddr reg)
405
+{
406
+ switch (reg) {
407
+ case NPCM7XX_TIMER_TICR0:
408
+ return 0;
409
+ case NPCM7XX_TIMER_TICR1:
410
+ return 1;
411
+ case NPCM7XX_TIMER_TICR2:
412
+ return 2;
413
+ case NPCM7XX_TIMER_TICR3:
414
+ return 3;
415
+ case NPCM7XX_TIMER_TICR4:
416
+ return 4;
417
+ default:
418
+ g_assert_not_reached();
419
+ }
420
+}
421
+
422
+static hwaddr npcm7xx_tdr_index(hwaddr reg)
423
+{
424
+ switch (reg) {
425
+ case NPCM7XX_TIMER_TDR0:
426
+ return 0;
427
+ case NPCM7XX_TIMER_TDR1:
428
+ return 1;
429
+ case NPCM7XX_TIMER_TDR2:
430
+ return 2;
431
+ case NPCM7XX_TIMER_TDR3:
432
+ return 3;
433
+ case NPCM7XX_TIMER_TDR4:
434
+ return 4;
435
+ default:
436
+ g_assert_not_reached();
437
+ }
438
+}
439
+
440
+static uint64_t npcm7xx_timer_read(void *opaque, hwaddr offset, unsigned size)
441
+{
442
+ NPCM7xxTimerCtrlState *s = opaque;
443
+ uint64_t value = 0;
444
+ hwaddr reg;
445
+
446
+ reg = offset / sizeof(uint32_t);
447
+ switch (reg) {
448
+ case NPCM7XX_TIMER_TCSR0:
449
+ case NPCM7XX_TIMER_TCSR1:
450
+ case NPCM7XX_TIMER_TCSR2:
451
+ case NPCM7XX_TIMER_TCSR3:
452
+ case NPCM7XX_TIMER_TCSR4:
453
+ value = s->timer[npcm7xx_tcsr_index(reg)].tcsr;
454
+ break;
455
+
456
+ case NPCM7XX_TIMER_TICR0:
457
+ case NPCM7XX_TIMER_TICR1:
458
+ case NPCM7XX_TIMER_TICR2:
459
+ case NPCM7XX_TIMER_TICR3:
460
+ case NPCM7XX_TIMER_TICR4:
461
+ value = s->timer[npcm7xx_ticr_index(reg)].ticr;
462
+ break;
463
+
464
+ case NPCM7XX_TIMER_TDR0:
465
+ case NPCM7XX_TIMER_TDR1:
466
+ case NPCM7XX_TIMER_TDR2:
467
+ case NPCM7XX_TIMER_TDR3:
468
+ case NPCM7XX_TIMER_TDR4:
469
+ value = npcm7xx_timer_read_tdr(&s->timer[npcm7xx_tdr_index(reg)]);
470
+ break;
471
+
472
+ case NPCM7XX_TIMER_TISR:
473
+ value = s->tisr;
474
+ break;
475
+
476
+ case NPCM7XX_TIMER_WTCR:
477
+ value = s->wtcr;
478
+ break;
479
+
480
+ default:
481
+ qemu_log_mask(LOG_GUEST_ERROR,
482
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
483
+ __func__, offset);
484
+ break;
485
+ }
486
+
487
+ trace_npcm7xx_timer_read(DEVICE(s)->canonical_path, offset, value);
488
+
489
+ return value;
490
+}
491
+
492
+static void npcm7xx_timer_write(void *opaque, hwaddr offset,
493
+ uint64_t v, unsigned size)
494
+{
495
+ uint32_t reg = offset / sizeof(uint32_t);
496
+ NPCM7xxTimerCtrlState *s = opaque;
497
+ uint32_t value = v;
498
+
499
+ trace_npcm7xx_timer_write(DEVICE(s)->canonical_path, offset, value);
500
+
501
+ switch (reg) {
502
+ case NPCM7XX_TIMER_TCSR0:
503
+ case NPCM7XX_TIMER_TCSR1:
504
+ case NPCM7XX_TIMER_TCSR2:
505
+ case NPCM7XX_TIMER_TCSR3:
506
+ case NPCM7XX_TIMER_TCSR4:
507
+ npcm7xx_timer_write_tcsr(&s->timer[npcm7xx_tcsr_index(reg)], value);
508
+ return;
509
+
510
+ case NPCM7XX_TIMER_TICR0:
511
+ case NPCM7XX_TIMER_TICR1:
512
+ case NPCM7XX_TIMER_TICR2:
513
+ case NPCM7XX_TIMER_TICR3:
514
+ case NPCM7XX_TIMER_TICR4:
515
+ npcm7xx_timer_write_ticr(&s->timer[npcm7xx_ticr_index(reg)], value);
516
+ return;
517
+
518
+ case NPCM7XX_TIMER_TDR0:
519
+ case NPCM7XX_TIMER_TDR1:
520
+ case NPCM7XX_TIMER_TDR2:
521
+ case NPCM7XX_TIMER_TDR3:
522
+ case NPCM7XX_TIMER_TDR4:
523
+ qemu_log_mask(LOG_GUEST_ERROR,
524
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
525
+ __func__, offset);
526
+ return;
527
+
528
+ case NPCM7XX_TIMER_TISR:
529
+ npcm7xx_timer_write_tisr(s, value);
530
+ return;
531
+
532
+ case NPCM7XX_TIMER_WTCR:
533
+ qemu_log_mask(LOG_UNIMP, "%s: WTCR write not implemented: 0x%08x\n",
534
+ __func__, value);
535
+ return;
536
+ }
537
+
538
+ qemu_log_mask(LOG_GUEST_ERROR,
539
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
540
+ __func__, offset);
541
+}
542
+
543
+static const struct MemoryRegionOps npcm7xx_timer_ops = {
544
+ .read = npcm7xx_timer_read,
545
+ .write = npcm7xx_timer_write,
546
+ .endianness = DEVICE_LITTLE_ENDIAN,
547
+ .valid = {
548
+ .min_access_size = 4,
549
+ .max_access_size = 4,
550
+ .unaligned = false,
551
+ },
552
+};
553
+
554
+/* Called when the QEMU timer expires. */
555
+static void npcm7xx_timer_expired(void *opaque)
556
+{
557
+ NPCM7xxTimer *t = opaque;
558
+
559
+ if (t->tcsr & NPCM7XX_TCSR_CEN) {
560
+ npcm7xx_timer_reached_zero(t);
561
+ }
562
+}
563
+
564
+static void npcm7xx_timer_enter_reset(Object *obj, ResetType type)
565
+{
566
+ NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(obj);
567
+ int i;
568
+
569
+ for (i = 0; i < NPCM7XX_TIMERS_PER_CTRL; i++) {
570
+ NPCM7xxTimer *t = &s->timer[i];
571
+
572
+ timer_del(&t->qtimer);
573
+ t->expires_ns = 0;
574
+ t->remaining_ns = 0;
575
+ t->tcsr = 0x00000005;
576
+ t->ticr = 0x00000000;
577
+ }
578
+
579
+ s->tisr = 0x00000000;
580
+ s->wtcr = 0x00000400;
581
+}
582
+
583
+static void npcm7xx_timer_hold_reset(Object *obj)
584
+{
585
+ NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(obj);
586
+ int i;
587
+
588
+ for (i = 0; i < NPCM7XX_TIMERS_PER_CTRL; i++) {
589
+ qemu_irq_lower(s->timer[i].irq);
590
+ }
591
+}
592
+
593
+static void npcm7xx_timer_realize(DeviceState *dev, Error **errp)
594
+{
595
+ NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(dev);
596
+ SysBusDevice *sbd = &s->parent;
597
+ int i;
598
+
599
+ for (i = 0; i < NPCM7XX_TIMERS_PER_CTRL; i++) {
600
+ NPCM7xxTimer *t = &s->timer[i];
601
+ t->ctrl = s;
602
+ timer_init_ns(&t->qtimer, QEMU_CLOCK_VIRTUAL, npcm7xx_timer_expired, t);
603
+ sysbus_init_irq(sbd, &t->irq);
604
+ }
605
+
606
+ memory_region_init_io(&s->iomem, OBJECT(s), &npcm7xx_timer_ops, s,
607
+ TYPE_NPCM7XX_TIMER, 4 * KiB);
608
+ sysbus_init_mmio(sbd, &s->iomem);
609
+}
610
+
611
+static const VMStateDescription vmstate_npcm7xx_timer = {
612
+ .name = "npcm7xx-timer",
613
+ .version_id = 0,
614
+ .minimum_version_id = 0,
615
+ .fields = (VMStateField[]) {
616
+ VMSTATE_TIMER(qtimer, NPCM7xxTimer),
617
+ VMSTATE_INT64(expires_ns, NPCM7xxTimer),
618
+ VMSTATE_INT64(remaining_ns, NPCM7xxTimer),
619
+ VMSTATE_UINT32(tcsr, NPCM7xxTimer),
620
+ VMSTATE_UINT32(ticr, NPCM7xxTimer),
621
+ VMSTATE_END_OF_LIST(),
622
+ },
623
+};
624
+
625
+static const VMStateDescription vmstate_npcm7xx_timer_ctrl = {
626
+ .name = "npcm7xx-timer-ctrl",
627
+ .version_id = 0,
628
+ .minimum_version_id = 0,
629
+ .fields = (VMStateField[]) {
630
+ VMSTATE_UINT32(tisr, NPCM7xxTimerCtrlState),
631
+ VMSTATE_UINT32(wtcr, NPCM7xxTimerCtrlState),
632
+ VMSTATE_STRUCT_ARRAY(timer, NPCM7xxTimerCtrlState,
633
+ NPCM7XX_TIMERS_PER_CTRL, 0, vmstate_npcm7xx_timer,
634
+ NPCM7xxTimer),
635
+ VMSTATE_END_OF_LIST(),
636
+ },
637
+};
638
+
639
+static void npcm7xx_timer_class_init(ObjectClass *klass, void *data)
640
+{
641
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
642
+ DeviceClass *dc = DEVICE_CLASS(klass);
643
+
644
+ QEMU_BUILD_BUG_ON(NPCM7XX_TIMER_REGS_END > NPCM7XX_TIMER_NR_REGS);
645
+
646
+ dc->desc = "NPCM7xx Timer Controller";
647
+ dc->realize = npcm7xx_timer_realize;
648
+ dc->vmsd = &vmstate_npcm7xx_timer_ctrl;
649
+ rc->phases.enter = npcm7xx_timer_enter_reset;
650
+ rc->phases.hold = npcm7xx_timer_hold_reset;
651
+}
652
+
653
+static const TypeInfo npcm7xx_timer_info = {
654
+ .name = TYPE_NPCM7XX_TIMER,
655
+ .parent = TYPE_SYS_BUS_DEVICE,
656
+ .instance_size = sizeof(NPCM7xxTimerCtrlState),
657
+ .class_init = npcm7xx_timer_class_init,
658
+};
659
+
660
+static void npcm7xx_timer_register_type(void)
661
+{
662
+ type_register_static(&npcm7xx_timer_info);
663
+}
664
+type_init(npcm7xx_timer_register_type);
665
diff --git a/hw/timer/meson.build b/hw/timer/meson.build
666
index XXXXXXX..XXXXXXX 100644
667
--- a/hw/timer/meson.build
668
+++ b/hw/timer/meson.build
669
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_LM32', if_true: files('lm32_timer.c'))
670
softmmu_ss.add(when: 'CONFIG_MILKYMIST', if_true: files('milkymist-sysctl.c'))
671
softmmu_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('mips_gictimer.c'))
672
softmmu_ss.add(when: 'CONFIG_MSF2', if_true: files('mss-timer.c'))
673
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_timer.c'))
674
softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_timer.c'))
675
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_gptimer.c'))
676
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_synctimer.c'))
677
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
678
index XXXXXXX..XXXXXXX 100644
679
--- a/hw/timer/trace-events
680
+++ b/hw/timer/trace-events
681
@@ -XXX,XX +XXX,XX @@ cmsdk_apb_dualtimer_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK A
682
cmsdk_apb_dualtimer_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB dualtimer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
683
cmsdk_apb_dualtimer_reset(void) "CMSDK APB dualtimer: reset"
684
685
+# npcm7xx_timer.c
686
+npcm7xx_timer_read(const char *id, uint64_t offset, uint64_t value) " %s offset: 0x%04" PRIx64 " value 0x%08" PRIx64
687
+npcm7xx_timer_write(const char *id, uint64_t offset, uint64_t value) "%s offset: 0x%04" PRIx64 " value 0x%08" PRIx64
688
+npcm7xx_timer_irq(const char *id, int timer, int state) "%s timer %d state %d"
689
+
690
# nrf51_timer.c
691
nrf51_timer_read(uint8_t timer_id, uint64_t addr, uint32_t value, unsigned size) "timer %u read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
692
nrf51_timer_write(uint8_t timer_id, uint64_t addr, uint32_t value, unsigned size) "timer %u write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
693
--
694
2.20.1
695
696
diff view generated by jsdifflib
Deleted patch
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
1
3
This adds two new machines, both supported by OpenBMC:
4
5
- npcm750-evb: Nuvoton NPCM750 Evaluation Board.
6
- quanta-gsj: A board with a NPCM730 chip.
7
8
They rely on the NPCM7xx SoC device to do the heavy lifting. They are
9
almost completely identical at the moment, apart from the SoC type,
10
which currently only changes the reset contents of one register
11
(GCR.MDLR), but they might grow apart a bit more as more functionality
12
is added.
13
14
Both machines can boot the Linux kernel into /bin/sh.
15
16
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
17
Reviewed-by: Joel Stanley <joel@jms.id.au>
18
Reviewed-by: Cédric Le Goater <clg@kaod.org>
19
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
21
Tested-by: Alexander Bulekov <alxndr@bu.edu>
22
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
23
Message-id: 20200911052101.2602693-6-hskinnemoen@google.com
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
---
26
default-configs/arm-softmmu.mak | 1 +
27
include/hw/arm/npcm7xx.h | 19 +++++
28
hw/arm/npcm7xx_boards.c | 145 ++++++++++++++++++++++++++++++++
29
hw/arm/meson.build | 2 +-
30
4 files changed, 166 insertions(+), 1 deletion(-)
31
create mode 100644 hw/arm/npcm7xx_boards.c
32
33
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
34
index XXXXXXX..XXXXXXX 100644
35
--- a/default-configs/arm-softmmu.mak
36
+++ b/default-configs/arm-softmmu.mak
37
@@ -XXX,XX +XXX,XX @@ CONFIG_GUMSTIX=y
38
CONFIG_SPITZ=y
39
CONFIG_TOSA=y
40
CONFIG_Z2=y
41
+CONFIG_NPCM7XX=y
42
CONFIG_COLLIE=y
43
CONFIG_ASPEED_SOC=y
44
CONFIG_NETDUINO2=y
45
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
46
index XXXXXXX..XXXXXXX 100644
47
--- a/include/hw/arm/npcm7xx.h
48
+++ b/include/hw/arm/npcm7xx.h
49
@@ -XXX,XX +XXX,XX @@
50
#define NPCM7XX_SMP_BOOTREG_ADDR (0xf080013c) /* GCR.SCRPAD */
51
#define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100) /* GIC within A9 */
52
53
+typedef struct NPCM7xxMachine {
54
+ MachineState parent;
55
+} NPCM7xxMachine;
56
+
57
+#define TYPE_NPCM7XX_MACHINE MACHINE_TYPE_NAME("npcm7xx")
58
+#define NPCM7XX_MACHINE(obj) \
59
+ OBJECT_CHECK(NPCM7xxMachine, (obj), TYPE_NPCM7XX_MACHINE)
60
+
61
+typedef struct NPCM7xxMachineClass {
62
+ MachineClass parent;
63
+
64
+ const char *soc_type;
65
+} NPCM7xxMachineClass;
66
+
67
+#define NPCM7XX_MACHINE_CLASS(klass) \
68
+ OBJECT_CLASS_CHECK(NPCM7xxMachineClass, (klass), TYPE_NPCM7XX_MACHINE)
69
+#define NPCM7XX_MACHINE_GET_CLASS(obj) \
70
+ OBJECT_GET_CLASS(NPCM7xxMachineClass, (obj), TYPE_NPCM7XX_MACHINE)
71
+
72
typedef struct NPCM7xxState {
73
DeviceState parent;
74
75
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
76
new file mode 100644
77
index XXXXXXX..XXXXXXX
78
--- /dev/null
79
+++ b/hw/arm/npcm7xx_boards.c
80
@@ -XXX,XX +XXX,XX @@
81
+/*
82
+ * Machine definitions for boards featuring an NPCM7xx SoC.
83
+ *
84
+ * Copyright 2020 Google LLC
85
+ *
86
+ * This program is free software; you can redistribute it and/or modify it
87
+ * under the terms of the GNU General Public License as published by the
88
+ * Free Software Foundation; either version 2 of the License, or
89
+ * (at your option) any later version.
90
+ *
91
+ * This program is distributed in the hope that it will be useful, but WITHOUT
92
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
93
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
94
+ * for more details.
95
+ */
96
+
97
+#include "qemu/osdep.h"
98
+
99
+#include "exec/address-spaces.h"
100
+#include "hw/arm/npcm7xx.h"
101
+#include "hw/core/cpu.h"
102
+#include "qapi/error.h"
103
+#include "qemu/units.h"
104
+
105
+#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7
106
+#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff
107
+
108
+static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
109
+{
110
+ memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, dram);
111
+
112
+ object_property_set_link(OBJECT(soc), "dram-mr", OBJECT(dram),
113
+ &error_abort);
114
+}
115
+
116
+static NPCM7xxState *npcm7xx_create_soc(MachineState *machine,
117
+ uint32_t hw_straps)
118
+{
119
+ NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_GET_CLASS(machine);
120
+ MachineClass *mc = &nmc->parent;
121
+ Object *obj;
122
+
123
+ if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
124
+ error_report("This board can only be used with %s",
125
+ mc->default_cpu_type);
126
+ exit(1);
127
+ }
128
+
129
+ obj = object_new_with_props(nmc->soc_type, OBJECT(machine), "soc",
130
+ &error_abort, NULL);
131
+ object_property_set_uint(obj, "power-on-straps", hw_straps, &error_abort);
132
+
133
+ return NPCM7XX(obj);
134
+}
135
+
136
+static void npcm750_evb_init(MachineState *machine)
137
+{
138
+ NPCM7xxState *soc;
139
+
140
+ soc = npcm7xx_create_soc(machine, NPCM750_EVB_POWER_ON_STRAPS);
141
+ npcm7xx_connect_dram(soc, machine->ram);
142
+ qdev_realize(DEVICE(soc), NULL, &error_fatal);
143
+
144
+ npcm7xx_load_kernel(machine, soc);
145
+}
146
+
147
+static void quanta_gsj_init(MachineState *machine)
148
+{
149
+ NPCM7xxState *soc;
150
+
151
+ soc = npcm7xx_create_soc(machine, QUANTA_GSJ_POWER_ON_STRAPS);
152
+ npcm7xx_connect_dram(soc, machine->ram);
153
+ qdev_realize(DEVICE(soc), NULL, &error_fatal);
154
+
155
+ npcm7xx_load_kernel(machine, soc);
156
+}
157
+
158
+static void npcm7xx_set_soc_type(NPCM7xxMachineClass *nmc, const char *type)
159
+{
160
+ NPCM7xxClass *sc = NPCM7XX_CLASS(object_class_by_name(type));
161
+ MachineClass *mc = MACHINE_CLASS(nmc);
162
+
163
+ nmc->soc_type = type;
164
+ mc->default_cpus = mc->min_cpus = mc->max_cpus = sc->num_cpus;
165
+}
166
+
167
+static void npcm7xx_machine_class_init(ObjectClass *oc, void *data)
168
+{
169
+ MachineClass *mc = MACHINE_CLASS(oc);
170
+
171
+ mc->no_floppy = 1;
172
+ mc->no_cdrom = 1;
173
+ mc->no_parallel = 1;
174
+ mc->default_ram_id = "ram";
175
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a9");
176
+}
177
+
178
+/*
179
+ * Schematics:
180
+ * https://github.com/Nuvoton-Israel/nuvoton-info/blob/master/npcm7xx-poleg/evaluation-board/board_deliverables/NPCM750x_EB_ver.A1.1_COMPLETE.pdf
181
+ */
182
+static void npcm750_evb_machine_class_init(ObjectClass *oc, void *data)
183
+{
184
+ NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_CLASS(oc);
185
+ MachineClass *mc = MACHINE_CLASS(oc);
186
+
187
+ npcm7xx_set_soc_type(nmc, TYPE_NPCM750);
188
+
189
+ mc->desc = "Nuvoton NPCM750 Evaluation Board (Cortex A9)";
190
+ mc->init = npcm750_evb_init;
191
+ mc->default_ram_size = 512 * MiB;
192
+};
193
+
194
+static void gsj_machine_class_init(ObjectClass *oc, void *data)
195
+{
196
+ NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_CLASS(oc);
197
+ MachineClass *mc = MACHINE_CLASS(oc);
198
+
199
+ npcm7xx_set_soc_type(nmc, TYPE_NPCM730);
200
+
201
+ mc->desc = "Quanta GSJ (Cortex A9)";
202
+ mc->init = quanta_gsj_init;
203
+ mc->default_ram_size = 512 * MiB;
204
+};
205
+
206
+static const TypeInfo npcm7xx_machine_types[] = {
207
+ {
208
+ .name = TYPE_NPCM7XX_MACHINE,
209
+ .parent = TYPE_MACHINE,
210
+ .instance_size = sizeof(NPCM7xxMachine),
211
+ .class_size = sizeof(NPCM7xxMachineClass),
212
+ .class_init = npcm7xx_machine_class_init,
213
+ .abstract = true,
214
+ }, {
215
+ .name = MACHINE_TYPE_NAME("npcm750-evb"),
216
+ .parent = TYPE_NPCM7XX_MACHINE,
217
+ .class_init = npcm750_evb_machine_class_init,
218
+ }, {
219
+ .name = MACHINE_TYPE_NAME("quanta-gsj"),
220
+ .parent = TYPE_NPCM7XX_MACHINE,
221
+ .class_init = gsj_machine_class_init,
222
+ },
223
+};
224
+
225
+DEFINE_TYPES(npcm7xx_machine_types)
226
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
227
index XXXXXXX..XXXXXXX 100644
228
--- a/hw/arm/meson.build
229
+++ b/hw/arm/meson.build
230
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'CONFIG_MICROBIT', if_true: files('microbit.c'))
231
arm_ss.add(when: 'CONFIG_MUSICPAL', if_true: files('musicpal.c'))
232
arm_ss.add(when: 'CONFIG_NETDUINO2', if_true: files('netduino2.c'))
233
arm_ss.add(when: 'CONFIG_NETDUINOPLUS2', if_true: files('netduinoplus2.c'))
234
-arm_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx.c'))
235
+arm_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx.c', 'npcm7xx_boards.c'))
236
arm_ss.add(when: 'CONFIG_NSERIES', if_true: files('nseries.c'))
237
arm_ss.add(when: 'CONFIG_SX1', if_true: files('omap_sx1.c'))
238
arm_ss.add(when: 'CONFIG_CHEETAH', if_true: files('palm.c'))
239
--
240
2.20.1
241
242
diff view generated by jsdifflib
Deleted patch
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
1
3
This is a minimalistic boot ROM written specifically for use with QEMU.
4
It supports loading the second-stage loader from SPI flash into RAM, SMP
5
boot, and not much else.
6
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
10
Message-id: 20200911052101.2602693-7-hskinnemoen@google.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
.gitmodules | 3 +++
14
MAINTAINERS | 2 ++
15
pc-bios/README | 6 ++++++
16
pc-bios/meson.build | 1 +
17
pc-bios/npcm7xx_bootrom.bin | Bin 0 -> 768 bytes
18
roms/Makefile | 7 +++++++
19
roms/vbootrom | 1 +
20
7 files changed, 20 insertions(+)
21
create mode 100644 pc-bios/npcm7xx_bootrom.bin
22
create mode 160000 roms/vbootrom
23
24
diff --git a/.gitmodules b/.gitmodules
25
index XXXXXXX..XXXXXXX 100644
26
--- a/.gitmodules
27
+++ b/.gitmodules
28
@@ -XXX,XX +XXX,XX @@
29
[submodule "meson"]
30
    path = meson
31
    url = https://github.com/mesonbuild/meson/
32
+[submodule "roms/vbootrom"]
33
+    path = roms/vbootrom
34
+    url = https://github.com/google/vbootrom.git
35
diff --git a/MAINTAINERS b/MAINTAINERS
36
index XXXXXXX..XXXXXXX 100644
37
--- a/MAINTAINERS
38
+++ b/MAINTAINERS
39
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
40
S: Supported
41
F: hw/*/npcm7xx*
42
F: include/hw/*/npcm7xx*
43
+F: pc-bios/npcm7xx_bootrom.bin
44
+F: roms/vbootrom
45
46
nSeries
47
M: Andrzej Zaborowski <balrogg@gmail.com>
48
diff --git a/pc-bios/README b/pc-bios/README
49
index XXXXXXX..XXXXXXX 100644
50
--- a/pc-bios/README
51
+++ b/pc-bios/README
52
@@ -XXX,XX +XXX,XX @@
53
("Simplified BSD License" or "FreeBSD License", SPDX: BSD-2-Clause). OpenSBI
54
source code also contains code reused from other projects desribed here:
55
https://github.com/riscv/opensbi/blob/master/ThirdPartyNotices.md.
56
+
57
+- npcm7xx_bootrom.bin is a simplified, free (Apache 2.0) boot ROM for Nuvoton
58
+ NPCM7xx BMC devices. It currently implements the bare minimum to load, parse,
59
+ initialize and run boot images stored in SPI flash, but may grow more
60
+ features over time as needed. The source code is available at:
61
+ https://github.com/google/vbootrom
62
diff --git a/pc-bios/meson.build b/pc-bios/meson.build
63
index XXXXXXX..XXXXXXX 100644
64
--- a/pc-bios/meson.build
65
+++ b/pc-bios/meson.build
66
@@ -XXX,XX +XXX,XX @@ blobs = files(
67
'opensbi-riscv64-generic-fw_dynamic.bin',
68
'opensbi-riscv32-generic-fw_dynamic.elf',
69
'opensbi-riscv64-generic-fw_dynamic.elf',
70
+ 'npcm7xx_bootrom.bin',
71
)
72
73
if install_blobs
74
diff --git a/pc-bios/npcm7xx_bootrom.bin b/pc-bios/npcm7xx_bootrom.bin
75
new file mode 100644
76
index XXXXXXX..XXXXXXX
77
GIT binary patch
78
literal 768
79
zcmd5)JxClu6n-<aczPbVhZYusb8wKx;7TklHfmuZdYT9pDRLwd1p_t-DFpWpyA+8(
80
zwKtZg3J4a0aCM3_X(ZL&4g;46VVk5e$K;z;L99|b@aE%v^S$rQ8)h(Vm@cB9IYc+2
81
z2SHd4^NwTIGE%w>9S05p1#kf90Sj5Z(jG8}+)IZIp~iXK=T&)dL`%d-q*8aR#mq{7
82
z9`=6;Dr(H0ACe72R5x?!)^86Qj-X%{+!K9iZNA@*wkBAV&iZ(l^I9?!Gz=S2I_*1d
83
zr+tTQDHjvyzKnw(hu00yX`u!Fv<!~XVcX?@kr#<B0(gGU?$W{gSsQa}CF^8Cfzp2X
84
z@P}yDV-bci(K9XL$FU!som2C`c)?Uc&294s^}Wzumap{hg1X^jN|V25M5tQZ=<9lN
85
z%(zKz#t-qCwHKb;HygOCpvCNL_4@1tXV1YGf^XUE_$zr{g8zWh-6gz-teI(eibtxo
86
z?0OZI4%rU0741PgUD`2xq@H|*4=+Rs?%N)Ox5G+q>C;DilBe_YlkeSUVHA-crNk+k
87
jtiF_MudA<CB(}8|fqYwCf3re&=&@_s761P#-ID$TwgmBa
88
89
literal 0
90
HcmV?d00001
91
92
diff --git a/roms/Makefile b/roms/Makefile
93
index XXXXXXX..XXXXXXX 100644
94
--- a/roms/Makefile
95
+++ b/roms/Makefile
96
@@ -XXX,XX +XXX,XX @@ find-cross-gcc = $(firstword $(wildcard $(patsubst %ld,%gcc,$(call find-cross-ld
97
# finally strip off path + toolname so we get the prefix
98
find-cross-prefix = $(subst gcc,,$(notdir $(call find-cross-gcc,$(1))))
99
100
+arm_cross_prefix := $(call find-cross-prefix,arm)
101
powerpc64_cross_prefix := $(call find-cross-prefix,powerpc64)
102
powerpc_cross_prefix := $(call find-cross-prefix,powerpc)
103
x86_64_cross_prefix := $(call find-cross-prefix,x86_64)
104
@@ -XXX,XX +XXX,XX @@ default help:
105
    @echo " skiboot -- update skiboot.lid"
106
    @echo " u-boot.e500 -- update u-boot.e500"
107
    @echo " u-boot.sam460 -- update u-boot.sam460"
108
+    @echo " npcm7xx_bootrom -- update vbootrom for npcm7xx"
109
    @echo " efi -- update UEFI (edk2) platform firmware"
110
    @echo " opensbi32-generic -- update OpenSBI for 32-bit generic machine"
111
    @echo " opensbi64-generic -- update OpenSBI for 64-bit generic machine"
112
@@ -XXX,XX +XXX,XX @@ bios-microvm:
113
    $(MAKE) -C qboot
114
    cp qboot/bios.bin ../pc-bios/bios-microvm.bin
115
116
+npcm7xx_bootrom:
117
+    $(MAKE) -C vbootrom CROSS_COMPILE=$(arm_cross_prefix)
118
+    cp vbootrom/npcm7xx_bootrom.bin ../pc-bios/npcm7xx_bootrom.bin
119
+
120
clean:
121
    rm -rf seabios/.config seabios/out seabios/builds
122
    $(MAKE) -C sgabios clean
123
@@ -XXX,XX +XXX,XX @@ clean:
124
    $(MAKE) -f Makefile.edk2 clean
125
    $(MAKE) -C opensbi clean
126
    $(MAKE) -C qboot clean
127
+    $(MAKE) -C vbootrom clean
128
diff --git a/roms/vbootrom b/roms/vbootrom
129
new file mode 160000
130
index XXXXXXX..XXXXXXX
131
--- /dev/null
132
+++ b/roms/vbootrom
133
@@ -0,0 +1 @@
134
+Subproject commit 0c37a43527f0ee2b9584e7fb2fdc805e902635ac
135
--
136
2.20.1
137
138
diff view generated by jsdifflib