1
Arm queue; not huge but I figured I might as well send it out since
1
The following changes since commit 8f6330a807f2642dc2a3cdf33347aa28a4c00a87:
2
I've been doing code review today and there's no queue of unprocessed
3
pullreqs...
4
2
5
thanks
3
Merge tag 'pull-maintainer-updates-060324-1' of https://gitlab.com/stsquad/qemu into staging (2024-03-06 16:56:20 +0000)
6
-- PMM
7
8
The following changes since commit b3f846c59d8405bb87c551187721fc92ff2f1b92:
9
10
Merge remote-tracking branch 'remotes/huth-gitlab/tags/pull-request-2021-01-11v2' into staging (2021-01-11 15:15:35 +0000)
11
4
12
are available in the Git repository at:
5
are available in the Git repository at:
13
6
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210112
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20240308
15
8
16
for you to fetch changes up to 19d131395ccaf503db21dadd8257e6dc9fc1d7de:
9
for you to fetch changes up to bbf6c6dbead82292a20951eb1204442a6b838de9:
17
10
18
ui/cocoa: Fix openFile: deprecation on Big Sur (2021-01-12 11:38:37 +0000)
11
target/arm: Move v7m-related code from cpu32.c into a separate file (2024-03-08 14:45:03 +0000)
19
12
20
----------------------------------------------------------------
13
----------------------------------------------------------------
21
target-arm queue:
14
target-arm queue:
22
* arm: Support emulation of ARMv8.4-TTST extension
15
* Implement FEAT_ECV
23
* arm: Update cpu.h ID register field definitions
16
* STM32L4x5: Implement GPIO device
24
* arm: Fix breakage of XScale instruction emulation
17
* Fix 32-bit SMOPA
25
* hw/net/lan9118: Fix RX Status FIFO PEEK value
18
* Refactor v7m related code from cpu32.c into its own file
26
* npcm7xx: Add ADC and PWM emulation
19
* hw/rtc/sun4v-rtc: Relicense to GPLv2-or-later
27
* ui/cocoa: Make "open docs" help menu entry work again when binary
28
is run from the build tree
29
* ui/cocoa: Fix openFile: deprecation on Big Sur
30
* docs: Add qemu-storage-daemon(1) manpage to meson.build
31
* docs: Build and install all the docs in a single manual
32
20
33
----------------------------------------------------------------
21
----------------------------------------------------------------
34
Hao Wu (6):
22
Inès Varhol (3):
35
hw/misc: Add clock converter in NPCM7XX CLK module
23
hw/gpio: Implement STM32L4x5 GPIO
36
hw/timer: Refactor NPCM7XX Timer to use CLK clock
24
hw/arm: Connect STM32L4x5 GPIO to STM32L4x5 SoC
37
hw/adc: Add an ADC module for NPCM7XX
25
tests/qtest: Add STM32L4x5 GPIO QTest testcase
38
hw/misc: Add a PWM module for NPCM7XX
39
hw/misc: Add QTest for NPCM7XX PWM Module
40
hw/*: Use type casting for SysBusDevice in NPCM7XX
41
26
42
Leif Lindholm (6):
27
Peter Maydell (9):
43
target/arm: fix typo in cpu.h ID_AA64PFR1 field name
28
target/arm: Move some register related defines to internals.h
44
target/arm: make ARMCPU.clidr 64-bit
29
target/arm: Timer _EL02 registers UNDEF for E2H == 0
45
target/arm: make ARMCPU.ctr 64-bit
30
target/arm: use FIELD macro for CNTHCTL bit definitions
46
target/arm: add descriptions of CLIDR_EL1, CCSIDR_EL1, CTR_EL0 to cpu.h
31
target/arm: Don't allow RES0 CNTHCTL_EL2 bits to be written
47
target/arm: add aarch64 ID register fields to cpu.h
32
target/arm: Implement new FEAT_ECV trap bits
48
target/arm: add aarch32 ID register fields to cpu.h
33
target/arm: Define CNTPCTSS_EL0 and CNTVCTSS_EL0
34
target/arm: Implement FEAT_ECV CNTPOFF_EL2 handling
35
target/arm: Enable FEAT_ECV for 'max' CPU
36
hw/rtc/sun4v-rtc: Relicense to GPLv2-or-later
49
37
50
Peter Maydell (5):
38
Richard Henderson (1):
51
docs: Add qemu-storage-daemon(1) manpage to meson.build
39
target/arm: Fix 32-bit SMOPA
52
docs: Build and install all the docs in a single manual
53
target/arm: Don't decode insns in the XScale/iWMMXt space as cp insns
54
hw/net/lan9118: Fix RX Status FIFO PEEK value
55
hw/net/lan9118: Add symbolic constants for register offsets
56
40
57
Roman Bolshakov (2):
41
Thomas Huth (1):
58
ui/cocoa: Update path to docs in build tree
42
target/arm: Move v7m-related code from cpu32.c into a separate file
59
ui/cocoa: Fix openFile: deprecation on Big Sur
60
43
61
Rémi Denis-Courmont (2):
44
MAINTAINERS | 1 +
62
target/arm: ARMv8.4-TTST extension
45
docs/system/arm/b-l475e-iot01a.rst | 2 +-
63
target/arm: enable Small Translation tables in max CPU
46
docs/system/arm/emulation.rst | 1 +
47
include/hw/arm/stm32l4x5_soc.h | 2 +
48
include/hw/gpio/stm32l4x5_gpio.h | 71 +++++
49
include/hw/misc/stm32l4x5_syscfg.h | 3 +-
50
include/hw/rtc/sun4v-rtc.h | 2 +-
51
target/arm/cpu-features.h | 10 +
52
target/arm/cpu.h | 129 +--------
53
target/arm/internals.h | 151 ++++++++++
54
hw/arm/stm32l4x5_soc.c | 71 ++++-
55
hw/gpio/stm32l4x5_gpio.c | 477 ++++++++++++++++++++++++++++++++
56
hw/misc/stm32l4x5_syscfg.c | 1 +
57
hw/rtc/sun4v-rtc.c | 2 +-
58
target/arm/helper.c | 189 ++++++++++++-
59
target/arm/tcg/cpu-v7m.c | 290 +++++++++++++++++++
60
target/arm/tcg/cpu32.c | 261 ------------------
61
target/arm/tcg/cpu64.c | 1 +
62
target/arm/tcg/sme_helper.c | 77 +++---
63
tests/qtest/stm32l4x5_gpio-test.c | 551 +++++++++++++++++++++++++++++++++++++
64
tests/tcg/aarch64/sme-smopa-1.c | 47 ++++
65
tests/tcg/aarch64/sme-smopa-2.c | 54 ++++
66
hw/arm/Kconfig | 3 +-
67
hw/gpio/Kconfig | 3 +
68
hw/gpio/meson.build | 1 +
69
hw/gpio/trace-events | 6 +
70
target/arm/meson.build | 3 +
71
target/arm/tcg/meson.build | 3 +
72
target/arm/trace-events | 1 +
73
tests/qtest/meson.build | 3 +-
74
tests/tcg/aarch64/Makefile.target | 2 +-
75
31 files changed, 1962 insertions(+), 456 deletions(-)
76
create mode 100644 include/hw/gpio/stm32l4x5_gpio.h
77
create mode 100644 hw/gpio/stm32l4x5_gpio.c
78
create mode 100644 target/arm/tcg/cpu-v7m.c
79
create mode 100644 tests/qtest/stm32l4x5_gpio-test.c
80
create mode 100644 tests/tcg/aarch64/sme-smopa-1.c
81
create mode 100644 tests/tcg/aarch64/sme-smopa-2.c
64
82
65
docs/conf.py | 46 ++-
66
docs/devel/conf.py | 15 -
67
docs/index.html.in | 17 -
68
docs/interop/conf.py | 28 --
69
docs/meson.build | 65 ++--
70
docs/specs/conf.py | 16 -
71
docs/system/arm/nuvoton.rst | 4 +-
72
docs/system/conf.py | 28 --
73
docs/tools/conf.py | 37 --
74
docs/user/conf.py | 15 -
75
meson.build | 1 +
76
hw/adc/trace.h | 1 +
77
include/hw/adc/npcm7xx_adc.h | 69 ++++
78
include/hw/arm/npcm7xx.h | 4 +
79
include/hw/misc/npcm7xx_clk.h | 146 ++++++-
80
include/hw/misc/npcm7xx_pwm.h | 105 +++++
81
include/hw/timer/npcm7xx_timer.h | 1 +
82
target/arm/cpu.h | 85 ++++-
83
hw/adc/npcm7xx_adc.c | 301 +++++++++++++++
84
hw/arm/npcm7xx.c | 55 ++-
85
hw/arm/npcm7xx_boards.c | 2 +-
86
hw/mem/npcm7xx_mc.c | 2 +-
87
hw/misc/npcm7xx_clk.c | 807 ++++++++++++++++++++++++++++++++++++++-
88
hw/misc/npcm7xx_gcr.c | 2 +-
89
hw/misc/npcm7xx_pwm.c | 550 ++++++++++++++++++++++++++
90
hw/misc/npcm7xx_rng.c | 2 +-
91
hw/net/lan9118.c | 26 +-
92
hw/nvram/npcm7xx_otp.c | 2 +-
93
hw/ssi/npcm7xx_fiu.c | 2 +-
94
hw/timer/npcm7xx_timer.c | 39 +-
95
target/arm/cpu64.c | 1 +
96
target/arm/helper.c | 15 +-
97
target/arm/translate.c | 7 +
98
tests/qtest/npcm7xx_adc-test.c | 377 ++++++++++++++++++
99
tests/qtest/npcm7xx_pwm-test.c | 490 ++++++++++++++++++++++++
100
hw/adc/meson.build | 1 +
101
hw/adc/trace-events | 5 +
102
hw/misc/meson.build | 1 +
103
hw/misc/trace-events | 6 +
104
tests/qtest/meson.build | 4 +-
105
ui/cocoa.m | 7 +-
106
41 files changed, 3124 insertions(+), 263 deletions(-)
107
delete mode 100644 docs/devel/conf.py
108
delete mode 100644 docs/index.html.in
109
delete mode 100644 docs/interop/conf.py
110
delete mode 100644 docs/specs/conf.py
111
delete mode 100644 docs/system/conf.py
112
delete mode 100644 docs/tools/conf.py
113
delete mode 100644 docs/user/conf.py
114
create mode 100644 hw/adc/trace.h
115
create mode 100644 include/hw/adc/npcm7xx_adc.h
116
create mode 100644 include/hw/misc/npcm7xx_pwm.h
117
create mode 100644 hw/adc/npcm7xx_adc.c
118
create mode 100644 hw/misc/npcm7xx_pwm.c
119
create mode 100644 tests/qtest/npcm7xx_adc-test.c
120
create mode 100644 tests/qtest/npcm7xx_pwm-test.c
121
create mode 100644 hw/adc/trace-events
122
diff view generated by jsdifflib
1
From: Leif Lindholm <leif@nuviainc.com>
1
cpu.h has a lot of #defines relating to CPU register fields.
2
Most of these aren't actually used outside target/arm code,
3
so there's no point in cluttering up the cpu.h file with them.
4
Move some easy ones to internals.h.
2
5
3
Add entries present in ARM DDI 0487F.c (August 2020).
4
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
8
Message-id: 20210108185154.8108-7-leif@nuviainc.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20240301183219.2424889-2-peter.maydell@linaro.org
10
---
10
---
11
target/arm/cpu.h | 28 ++++++++++++++++++++++++++++
11
target/arm/cpu.h | 128 -----------------------------------------
12
1 file changed, 28 insertions(+)
12
target/arm/internals.h | 128 +++++++++++++++++++++++++++++++++++++++++
13
2 files changed, 128 insertions(+), 128 deletions(-)
13
14
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
17
--- a/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
18
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@ FIELD(ID_ISAR6, DP, 4, 4)
19
@@ -XXX,XX +XXX,XX @@ typedef struct ARMGenericTimer {
19
FIELD(ID_ISAR6, FHM, 8, 4)
20
uint64_t ctl; /* Timer Control register */
20
FIELD(ID_ISAR6, SB, 12, 4)
21
} ARMGenericTimer;
21
FIELD(ID_ISAR6, SPECRES, 16, 4)
22
22
+FIELD(ID_ISAR6, BF16, 20, 4)
23
-#define VTCR_NSW (1u << 29)
23
+FIELD(ID_ISAR6, I8MM, 24, 4)
24
-#define VTCR_NSA (1u << 30)
24
25
-#define VSTCR_SW VTCR_NSW
25
FIELD(ID_MMFR0, VMSA, 0, 4)
26
-#define VSTCR_SA VTCR_NSA
26
FIELD(ID_MMFR0, PMSA, 4, 4)
27
-
27
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR0, AUXREG, 20, 4)
28
/* Define a maximum sized vector register.
28
FIELD(ID_MMFR0, FCSE, 24, 4)
29
* For 32-bit, this is a 128-bit NEON/AdvSIMD register.
29
FIELD(ID_MMFR0, INNERSHR, 28, 4)
30
* For 64-bit, this is a 2048-bit SVE register.
30
31
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
31
+FIELD(ID_MMFR1, L1HVDVA, 0, 4)
32
#define SCTLR_SPINTMASK (1ULL << 62) /* FEAT_NMI */
32
+FIELD(ID_MMFR1, L1UNIVA, 4, 4)
33
#define SCTLR_TIDCP (1ULL << 63) /* FEAT_TIDCP1 */
33
+FIELD(ID_MMFR1, L1HVDSW, 8, 4)
34
34
+FIELD(ID_MMFR1, L1UNISW, 12, 4)
35
-/* Bit definitions for CPACR (AArch32 only) */
35
+FIELD(ID_MMFR1, L1HVD, 16, 4)
36
-FIELD(CPACR, CP10, 20, 2)
36
+FIELD(ID_MMFR1, L1UNI, 20, 4)
37
-FIELD(CPACR, CP11, 22, 2)
37
+FIELD(ID_MMFR1, L1TSTCLN, 24, 4)
38
-FIELD(CPACR, TRCDIS, 28, 1) /* matches CPACR_EL1.TTA */
38
+FIELD(ID_MMFR1, BPRED, 28, 4)
39
-FIELD(CPACR, D32DIS, 30, 1) /* up to v7; RAZ in v8 */
39
+
40
-FIELD(CPACR, ASEDIS, 31, 1)
40
+FIELD(ID_MMFR2, L1HVDFG, 0, 4)
41
-
41
+FIELD(ID_MMFR2, L1HVDBG, 4, 4)
42
-/* Bit definitions for CPACR_EL1 (AArch64 only) */
42
+FIELD(ID_MMFR2, L1HVDRNG, 8, 4)
43
-FIELD(CPACR_EL1, ZEN, 16, 2)
43
+FIELD(ID_MMFR2, HVDTLB, 12, 4)
44
-FIELD(CPACR_EL1, FPEN, 20, 2)
44
+FIELD(ID_MMFR2, UNITLB, 16, 4)
45
-FIELD(CPACR_EL1, SMEN, 24, 2)
45
+FIELD(ID_MMFR2, MEMBARR, 20, 4)
46
-FIELD(CPACR_EL1, TTA, 28, 1) /* matches CPACR.TRCDIS */
46
+FIELD(ID_MMFR2, WFISTALL, 24, 4)
47
-
47
+FIELD(ID_MMFR2, HWACCFLG, 28, 4)
48
-/* Bit definitions for HCPTR (AArch32 only) */
48
+
49
-FIELD(HCPTR, TCP10, 10, 1)
49
FIELD(ID_MMFR3, CMAINTVA, 0, 4)
50
-FIELD(HCPTR, TCP11, 11, 1)
50
FIELD(ID_MMFR3, CMAINTSW, 4, 4)
51
-FIELD(HCPTR, TASE, 15, 1)
51
FIELD(ID_MMFR3, BPMAINT, 8, 4)
52
-FIELD(HCPTR, TTA, 20, 1)
52
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR4, LSM, 20, 4)
53
-FIELD(HCPTR, TAM, 30, 1) /* matches CPTR_EL2.TAM */
53
FIELD(ID_MMFR4, CCIDX, 24, 4)
54
-FIELD(HCPTR, TCPAC, 31, 1) /* matches CPTR_EL2.TCPAC */
54
FIELD(ID_MMFR4, EVT, 28, 4)
55
-
55
56
-/* Bit definitions for CPTR_EL2 (AArch64 only) */
56
+FIELD(ID_MMFR5, ETS, 0, 4)
57
-FIELD(CPTR_EL2, TZ, 8, 1) /* !E2H */
57
+
58
-FIELD(CPTR_EL2, TFP, 10, 1) /* !E2H, matches HCPTR.TCP10 */
58
FIELD(ID_PFR0, STATE0, 0, 4)
59
-FIELD(CPTR_EL2, TSM, 12, 1) /* !E2H */
59
FIELD(ID_PFR0, STATE1, 4, 4)
60
-FIELD(CPTR_EL2, ZEN, 16, 2) /* E2H */
60
FIELD(ID_PFR0, STATE2, 8, 4)
61
-FIELD(CPTR_EL2, FPEN, 20, 2) /* E2H */
61
@@ -XXX,XX +XXX,XX @@ FIELD(ID_PFR1, SEC_FRAC, 20, 4)
62
-FIELD(CPTR_EL2, SMEN, 24, 2) /* E2H */
62
FIELD(ID_PFR1, VIRT_FRAC, 24, 4)
63
-FIELD(CPTR_EL2, TTA, 28, 1)
63
FIELD(ID_PFR1, GIC, 28, 4)
64
-FIELD(CPTR_EL2, TAM, 30, 1) /* matches HCPTR.TAM */
64
65
-FIELD(CPTR_EL2, TCPAC, 31, 1) /* matches HCPTR.TCPAC */
65
+FIELD(ID_PFR2, CSV3, 0, 4)
66
-
66
+FIELD(ID_PFR2, SSBS, 4, 4)
67
-/* Bit definitions for CPTR_EL3 (AArch64 only) */
67
+FIELD(ID_PFR2, RAS_FRAC, 8, 4)
68
-FIELD(CPTR_EL3, EZ, 8, 1)
68
+
69
-FIELD(CPTR_EL3, TFP, 10, 1)
69
FIELD(ID_AA64ISAR0, AES, 4, 4)
70
-FIELD(CPTR_EL3, ESM, 12, 1)
70
FIELD(ID_AA64ISAR0, SHA1, 8, 4)
71
-FIELD(CPTR_EL3, TTA, 20, 1)
71
FIELD(ID_AA64ISAR0, SHA2, 12, 4)
72
-FIELD(CPTR_EL3, TAM, 30, 1)
72
@@ -XXX,XX +XXX,XX @@ FIELD(ID_DFR0, MPROFDBG, 20, 4)
73
-FIELD(CPTR_EL3, TCPAC, 31, 1)
73
FIELD(ID_DFR0, PERFMON, 24, 4)
74
-
74
FIELD(ID_DFR0, TRACEFILT, 28, 4)
75
-#define MDCR_MTPME (1U << 28)
75
76
-#define MDCR_TDCC (1U << 27)
76
+FIELD(ID_DFR1, MTPMU, 0, 4)
77
-#define MDCR_HLP (1U << 26) /* MDCR_EL2 */
77
+
78
-#define MDCR_SCCD (1U << 23) /* MDCR_EL3 */
78
FIELD(DBGDIDR, SE_IMP, 12, 1)
79
-#define MDCR_HCCD (1U << 23) /* MDCR_EL2 */
79
FIELD(DBGDIDR, NSUHD_IMP, 14, 1)
80
-#define MDCR_EPMAD (1U << 21)
80
FIELD(DBGDIDR, VERSION, 16, 4)
81
-#define MDCR_EDAD (1U << 20)
82
-#define MDCR_TTRF (1U << 19)
83
-#define MDCR_STE (1U << 18) /* MDCR_EL3 */
84
-#define MDCR_SPME (1U << 17) /* MDCR_EL3 */
85
-#define MDCR_HPMD (1U << 17) /* MDCR_EL2 */
86
-#define MDCR_SDD (1U << 16)
87
-#define MDCR_SPD (3U << 14)
88
-#define MDCR_TDRA (1U << 11)
89
-#define MDCR_TDOSA (1U << 10)
90
-#define MDCR_TDA (1U << 9)
91
-#define MDCR_TDE (1U << 8)
92
-#define MDCR_HPME (1U << 7)
93
-#define MDCR_TPM (1U << 6)
94
-#define MDCR_TPMCR (1U << 5)
95
-#define MDCR_HPMN (0x1fU)
96
-
97
-/* Not all of the MDCR_EL3 bits are present in the 32-bit SDCR */
98
-#define SDCR_VALID_MASK (MDCR_MTPME | MDCR_TDCC | MDCR_SCCD | \
99
- MDCR_EPMAD | MDCR_EDAD | MDCR_TTRF | \
100
- MDCR_STE | MDCR_SPME | MDCR_SPD)
101
-
102
#define CPSR_M (0x1fU)
103
#define CPSR_T (1U << 5)
104
#define CPSR_F (1U << 6)
105
@@ -XXX,XX +XXX,XX @@ FIELD(CPTR_EL3, TCPAC, 31, 1)
106
#define XPSR_NZCV CPSR_NZCV
107
#define XPSR_IT CPSR_IT
108
109
-#define TTBCR_N (7U << 0) /* TTBCR.EAE==0 */
110
-#define TTBCR_T0SZ (7U << 0) /* TTBCR.EAE==1 */
111
-#define TTBCR_PD0 (1U << 4)
112
-#define TTBCR_PD1 (1U << 5)
113
-#define TTBCR_EPD0 (1U << 7)
114
-#define TTBCR_IRGN0 (3U << 8)
115
-#define TTBCR_ORGN0 (3U << 10)
116
-#define TTBCR_SH0 (3U << 12)
117
-#define TTBCR_T1SZ (3U << 16)
118
-#define TTBCR_A1 (1U << 22)
119
-#define TTBCR_EPD1 (1U << 23)
120
-#define TTBCR_IRGN1 (3U << 24)
121
-#define TTBCR_ORGN1 (3U << 26)
122
-#define TTBCR_SH1 (1U << 28)
123
-#define TTBCR_EAE (1U << 31)
124
-
125
-FIELD(VTCR, T0SZ, 0, 6)
126
-FIELD(VTCR, SL0, 6, 2)
127
-FIELD(VTCR, IRGN0, 8, 2)
128
-FIELD(VTCR, ORGN0, 10, 2)
129
-FIELD(VTCR, SH0, 12, 2)
130
-FIELD(VTCR, TG0, 14, 2)
131
-FIELD(VTCR, PS, 16, 3)
132
-FIELD(VTCR, VS, 19, 1)
133
-FIELD(VTCR, HA, 21, 1)
134
-FIELD(VTCR, HD, 22, 1)
135
-FIELD(VTCR, HWU59, 25, 1)
136
-FIELD(VTCR, HWU60, 26, 1)
137
-FIELD(VTCR, HWU61, 27, 1)
138
-FIELD(VTCR, HWU62, 28, 1)
139
-FIELD(VTCR, NSW, 29, 1)
140
-FIELD(VTCR, NSA, 30, 1)
141
-FIELD(VTCR, DS, 32, 1)
142
-FIELD(VTCR, SL2, 33, 1)
143
-
144
/* Bit definitions for ARMv8 SPSR (PSTATE) format.
145
* Only these are valid when in AArch64 mode; in
146
* AArch32 mode SPSRs are basically CPSR-format.
147
@@ -XXX,XX +XXX,XX @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
148
#define HCR_TWEDEN (1ULL << 59)
149
#define HCR_TWEDEL MAKE_64BIT_MASK(60, 4)
150
151
-#define HCRX_ENAS0 (1ULL << 0)
152
-#define HCRX_ENALS (1ULL << 1)
153
-#define HCRX_ENASR (1ULL << 2)
154
-#define HCRX_FNXS (1ULL << 3)
155
-#define HCRX_FGTNXS (1ULL << 4)
156
-#define HCRX_SMPME (1ULL << 5)
157
-#define HCRX_TALLINT (1ULL << 6)
158
-#define HCRX_VINMI (1ULL << 7)
159
-#define HCRX_VFNMI (1ULL << 8)
160
-#define HCRX_CMOW (1ULL << 9)
161
-#define HCRX_MCE2 (1ULL << 10)
162
-#define HCRX_MSCEN (1ULL << 11)
163
-
164
-#define HPFAR_NS (1ULL << 63)
165
-
166
#define SCR_NS (1ULL << 0)
167
#define SCR_IRQ (1ULL << 1)
168
#define SCR_FIQ (1ULL << 2)
169
@@ -XXX,XX +XXX,XX @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
170
#define SCR_GPF (1ULL << 48)
171
#define SCR_NSE (1ULL << 62)
172
173
-#define HSTR_TTEE (1 << 16)
174
-#define HSTR_TJDBX (1 << 17)
175
-
176
-#define CNTHCTL_CNTVMASK (1 << 18)
177
-#define CNTHCTL_CNTPMASK (1 << 19)
178
-
179
/* Return the current FPSCR value. */
180
uint32_t vfp_get_fpscr(CPUARMState *env);
181
void vfp_set_fpscr(CPUARMState *env, uint32_t val);
182
diff --git a/target/arm/internals.h b/target/arm/internals.h
183
index XXXXXXX..XXXXXXX 100644
184
--- a/target/arm/internals.h
185
+++ b/target/arm/internals.h
186
@@ -XXX,XX +XXX,XX @@ FIELD(DBGWCR, WT, 20, 1)
187
FIELD(DBGWCR, MASK, 24, 5)
188
FIELD(DBGWCR, SSCE, 29, 1)
189
190
+#define VTCR_NSW (1u << 29)
191
+#define VTCR_NSA (1u << 30)
192
+#define VSTCR_SW VTCR_NSW
193
+#define VSTCR_SA VTCR_NSA
194
+
195
+/* Bit definitions for CPACR (AArch32 only) */
196
+FIELD(CPACR, CP10, 20, 2)
197
+FIELD(CPACR, CP11, 22, 2)
198
+FIELD(CPACR, TRCDIS, 28, 1) /* matches CPACR_EL1.TTA */
199
+FIELD(CPACR, D32DIS, 30, 1) /* up to v7; RAZ in v8 */
200
+FIELD(CPACR, ASEDIS, 31, 1)
201
+
202
+/* Bit definitions for CPACR_EL1 (AArch64 only) */
203
+FIELD(CPACR_EL1, ZEN, 16, 2)
204
+FIELD(CPACR_EL1, FPEN, 20, 2)
205
+FIELD(CPACR_EL1, SMEN, 24, 2)
206
+FIELD(CPACR_EL1, TTA, 28, 1) /* matches CPACR.TRCDIS */
207
+
208
+/* Bit definitions for HCPTR (AArch32 only) */
209
+FIELD(HCPTR, TCP10, 10, 1)
210
+FIELD(HCPTR, TCP11, 11, 1)
211
+FIELD(HCPTR, TASE, 15, 1)
212
+FIELD(HCPTR, TTA, 20, 1)
213
+FIELD(HCPTR, TAM, 30, 1) /* matches CPTR_EL2.TAM */
214
+FIELD(HCPTR, TCPAC, 31, 1) /* matches CPTR_EL2.TCPAC */
215
+
216
+/* Bit definitions for CPTR_EL2 (AArch64 only) */
217
+FIELD(CPTR_EL2, TZ, 8, 1) /* !E2H */
218
+FIELD(CPTR_EL2, TFP, 10, 1) /* !E2H, matches HCPTR.TCP10 */
219
+FIELD(CPTR_EL2, TSM, 12, 1) /* !E2H */
220
+FIELD(CPTR_EL2, ZEN, 16, 2) /* E2H */
221
+FIELD(CPTR_EL2, FPEN, 20, 2) /* E2H */
222
+FIELD(CPTR_EL2, SMEN, 24, 2) /* E2H */
223
+FIELD(CPTR_EL2, TTA, 28, 1)
224
+FIELD(CPTR_EL2, TAM, 30, 1) /* matches HCPTR.TAM */
225
+FIELD(CPTR_EL2, TCPAC, 31, 1) /* matches HCPTR.TCPAC */
226
+
227
+/* Bit definitions for CPTR_EL3 (AArch64 only) */
228
+FIELD(CPTR_EL3, EZ, 8, 1)
229
+FIELD(CPTR_EL3, TFP, 10, 1)
230
+FIELD(CPTR_EL3, ESM, 12, 1)
231
+FIELD(CPTR_EL3, TTA, 20, 1)
232
+FIELD(CPTR_EL3, TAM, 30, 1)
233
+FIELD(CPTR_EL3, TCPAC, 31, 1)
234
+
235
+#define MDCR_MTPME (1U << 28)
236
+#define MDCR_TDCC (1U << 27)
237
+#define MDCR_HLP (1U << 26) /* MDCR_EL2 */
238
+#define MDCR_SCCD (1U << 23) /* MDCR_EL3 */
239
+#define MDCR_HCCD (1U << 23) /* MDCR_EL2 */
240
+#define MDCR_EPMAD (1U << 21)
241
+#define MDCR_EDAD (1U << 20)
242
+#define MDCR_TTRF (1U << 19)
243
+#define MDCR_STE (1U << 18) /* MDCR_EL3 */
244
+#define MDCR_SPME (1U << 17) /* MDCR_EL3 */
245
+#define MDCR_HPMD (1U << 17) /* MDCR_EL2 */
246
+#define MDCR_SDD (1U << 16)
247
+#define MDCR_SPD (3U << 14)
248
+#define MDCR_TDRA (1U << 11)
249
+#define MDCR_TDOSA (1U << 10)
250
+#define MDCR_TDA (1U << 9)
251
+#define MDCR_TDE (1U << 8)
252
+#define MDCR_HPME (1U << 7)
253
+#define MDCR_TPM (1U << 6)
254
+#define MDCR_TPMCR (1U << 5)
255
+#define MDCR_HPMN (0x1fU)
256
+
257
+/* Not all of the MDCR_EL3 bits are present in the 32-bit SDCR */
258
+#define SDCR_VALID_MASK (MDCR_MTPME | MDCR_TDCC | MDCR_SCCD | \
259
+ MDCR_EPMAD | MDCR_EDAD | MDCR_TTRF | \
260
+ MDCR_STE | MDCR_SPME | MDCR_SPD)
261
+
262
+#define TTBCR_N (7U << 0) /* TTBCR.EAE==0 */
263
+#define TTBCR_T0SZ (7U << 0) /* TTBCR.EAE==1 */
264
+#define TTBCR_PD0 (1U << 4)
265
+#define TTBCR_PD1 (1U << 5)
266
+#define TTBCR_EPD0 (1U << 7)
267
+#define TTBCR_IRGN0 (3U << 8)
268
+#define TTBCR_ORGN0 (3U << 10)
269
+#define TTBCR_SH0 (3U << 12)
270
+#define TTBCR_T1SZ (3U << 16)
271
+#define TTBCR_A1 (1U << 22)
272
+#define TTBCR_EPD1 (1U << 23)
273
+#define TTBCR_IRGN1 (3U << 24)
274
+#define TTBCR_ORGN1 (3U << 26)
275
+#define TTBCR_SH1 (1U << 28)
276
+#define TTBCR_EAE (1U << 31)
277
+
278
+FIELD(VTCR, T0SZ, 0, 6)
279
+FIELD(VTCR, SL0, 6, 2)
280
+FIELD(VTCR, IRGN0, 8, 2)
281
+FIELD(VTCR, ORGN0, 10, 2)
282
+FIELD(VTCR, SH0, 12, 2)
283
+FIELD(VTCR, TG0, 14, 2)
284
+FIELD(VTCR, PS, 16, 3)
285
+FIELD(VTCR, VS, 19, 1)
286
+FIELD(VTCR, HA, 21, 1)
287
+FIELD(VTCR, HD, 22, 1)
288
+FIELD(VTCR, HWU59, 25, 1)
289
+FIELD(VTCR, HWU60, 26, 1)
290
+FIELD(VTCR, HWU61, 27, 1)
291
+FIELD(VTCR, HWU62, 28, 1)
292
+FIELD(VTCR, NSW, 29, 1)
293
+FIELD(VTCR, NSA, 30, 1)
294
+FIELD(VTCR, DS, 32, 1)
295
+FIELD(VTCR, SL2, 33, 1)
296
+
297
+#define HCRX_ENAS0 (1ULL << 0)
298
+#define HCRX_ENALS (1ULL << 1)
299
+#define HCRX_ENASR (1ULL << 2)
300
+#define HCRX_FNXS (1ULL << 3)
301
+#define HCRX_FGTNXS (1ULL << 4)
302
+#define HCRX_SMPME (1ULL << 5)
303
+#define HCRX_TALLINT (1ULL << 6)
304
+#define HCRX_VINMI (1ULL << 7)
305
+#define HCRX_VFNMI (1ULL << 8)
306
+#define HCRX_CMOW (1ULL << 9)
307
+#define HCRX_MCE2 (1ULL << 10)
308
+#define HCRX_MSCEN (1ULL << 11)
309
+
310
+#define HPFAR_NS (1ULL << 63)
311
+
312
+#define HSTR_TTEE (1 << 16)
313
+#define HSTR_TJDBX (1 << 17)
314
+
315
+#define CNTHCTL_CNTVMASK (1 << 18)
316
+#define CNTHCTL_CNTPMASK (1 << 19)
317
+
318
/* We use a few fake FSR values for internal purposes in M profile.
319
* M profile cores don't have A/R format FSRs, but currently our
320
* get_phys_addr() code assumes A/R profile and reports failures via
81
--
321
--
82
2.20.1
322
2.34.1
83
323
84
324
diff view generated by jsdifflib
1
A copy-and-paste error meant that the return value for register offset 0x44
1
The timer _EL02 registers should UNDEF for invalid accesses from EL2
2
(the RX Status FIFO PEEK register) returned a byte from a bogus offset in
2
or EL3 when HCR_EL2.E2H == 0, not take a cp access trap. We were
3
the rx status FIFO. Fix the typo.
3
delivering the exception to EL2 with the wrong syndrome.
4
4
5
Cc: qemu-stable@nongnu.org
6
Fixes: https://bugs.launchpad.net/qemu/+bug/1904954
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210108180401.2263-2-peter.maydell@linaro.org
7
Message-id: 20240301183219.2424889-3-peter.maydell@linaro.org
10
---
8
---
11
hw/net/lan9118.c | 2 +-
9
target/arm/helper.c | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
10
1 file changed, 1 insertion(+), 1 deletion(-)
13
11
14
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/net/lan9118.c
14
--- a/target/arm/helper.c
17
+++ b/hw/net/lan9118.c
15
+++ b/target/arm/helper.c
18
@@ -XXX,XX +XXX,XX @@ static uint64_t lan9118_readl(void *opaque, hwaddr offset,
16
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
19
case 0x40:
17
return CP_ACCESS_OK;
20
return rx_status_fifo_pop(s);
18
}
21
case 0x44:
19
if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
22
- return s->rx_status_fifo[s->tx_status_fifo_head];
20
- return CP_ACCESS_TRAP;
23
+ return s->rx_status_fifo[s->rx_status_fifo_head];
21
+ return CP_ACCESS_TRAP_UNCATEGORIZED;
24
case 0x48:
22
}
25
return tx_status_fifo_pop(s);
23
return CP_ACCESS_OK;
26
case 0x4c:
24
}
27
--
25
--
28
2.20.1
26
2.34.1
29
30
diff view generated by jsdifflib
1
When we first converted our documentation to Sphinx, we split it into
1
We prefer the FIELD macro over ad-hoc #defines for register bits;
2
multiple manuals (system, interop, tools, etc), which are all built
2
switch CNTHCTL to that style before we add any more bits.
3
separately. The primary driver for this was wanting to be able to
4
avoid shipping the 'devel' manual to end-users. However, this is
5
working against the grain of the way Sphinx wants to be used and
6
causes some annoyances:
7
* Cross-references between documents become much harder or
8
possibly impossible
9
* There is no single index to the whole documentation
10
* Within one manual there's no links or table-of-contents info
11
that lets you easily navigate to the others
12
* The devel manual doesn't get published on the QEMU website
13
(it would be nice to able to refer to it there)
14
15
Merely hiding our developer documentation from end users seems like
16
it's not enough benefit for these costs. Combine all the
17
documentation into a single manual (the same way that the readthedocs
18
site builds it) and install the whole thing. The previous manual
19
divisions remain as the new top level sections in the manual.
20
21
* The per-manual conf.py files are no longer needed
22
* The man_pages[] specifications previously in each per-manual
23
conf.py move to the top level conf.py
24
* docs/meson.build logic is simplified as we now only need to run
25
Sphinx once for the HTML and then once for the manpages5B
26
* The old index.html.in that produced the top-level page with
27
links to each manual is no longer needed
28
29
Unfortunately this means that we now have to build the HTML
30
documentation into docs/manual in the build tree rather than directly
31
into docs/; otherwise it is too awkward to ensure we install only the
32
built manual and not also the dependency info, stamp file, etc. The
33
manual still ends up in the same place in the final installed
34
directory, but anybody who was consulting documentation from within
35
the build tree will have to adjust where they're looking.
36
3
37
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
38
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
39
Message-id: 20210108161416.21129-3-peter.maydell@linaro.org
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20240301183219.2424889-4-peter.maydell@linaro.org
40
---
8
---
41
docs/conf.py | 46 ++++++++++++++++++++++++++++++-
9
target/arm/internals.h | 27 +++++++++++++++++++++++++--
42
docs/devel/conf.py | 15 -----------
10
target/arm/helper.c | 9 ++++-----
43
docs/index.html.in | 17 ------------
11
2 files changed, 29 insertions(+), 7 deletions(-)
44
docs/interop/conf.py | 28 -------------------
45
docs/meson.build | 64 +++++++++++++++++---------------------------
46
docs/specs/conf.py | 16 -----------
47
docs/system/conf.py | 28 -------------------
48
docs/tools/conf.py | 37 -------------------------
49
docs/user/conf.py | 15 -----------
50
9 files changed, 70 insertions(+), 196 deletions(-)
51
delete mode 100644 docs/devel/conf.py
52
delete mode 100644 docs/index.html.in
53
delete mode 100644 docs/interop/conf.py
54
delete mode 100644 docs/specs/conf.py
55
delete mode 100644 docs/system/conf.py
56
delete mode 100644 docs/tools/conf.py
57
delete mode 100644 docs/user/conf.py
58
12
59
diff --git a/docs/conf.py b/docs/conf.py
13
diff --git a/target/arm/internals.h b/target/arm/internals.h
60
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
61
--- a/docs/conf.py
15
--- a/target/arm/internals.h
62
+++ b/docs/conf.py
16
+++ b/target/arm/internals.h
63
@@ -XXX,XX +XXX,XX @@ latex_documents = [
17
@@ -XXX,XX +XXX,XX @@ FIELD(VTCR, SL2, 33, 1)
64
18
#define HSTR_TTEE (1 << 16)
65
# -- Options for manual page output ---------------------------------------
19
#define HSTR_TJDBX (1 << 17)
66
# Individual manual/conf.py can override this to create man pages
20
67
-man_pages = []
21
-#define CNTHCTL_CNTVMASK (1 << 18)
68
+man_pages = [
22
-#define CNTHCTL_CNTPMASK (1 << 19)
69
+ ('interop/qemu-ga', 'qemu-ga',
23
+/*
70
+ 'QEMU Guest Agent',
24
+ * Depending on the value of HCR_EL2.E2H, bits 0 and 1
71
+ ['Michael Roth <mdroth@linux.vnet.ibm.com>'], 8),
25
+ * have different bit definitions, and EL1PCTEN might be
72
+ ('interop/qemu-ga-ref', 'qemu-ga-ref',
26
+ * bit 0 or bit 10. We use _E2H1 and _E2H0 suffixes to
73
+ 'QEMU Guest Agent Protocol Reference',
27
+ * disambiguate if necessary.
74
+ [], 7),
28
+ */
75
+ ('interop/qemu-qmp-ref', 'qemu-qmp-ref',
29
+FIELD(CNTHCTL, EL0PCTEN_E2H1, 0, 1)
76
+ 'QEMU QMP Reference Manual',
30
+FIELD(CNTHCTL, EL0VCTEN_E2H1, 1, 1)
77
+ [], 7),
31
+FIELD(CNTHCTL, EL1PCTEN_E2H0, 0, 1)
78
+ ('interop/qemu-storage-daemon-qmp-ref', 'qemu-storage-daemon-qmp-ref',
32
+FIELD(CNTHCTL, EL1PCEN_E2H0, 1, 1)
79
+ 'QEMU Storage Daemon QMP Reference Manual',
33
+FIELD(CNTHCTL, EVNTEN, 2, 1)
80
+ [], 7),
34
+FIELD(CNTHCTL, EVNTDIR, 3, 1)
81
+ ('system/qemu-manpage', 'qemu',
35
+FIELD(CNTHCTL, EVNTI, 4, 4)
82
+ 'QEMU User Documentation',
36
+FIELD(CNTHCTL, EL0VTEN, 8, 1)
83
+ ['Fabrice Bellard'], 1),
37
+FIELD(CNTHCTL, EL0PTEN, 9, 1)
84
+ ('system/qemu-block-drivers', 'qemu-block-drivers',
38
+FIELD(CNTHCTL, EL1PCTEN_E2H1, 10, 1)
85
+ 'QEMU block drivers reference',
39
+FIELD(CNTHCTL, EL1PTEN, 11, 1)
86
+ ['Fabrice Bellard and the QEMU Project developers'], 7),
40
+FIELD(CNTHCTL, ECV, 12, 1)
87
+ ('system/qemu-cpu-models', 'qemu-cpu-models',
41
+FIELD(CNTHCTL, EL1TVT, 13, 1)
88
+ 'QEMU CPU Models',
42
+FIELD(CNTHCTL, EL1TVCT, 14, 1)
89
+ ['The QEMU Project developers'], 7),
43
+FIELD(CNTHCTL, EL1NVPCT, 15, 1)
90
+ ('tools/qemu-img', 'qemu-img',
44
+FIELD(CNTHCTL, EL1NVVCT, 16, 1)
91
+ 'QEMU disk image utility',
45
+FIELD(CNTHCTL, EVNTIS, 17, 1)
92
+ ['Fabrice Bellard'], 1),
46
+FIELD(CNTHCTL, CNTVMASK, 18, 1)
93
+ ('tools/qemu-nbd', 'qemu-nbd',
47
+FIELD(CNTHCTL, CNTPMASK, 19, 1)
94
+ 'QEMU Disk Network Block Device Server',
48
95
+ ['Anthony Liguori <anthony@codemonkey.ws>'], 8),
49
/* We use a few fake FSR values for internal purposes in M profile.
96
+ ('tools/qemu-pr-helper', 'qemu-pr-helper',
50
* M profile cores don't have A/R format FSRs, but currently our
97
+ 'QEMU persistent reservation helper',
51
diff --git a/target/arm/helper.c b/target/arm/helper.c
98
+ [], 8),
52
index XXXXXXX..XXXXXXX 100644
99
+ ('tools/qemu-storage-daemon', 'qemu-storage-daemon',
53
--- a/target/arm/helper.c
100
+ 'QEMU storage daemon',
54
+++ b/target/arm/helper.c
101
+ [], 1),
55
@@ -XXX,XX +XXX,XX @@ static void gt_update_irq(ARMCPU *cpu, int timeridx)
102
+ ('tools/qemu-trace-stap', 'qemu-trace-stap',
56
* It is RES0 in Secure and NonSecure state.
103
+ 'QEMU SystemTap trace tool',
57
*/
104
+ [], 1),
58
if ((ss == ARMSS_Root || ss == ARMSS_Realm) &&
105
+ ('tools/virtfs-proxy-helper', 'virtfs-proxy-helper',
59
- ((timeridx == GTIMER_VIRT && (cnthctl & CNTHCTL_CNTVMASK)) ||
106
+ 'QEMU 9p virtfs proxy filesystem helper',
60
- (timeridx == GTIMER_PHYS && (cnthctl & CNTHCTL_CNTPMASK)))) {
107
+ ['M. Mohan Kumar'], 1),
61
+ ((timeridx == GTIMER_VIRT && (cnthctl & R_CNTHCTL_CNTVMASK_MASK)) ||
108
+ ('tools/virtiofsd', 'virtiofsd',
62
+ (timeridx == GTIMER_PHYS && (cnthctl & R_CNTHCTL_CNTPMASK_MASK)))) {
109
+ 'QEMU virtio-fs shared file system daemon',
63
irqstate = 0;
110
+ ['Stefan Hajnoczi <stefanha@redhat.com>',
64
}
111
+ 'Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>'], 1),
65
112
+]
66
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
113
67
{
114
# -- Options for Texinfo output -------------------------------------------
68
ARMCPU *cpu = env_archcpu(env);
115
69
uint32_t oldval = env->cp15.cnthctl_el2;
116
diff --git a/docs/devel/conf.py b/docs/devel/conf.py
117
deleted file mode 100644
118
index XXXXXXX..XXXXXXX
119
--- a/docs/devel/conf.py
120
+++ /dev/null
121
@@ -XXX,XX +XXX,XX @@
122
-# -*- coding: utf-8 -*-
123
-#
124
-# QEMU documentation build configuration file for the 'devel' manual.
125
-#
126
-# This includes the top level conf file and then makes any necessary tweaks.
127
-import sys
128
-import os
129
-
70
-
130
-qemu_docdir = os.path.abspath("..")
71
raw_write(env, ri, value);
131
-parent_config = os.path.join(qemu_docdir, "conf.py")
72
132
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
73
- if ((oldval ^ value) & CNTHCTL_CNTVMASK) {
133
-
74
+ if ((oldval ^ value) & R_CNTHCTL_CNTVMASK_MASK) {
134
-# This slightly misuses the 'description', but is the best way to get
75
gt_update_irq(cpu, GTIMER_VIRT);
135
-# the manual title to appear in the sidebar.
76
- } else if ((oldval ^ value) & CNTHCTL_CNTPMASK) {
136
-html_theme_options['description'] = u'Developer''s Guide'
77
+ } else if ((oldval ^ value) & R_CNTHCTL_CNTPMASK_MASK) {
137
diff --git a/docs/index.html.in b/docs/index.html.in
78
gt_update_irq(cpu, GTIMER_PHYS);
138
deleted file mode 100644
79
}
139
index XXXXXXX..XXXXXXX
80
}
140
--- a/docs/index.html.in
141
+++ /dev/null
142
@@ -XXX,XX +XXX,XX @@
143
-<!DOCTYPE html>
144
-<html lang="en">
145
- <head>
146
- <meta charset="UTF-8">
147
- <title>QEMU @VERSION@ Documentation</title>
148
- </head>
149
- <body>
150
- <h1>QEMU @VERSION@ Documentation</h1>
151
- <ul>
152
- <li><a href="system/index.html">System Emulation User's Guide</a></li>
153
- <li><a href="user/index.html">User Mode Emulation User's Guide</a></li>
154
- <li><a href="tools/index.html">Tools Guide</a></li>
155
- <li><a href="interop/index.html">System Emulation Management and Interoperability Guide</a></li>
156
- <li><a href="specs/index.html">System Emulation Guest Hardware Specifications</a></li>
157
- </ul>
158
- </body>
159
-</html>
160
diff --git a/docs/interop/conf.py b/docs/interop/conf.py
161
deleted file mode 100644
162
index XXXXXXX..XXXXXXX
163
--- a/docs/interop/conf.py
164
+++ /dev/null
165
@@ -XXX,XX +XXX,XX @@
166
-# -*- coding: utf-8 -*-
167
-#
168
-# QEMU documentation build configuration file for the 'interop' manual.
169
-#
170
-# This includes the top level conf file and then makes any necessary tweaks.
171
-import sys
172
-import os
173
-
174
-qemu_docdir = os.path.abspath("..")
175
-parent_config = os.path.join(qemu_docdir, "conf.py")
176
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
177
-
178
-# This slightly misuses the 'description', but is the best way to get
179
-# the manual title to appear in the sidebar.
180
-html_theme_options['description'] = u'System Emulation Management and Interoperability Guide'
181
-
182
-# One entry per manual page. List of tuples
183
-# (source start file, name, description, authors, manual section).
184
-man_pages = [
185
- ('qemu-ga', 'qemu-ga', u'QEMU Guest Agent',
186
- ['Michael Roth <mdroth@linux.vnet.ibm.com>'], 8),
187
- ('qemu-ga-ref', 'qemu-ga-ref', 'QEMU Guest Agent Protocol Reference',
188
- [], 7),
189
- ('qemu-qmp-ref', 'qemu-qmp-ref', 'QEMU QMP Reference Manual',
190
- [], 7),
191
- ('qemu-storage-daemon-qmp-ref', 'qemu-storage-daemon-qmp-ref',
192
- 'QEMU Storage Daemon QMP Reference Manual', [], 7),
193
-]
194
diff --git a/docs/meson.build b/docs/meson.build
195
index XXXXXXX..XXXXXXX 100644
196
--- a/docs/meson.build
197
+++ b/docs/meson.build
198
@@ -XXX,XX +XXX,XX @@ if build_docs
199
meson.source_root() / 'docs/sphinx/qmp_lexer.py',
200
qapi_gen_depends ]
201
202
- configure_file(output: 'index.html',
203
- input: files('index.html.in'),
204
- configuration: {'VERSION': meson.project_version()},
205
- install_dir: qemu_docdir)
206
- manuals = [ 'devel', 'interop', 'tools', 'specs', 'system', 'user' ]
207
man_pages = {
208
- 'interop' : {
209
'qemu-ga.8': (have_tools ? 'man8' : ''),
210
'qemu-ga-ref.7': 'man7',
211
'qemu-qmp-ref.7': 'man7',
212
'qemu-storage-daemon-qmp-ref.7': (have_tools ? 'man7' : ''),
213
- },
214
- 'tools': {
215
'qemu-img.1': (have_tools ? 'man1' : ''),
216
'qemu-nbd.8': (have_tools ? 'man8' : ''),
217
'qemu-pr-helper.8': (have_tools ? 'man8' : ''),
218
@@ -XXX,XX +XXX,XX @@ if build_docs
219
'qemu-trace-stap.1': (config_host.has_key('CONFIG_TRACE_SYSTEMTAP') ? 'man1' : ''),
220
'virtfs-proxy-helper.1': (have_virtfs_proxy_helper ? 'man1' : ''),
221
'virtiofsd.1': (have_virtiofsd ? 'man1' : ''),
222
- },
223
- 'system': {
224
'qemu.1': 'man1',
225
'qemu-block-drivers.7': 'man7',
226
'qemu-cpu-models.7': 'man7'
227
- },
228
}
229
230
sphinxdocs = []
231
sphinxmans = []
232
- foreach manual : manuals
233
- private_dir = meson.current_build_dir() / (manual + '.p')
234
- output_dir = meson.current_build_dir() / manual
235
- input_dir = meson.current_source_dir() / manual
236
237
- this_manual = custom_target(manual + ' manual',
238
+ private_dir = meson.current_build_dir() / 'manual.p'
239
+ output_dir = meson.current_build_dir() / 'manual'
240
+ input_dir = meson.current_source_dir()
241
+
242
+ this_manual = custom_target('QEMU manual',
243
build_by_default: build_docs,
244
- output: [manual + '.stamp'],
245
- input: [files('conf.py'), files(manual / 'conf.py')],
246
- depfile: manual + '.d',
247
+ output: 'docs.stamp',
248
+ input: files('conf.py'),
249
+ depfile: 'docs.d',
250
depend_files: sphinx_extn_depends,
251
command: [SPHINX_ARGS, '-Ddepfile=@DEPFILE@',
252
'-Ddepfile_stamp=@OUTPUT0@',
253
'-b', 'html', '-d', private_dir,
254
input_dir, output_dir])
255
- sphinxdocs += this_manual
256
- if build_docs and manual != 'devel'
257
- install_subdir(output_dir, install_dir: qemu_docdir)
258
- endif
259
+ sphinxdocs += this_manual
260
+ install_subdir(output_dir, install_dir: qemu_docdir, strip_directory: true)
261
262
- these_man_pages = []
263
- install_dirs = []
264
- foreach page, section : man_pages.get(manual, {})
265
- these_man_pages += page
266
- install_dirs += section == '' ? false : get_option('mandir') / section
267
- endforeach
268
- if these_man_pages.length() > 0
269
- sphinxmans += custom_target(manual + ' man pages',
270
- build_by_default: build_docs,
271
- output: these_man_pages,
272
- input: this_manual,
273
- install: build_docs,
274
- install_dir: install_dirs,
275
- command: [SPHINX_ARGS, '-b', 'man', '-d', private_dir,
276
- input_dir, meson.current_build_dir()])
277
- endif
278
+ these_man_pages = []
279
+ install_dirs = []
280
+ foreach page, section : man_pages
281
+ these_man_pages += page
282
+ install_dirs += section == '' ? false : get_option('mandir') / section
283
endforeach
284
+
285
+ sphinxmans += custom_target('QEMU man pages',
286
+ build_by_default: build_docs,
287
+ output: these_man_pages,
288
+ input: this_manual,
289
+ install: build_docs,
290
+ install_dir: install_dirs,
291
+ command: [SPHINX_ARGS, '-b', 'man', '-d', private_dir,
292
+ input_dir, meson.current_build_dir()])
293
+
294
alias_target('sphinxdocs', sphinxdocs)
295
alias_target('html', sphinxdocs)
296
alias_target('man', sphinxmans)
297
diff --git a/docs/specs/conf.py b/docs/specs/conf.py
298
deleted file mode 100644
299
index XXXXXXX..XXXXXXX
300
--- a/docs/specs/conf.py
301
+++ /dev/null
302
@@ -XXX,XX +XXX,XX @@
303
-# -*- coding: utf-8 -*-
304
-#
305
-# QEMU documentation build configuration file for the 'specs' manual.
306
-#
307
-# This includes the top level conf file and then makes any necessary tweaks.
308
-import sys
309
-import os
310
-
311
-qemu_docdir = os.path.abspath("..")
312
-parent_config = os.path.join(qemu_docdir, "conf.py")
313
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
314
-
315
-# This slightly misuses the 'description', but is the best way to get
316
-# the manual title to appear in the sidebar.
317
-html_theme_options['description'] = \
318
- u'System Emulation Guest Hardware Specifications'
319
diff --git a/docs/system/conf.py b/docs/system/conf.py
320
deleted file mode 100644
321
index XXXXXXX..XXXXXXX
322
--- a/docs/system/conf.py
323
+++ /dev/null
324
@@ -XXX,XX +XXX,XX @@
325
-# -*- coding: utf-8 -*-
326
-#
327
-# QEMU documentation build configuration file for the 'system' manual.
328
-#
329
-# This includes the top level conf file and then makes any necessary tweaks.
330
-import sys
331
-import os
332
-
333
-qemu_docdir = os.path.abspath("..")
334
-parent_config = os.path.join(qemu_docdir, "conf.py")
335
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
336
-
337
-# This slightly misuses the 'description', but is the best way to get
338
-# the manual title to appear in the sidebar.
339
-html_theme_options['description'] = u'System Emulation User''s Guide'
340
-
341
-# One entry per manual page. List of tuples
342
-# (source start file, name, description, authors, manual section).
343
-man_pages = [
344
- ('qemu-manpage', 'qemu', u'QEMU User Documentation',
345
- ['Fabrice Bellard'], 1),
346
- ('qemu-block-drivers', 'qemu-block-drivers',
347
- u'QEMU block drivers reference',
348
- ['Fabrice Bellard and the QEMU Project developers'], 7),
349
- ('qemu-cpu-models', 'qemu-cpu-models',
350
- u'QEMU CPU Models',
351
- ['The QEMU Project developers'], 7)
352
-]
353
diff --git a/docs/tools/conf.py b/docs/tools/conf.py
354
deleted file mode 100644
355
index XXXXXXX..XXXXXXX
356
--- a/docs/tools/conf.py
357
+++ /dev/null
358
@@ -XXX,XX +XXX,XX @@
359
-# -*- coding: utf-8 -*-
360
-#
361
-# QEMU documentation build configuration file for the 'tools' manual.
362
-#
363
-# This includes the top level conf file and then makes any necessary tweaks.
364
-import sys
365
-import os
366
-
367
-qemu_docdir = os.path.abspath("..")
368
-parent_config = os.path.join(qemu_docdir, "conf.py")
369
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
370
-
371
-# This slightly misuses the 'description', but is the best way to get
372
-# the manual title to appear in the sidebar.
373
-html_theme_options['description'] = \
374
- u'Tools Guide'
375
-
376
-# One entry per manual page. List of tuples
377
-# (source start file, name, description, authors, manual section).
378
-man_pages = [
379
- ('qemu-img', 'qemu-img', u'QEMU disk image utility',
380
- ['Fabrice Bellard'], 1),
381
- ('qemu-storage-daemon', 'qemu-storage-daemon', u'QEMU storage daemon',
382
- [], 1),
383
- ('qemu-nbd', 'qemu-nbd', u'QEMU Disk Network Block Device Server',
384
- ['Anthony Liguori <anthony@codemonkey.ws>'], 8),
385
- ('qemu-pr-helper', 'qemu-pr-helper', 'QEMU persistent reservation helper',
386
- [], 8),
387
- ('qemu-trace-stap', 'qemu-trace-stap', u'QEMU SystemTap trace tool',
388
- [], 1),
389
- ('virtfs-proxy-helper', 'virtfs-proxy-helper',
390
- u'QEMU 9p virtfs proxy filesystem helper',
391
- ['M. Mohan Kumar'], 1),
392
- ('virtiofsd', 'virtiofsd', u'QEMU virtio-fs shared file system daemon',
393
- ['Stefan Hajnoczi <stefanha@redhat.com>',
394
- 'Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>'], 1),
395
-]
396
diff --git a/docs/user/conf.py b/docs/user/conf.py
397
deleted file mode 100644
398
index XXXXXXX..XXXXXXX
399
--- a/docs/user/conf.py
400
+++ /dev/null
401
@@ -XXX,XX +XXX,XX @@
402
-# -*- coding: utf-8 -*-
403
-#
404
-# QEMU documentation build configuration file for the 'user' manual.
405
-#
406
-# This includes the top level conf file and then makes any necessary tweaks.
407
-import sys
408
-import os
409
-
410
-qemu_docdir = os.path.abspath("..")
411
-parent_config = os.path.join(qemu_docdir, "conf.py")
412
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
413
-
414
-# This slightly misuses the 'description', but is the best way to get
415
-# the manual title to appear in the sidebar.
416
-html_theme_options['description'] = u'User Mode Emulation User''s Guide'
417
--
81
--
418
2.20.1
82
2.34.1
419
83
420
84
diff view generated by jsdifflib
1
In commit cd8be50e58f63413c0 we converted the A32 coprocessor
1
Don't allow the guest to write CNTHCTL_EL2 bits which don't exist.
2
insns to decodetree. This accidentally broke XScale/iWMMXt insns,
2
This is not strictly architecturally required, but it is how we've
3
because it moved the handling of "cp insns which are handled
3
tended to implement registers more recently.
4
by looking up the cp register in the hashtable" from after the
5
call to the legacy disas_xscale_insn() decode to before it,
6
with the result that all XScale/iWMMXt insns now UNDEF.
7
4
8
Update valid_cp() so that it knows that on XScale cp 0 and 1
5
In particular, bits [19:18] are only present with FEAT_RME,
9
are not standard coprocessor instructions; this will cause
6
and bits [17:12] will only be present with FEAT_ECV.
10
the decodetree trans_ functions to ignore them, so that
11
execution will correctly get through to the legacy decode again.
12
7
13
Cc: qemu-stable@nongnu.org
14
Reported-by: Guenter Roeck <linux@roeck-us.net>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Tested-by: Guenter Roeck <linux@roeck-us.net>
10
Message-id: 20240301183219.2424889-5-peter.maydell@linaro.org
18
Message-id: 20210108195157.32067-1-peter.maydell@linaro.org
19
---
11
---
20
target/arm/translate.c | 7 +++++++
12
target/arm/helper.c | 18 ++++++++++++++++++
21
1 file changed, 7 insertions(+)
13
1 file changed, 18 insertions(+)
22
14
23
diff --git a/target/arm/translate.c b/target/arm/translate.c
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
24
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/translate.c
17
--- a/target/arm/helper.c
26
+++ b/target/arm/translate.c
18
+++ b/target/arm/helper.c
27
@@ -XXX,XX +XXX,XX @@ static bool valid_cp(DisasContext *s, int cp)
19
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
28
* only cp14 and cp15 are valid, and other values aren't considered
20
{
29
* to be in the coprocessor-instruction space at all. v8M still
21
ARMCPU *cpu = env_archcpu(env);
30
* permits coprocessors 0..7.
22
uint32_t oldval = env->cp15.cnthctl_el2;
31
+ * For XScale, we must not decode the XScale cp0, cp1 space as
23
+ uint32_t valid_mask =
32
+ * a standard coprocessor insn, because we want to fall through to
24
+ R_CNTHCTL_EL0PCTEN_E2H1_MASK |
33
+ * the legacy disas_xscale_insn() decoder after decodetree is done.
25
+ R_CNTHCTL_EL0VCTEN_E2H1_MASK |
34
*/
26
+ R_CNTHCTL_EVNTEN_MASK |
35
+ if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cp == 0 || cp == 1)) {
27
+ R_CNTHCTL_EVNTDIR_MASK |
36
+ return false;
28
+ R_CNTHCTL_EVNTI_MASK |
29
+ R_CNTHCTL_EL0VTEN_MASK |
30
+ R_CNTHCTL_EL0PTEN_MASK |
31
+ R_CNTHCTL_EL1PCTEN_E2H1_MASK |
32
+ R_CNTHCTL_EL1PTEN_MASK;
33
+
34
+ if (cpu_isar_feature(aa64_rme, cpu)) {
35
+ valid_mask |= R_CNTHCTL_CNTVMASK_MASK | R_CNTHCTL_CNTPMASK_MASK;
37
+ }
36
+ }
38
+
37
+
39
if (arm_dc_feature(s, ARM_FEATURE_V8) &&
38
+ /* Clear RES0 bits */
40
!arm_dc_feature(s, ARM_FEATURE_M)) {
39
+ value &= valid_mask;
41
return cp >= 14;
40
+
41
raw_write(env, ri, value);
42
43
if ((oldval ^ value) & R_CNTHCTL_CNTVMASK_MASK) {
42
--
44
--
43
2.20.1
45
2.34.1
44
45
diff view generated by jsdifflib
1
From: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
1
The functionality defined by ID_AA64MMFR0_EL1.ECV == 1 is:
2
* four new trap bits for various counter and timer registers
3
* the CNTHCTL_EL2.EVNTIS and CNTKCTL_EL1.EVNTIS bits which control
4
scaling of the event stream. This is a no-op for us, because we don't
5
implement the event stream (our WFE is a NOP): all we need to do is
6
allow CNTHCTL_EL2.ENVTIS to be read and written.
7
* extensions to PMSCR_EL1.PCT, PMSCR_EL2.PCT, TRFCR_EL1.TS and
8
TRFCR_EL2.TS: these are all no-ops for us, because we don't implement
9
FEAT_SPE or FEAT_TRF.
10
* new registers CNTPCTSS_EL0 and NCTVCTSS_EL0 which are
11
"self-sychronizing" views of the CNTPCT_EL0 and CNTVCT_EL0, meaning
12
that no barriers are needed around their accesses. For us these
13
are just the same as the normal views, because all our sysregs are
14
inherently self-sychronizing.
2
15
3
This adds for the Small Translation tables extension in AArch64 state.
16
In this commit we implement the trap handling and permit the new
17
CNTHCTL_EL2 bits to be written.
4
18
5
Signed-off-by: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Message-id: 20240301183219.2424889-6-peter.maydell@linaro.org
8
---
22
---
9
target/arm/cpu.h | 5 +++++
23
target/arm/cpu-features.h | 5 ++++
10
target/arm/helper.c | 15 +++++++++++++--
24
target/arm/helper.c | 51 +++++++++++++++++++++++++++++++++++----
11
2 files changed, 18 insertions(+), 2 deletions(-)
25
2 files changed, 51 insertions(+), 5 deletions(-)
12
26
13
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
27
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
14
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/cpu.h
29
--- a/target/arm/cpu-features.h
16
+++ b/target/arm/cpu.h
30
+++ b/target/arm/cpu-features.h
17
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_uao(const ARMISARegisters *id)
31
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_fgt(const ARMISARegisters *id)
18
return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0;
32
return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, FGT) != 0;
19
}
33
}
20
34
21
+static inline bool isar_feature_aa64_st(const ARMISARegisters *id)
35
+static inline bool isar_feature_aa64_ecv_traps(const ARMISARegisters *id)
22
+{
36
+{
23
+ return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, ST) != 0;
37
+ return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 0;
24
+}
38
+}
25
+
39
+
26
static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
40
static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
27
{
41
{
28
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;
42
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
29
diff --git a/target/arm/helper.c b/target/arm/helper.c
43
diff --git a/target/arm/helper.c b/target/arm/helper.c
30
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/helper.c
45
--- a/target/arm/helper.c
32
+++ b/target/arm/helper.c
46
+++ b/target/arm/helper.c
33
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
47
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_counter_access(CPUARMState *env, int timeridx,
48
: !extract32(env->cp15.cnthctl_el2, 0, 1))) {
49
return CP_ACCESS_TRAP_EL2;
50
}
51
+ if (has_el2 && timeridx == GTIMER_VIRT) {
52
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1TVCT)) {
53
+ return CP_ACCESS_TRAP_EL2;
54
+ }
55
+ }
56
break;
57
}
58
return CP_ACCESS_OK;
59
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_timer_access(CPUARMState *env, int timeridx,
60
}
61
}
62
}
63
+ if (has_el2 && timeridx == GTIMER_VIRT) {
64
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1TVT)) {
65
+ return CP_ACCESS_TRAP_EL2;
66
+ }
67
+ }
68
break;
69
}
70
return CP_ACCESS_OK;
71
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
72
if (cpu_isar_feature(aa64_rme, cpu)) {
73
valid_mask |= R_CNTHCTL_CNTVMASK_MASK | R_CNTHCTL_CNTPMASK_MASK;
74
}
75
+ if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
76
+ valid_mask |=
77
+ R_CNTHCTL_EL1TVT_MASK |
78
+ R_CNTHCTL_EL1TVCT_MASK |
79
+ R_CNTHCTL_EL1NVPCT_MASK |
80
+ R_CNTHCTL_EL1NVVCT_MASK |
81
+ R_CNTHCTL_EVNTIS_MASK;
82
+ }
83
84
/* Clear RES0 bits */
85
value &= valid_mask;
86
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
34
{
87
{
35
uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
88
if (arm_current_el(env) == 1) {
36
bool epd, hpd, using16k, using64k;
89
/* This must be a FEAT_NV access */
37
- int select, tsz, tbi;
90
- /* TODO: FEAT_ECV will need to check CNTHCTL_EL2 here */
38
+ int select, tsz, tbi, max_tsz;
91
return CP_ACCESS_OK;
39
40
if (!regime_has_2_ranges(mmu_idx)) {
41
select = 0;
42
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
43
hpd = extract64(tcr, 42, 1);
44
}
45
}
92
}
46
- tsz = MIN(tsz, 39); /* TODO: ARMv8.4-TTST */
93
if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
94
@@ -XXX,XX +XXX,XX @@ static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
95
return CP_ACCESS_OK;
96
}
97
98
+static CPAccessResult access_el1nvpct(CPUARMState *env, const ARMCPRegInfo *ri,
99
+ bool isread)
100
+{
101
+ if (arm_current_el(env) == 1) {
102
+ /* This must be a FEAT_NV access with NVx == 101 */
103
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1NVPCT)) {
104
+ return CP_ACCESS_TRAP_EL2;
105
+ }
106
+ }
107
+ return e2h_access(env, ri, isread);
108
+}
47
+
109
+
48
+ if (cpu_isar_feature(aa64_st, env_archcpu(env))) {
110
+static CPAccessResult access_el1nvvct(CPUARMState *env, const ARMCPRegInfo *ri,
49
+ max_tsz = 48 - using64k;
111
+ bool isread)
50
+ } else {
112
+{
51
+ max_tsz = 39;
113
+ if (arm_current_el(env) == 1) {
114
+ /* This must be a FEAT_NV access with NVx == 101 */
115
+ if (FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, EL1NVVCT)) {
116
+ return CP_ACCESS_TRAP_EL2;
117
+ }
52
+ }
118
+ }
119
+ return e2h_access(env, ri, isread);
120
+}
53
+
121
+
54
+ tsz = MIN(tsz, max_tsz);
122
/* Test if system register redirection is to occur in the current state. */
55
tsz = MAX(tsz, 16); /* TODO: ARMv8.2-LVA */
123
static bool redirect_for_e2h(CPUARMState *env)
56
124
{
57
/* Present TBI as a composite with TBID. */
125
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
58
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
126
{ .name = "CNTP_CTL_EL02", .state = ARM_CP_STATE_AA64,
59
if (!aarch64 || stride == 9) {
127
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 2, .opc2 = 1,
60
/* AArch32 or 4KB pages */
128
.type = ARM_CP_IO | ARM_CP_ALIAS,
61
startlevel = 2 - sl0;
129
- .access = PL2_RW, .accessfn = e2h_access,
62
+
130
+ .access = PL2_RW, .accessfn = access_el1nvpct,
63
+ if (cpu_isar_feature(aa64_st, cpu)) {
131
.nv2_redirect_offset = 0x180 | NV2_REDIR_NO_NV1,
64
+ startlevel &= 3;
132
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].ctl),
65
+ }
133
.writefn = gt_phys_ctl_write, .raw_writefn = raw_write },
66
} else {
134
{ .name = "CNTV_CTL_EL02", .state = ARM_CP_STATE_AA64,
67
/* 16KB or 64KB pages */
135
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 1,
68
startlevel = 3 - sl0;
136
.type = ARM_CP_IO | ARM_CP_ALIAS,
137
- .access = PL2_RW, .accessfn = e2h_access,
138
+ .access = PL2_RW, .accessfn = access_el1nvvct,
139
.nv2_redirect_offset = 0x170 | NV2_REDIR_NO_NV1,
140
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].ctl),
141
.writefn = gt_virt_ctl_write, .raw_writefn = raw_write },
142
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo vhe_reginfo[] = {
143
.type = ARM_CP_IO | ARM_CP_ALIAS,
144
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
145
.nv2_redirect_offset = 0x178 | NV2_REDIR_NO_NV1,
146
- .access = PL2_RW, .accessfn = e2h_access,
147
+ .access = PL2_RW, .accessfn = access_el1nvpct,
148
.writefn = gt_phys_cval_write, .raw_writefn = raw_write },
149
{ .name = "CNTV_CVAL_EL02", .state = ARM_CP_STATE_AA64,
150
.opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 2,
151
.type = ARM_CP_IO | ARM_CP_ALIAS,
152
.nv2_redirect_offset = 0x168 | NV2_REDIR_NO_NV1,
153
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
154
- .access = PL2_RW, .accessfn = e2h_access,
155
+ .access = PL2_RW, .accessfn = access_el1nvvct,
156
.writefn = gt_virt_cval_write, .raw_writefn = raw_write },
157
#endif
158
};
69
--
159
--
70
2.20.1
160
2.34.1
71
72
diff view generated by jsdifflib
Deleted patch
1
From: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
2
1
3
Signed-off-by: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
---
7
target/arm/cpu64.c | 1 +
8
1 file changed, 1 insertion(+)
9
10
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/arm/cpu64.c
13
+++ b/target/arm/cpu64.c
14
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
15
t = cpu->isar.id_aa64mmfr2;
16
t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1);
17
t = FIELD_DP64(t, ID_AA64MMFR2, CNP, 1); /* TTCNP */
18
+ t = FIELD_DP64(t, ID_AA64MMFR2, ST, 1); /* TTST */
19
cpu->isar.id_aa64mmfr2 = t;
20
21
/* Replicate the same data to the 32-bit id registers. */
22
--
23
2.20.1
24
25
diff view generated by jsdifflib
1
The lan9118 code mostly uses symbolic constants for register offsets;
1
For FEAT_ECV, new registers CNTPCTSS_EL0 and CNTVCTSS_EL0 are
2
the exceptions are those which the datasheet doesn't give an official
2
defined, which are "self-synchronized" views of the physical and
3
symbolic name to.
3
virtual counts as seen in the CNTPCT_EL0 and CNTVCT_EL0 registers
4
(meaning that no barriers are needed around accesses to them to
5
ensure that reads of them do not occur speculatively and out-of-order
6
with other instructions).
4
7
5
Add some names for the registers which don't already have them, based
8
For QEMU, all our system registers are self-synchronized, so we can
6
on the longer names they are given in the memory map.
9
simply copy the existing implementation of CNTPCT_EL0 and CNTVCT_EL0
10
to the new register encodings.
11
12
This means we now implement all the functionality required for
13
ID_AA64MMFR0_EL1.ECV == 0b0001.
7
14
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210108180401.2263-3-peter.maydell@linaro.org
17
Message-id: 20240301183219.2424889-7-peter.maydell@linaro.org
11
---
18
---
12
hw/net/lan9118.c | 24 ++++++++++++++++++------
19
target/arm/helper.c | 43 +++++++++++++++++++++++++++++++++++++++++++
13
1 file changed, 18 insertions(+), 6 deletions(-)
20
1 file changed, 43 insertions(+)
14
21
15
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
22
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/net/lan9118.c
24
--- a/target/arm/helper.c
18
+++ b/hw/net/lan9118.c
25
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ do { hw_error("lan9118: error: " fmt , ## __VA_ARGS__);} while (0)
26
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
20
do { fprintf(stderr, "lan9118: error: " fmt , ## __VA_ARGS__);} while (0)
27
},
28
};
29
30
+/*
31
+ * FEAT_ECV adds extra views of CNTVCT_EL0 and CNTPCT_EL0 which
32
+ * are "self-synchronizing". For QEMU all sysregs are self-synchronizing,
33
+ * so our implementations here are identical to the normal registers.
34
+ */
35
+static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
36
+ { .name = "CNTVCTSS", .cp = 15, .crm = 14, .opc1 = 9,
37
+ .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_IO,
38
+ .accessfn = gt_vct_access,
39
+ .readfn = gt_virt_cnt_read, .resetfn = arm_cp_reset_ignore,
40
+ },
41
+ { .name = "CNTVCTSS_EL0", .state = ARM_CP_STATE_AA64,
42
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 6,
43
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
44
+ .accessfn = gt_vct_access, .readfn = gt_virt_cnt_read,
45
+ },
46
+ { .name = "CNTPCTSS", .cp = 15, .crm = 14, .opc1 = 8,
47
+ .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_IO,
48
+ .accessfn = gt_pct_access,
49
+ .readfn = gt_cnt_read, .resetfn = arm_cp_reset_ignore,
50
+ },
51
+ { .name = "CNTPCTSS_EL0", .state = ARM_CP_STATE_AA64,
52
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 5,
53
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
54
+ .accessfn = gt_pct_access, .readfn = gt_cnt_read,
55
+ },
56
+};
57
+
58
#else
59
60
/*
61
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
62
},
63
};
64
65
+/*
66
+ * CNTVCTSS_EL0 has the same trap conditions as CNTVCT_EL0, so it also
67
+ * is exposed to userspace by Linux.
68
+ */
69
+static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
70
+ { .name = "CNTVCTSS_EL0", .state = ARM_CP_STATE_AA64,
71
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 6,
72
+ .access = PL0_R, .type = ARM_CP_NO_RAW | ARM_CP_IO,
73
+ .readfn = gt_virt_cnt_read,
74
+ },
75
+};
76
+
21
#endif
77
#endif
22
78
23
+/* The tx and rx fifo ports are a range of aliased 32-bit registers */
79
static void par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
24
+#define RX_DATA_FIFO_PORT_FIRST 0x00
80
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
25
+#define RX_DATA_FIFO_PORT_LAST 0x1f
81
if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
26
+#define TX_DATA_FIFO_PORT_FIRST 0x20
82
define_arm_cp_regs(cpu, generic_timer_cp_reginfo);
27
+#define TX_DATA_FIFO_PORT_LAST 0x3f
28
+
29
+#define RX_STATUS_FIFO_PORT 0x40
30
+#define RX_STATUS_FIFO_PEEK 0x44
31
+#define TX_STATUS_FIFO_PORT 0x48
32
+#define TX_STATUS_FIFO_PEEK 0x4c
33
+
34
#define CSR_ID_REV 0x50
35
#define CSR_IRQ_CFG 0x54
36
#define CSR_INT_STS 0x58
37
@@ -XXX,XX +XXX,XX @@ static void lan9118_writel(void *opaque, hwaddr offset,
38
offset &= 0xff;
39
40
//DPRINTF("Write reg 0x%02x = 0x%08x\n", (int)offset, val);
41
- if (offset >= 0x20 && offset < 0x40) {
42
+ if (offset >= TX_DATA_FIFO_PORT_FIRST &&
43
+ offset <= TX_DATA_FIFO_PORT_LAST) {
44
/* TX FIFO */
45
tx_fifo_push(s, val);
46
return;
47
@@ -XXX,XX +XXX,XX @@ static uint64_t lan9118_readl(void *opaque, hwaddr offset,
48
lan9118_state *s = (lan9118_state *)opaque;
49
50
//DPRINTF("Read reg 0x%02x\n", (int)offset);
51
- if (offset < 0x20) {
52
+ if (offset <= RX_DATA_FIFO_PORT_LAST) {
53
/* RX FIFO */
54
return rx_fifo_pop(s);
55
}
83
}
56
switch (offset) {
84
+ if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
57
- case 0x40:
85
+ define_arm_cp_regs(cpu, gen_timer_ecv_cp_reginfo);
58
+ case RX_STATUS_FIFO_PORT:
86
+ }
59
return rx_status_fifo_pop(s);
87
if (arm_feature(env, ARM_FEATURE_VAPA)) {
60
- case 0x44:
88
ARMCPRegInfo vapa_cp_reginfo[] = {
61
+ case RX_STATUS_FIFO_PEEK:
89
{ .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0,
62
return s->rx_status_fifo[s->rx_status_fifo_head];
63
- case 0x48:
64
+ case TX_STATUS_FIFO_PORT:
65
return tx_status_fifo_pop(s);
66
- case 0x4c:
67
+ case TX_STATUS_FIFO_PEEK:
68
return s->tx_status_fifo[s->tx_status_fifo_head];
69
case CSR_ID_REV:
70
return 0x01180001;
71
--
90
--
72
2.20.1
91
2.34.1
73
74
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
When ID_AA64MMFR0_EL1.ECV is 0b0010, a new register CNTPOFF_EL2 is
2
implemented. This is similar to the existing CNTVOFF_EL2, except
3
that it controls a hypervisor-adjustable offset made to the physical
4
counter and timer.
2
5
3
This patch allows NPCM7XX CLK module to compute clocks that are used by
6
Implement the handling for this register, which includes control/trap
4
other NPCM7XX modules.
7
bits in SCR_EL3 and CNTHCTL_EL2.
5
8
6
Add a new struct NPCM7xxClockConverterState which represents a
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
single converter. Each clock converter in CLK module represents one
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
converter in NPCM7XX CLK Module(PLL, SEL or Divider). Each converter
11
Message-id: 20240301183219.2424889-8-peter.maydell@linaro.org
9
takes one or more input clocks and converts them into one output clock.
12
---
10
They form a clock hierarchy in the CLK module and are responsible for
13
target/arm/cpu-features.h | 5 +++
11
outputing clocks for various other modules in an NPCM7XX SoC.
14
target/arm/cpu.h | 1 +
15
target/arm/helper.c | 68 +++++++++++++++++++++++++++++++++++++--
16
target/arm/trace-events | 1 +
17
4 files changed, 73 insertions(+), 2 deletions(-)
12
18
13
Each converter has a function pointer called "convert" which represents
19
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
14
the unique logic for that converter.
15
16
The clock contains two initialization information: ConverterInitInfo and
17
ConverterConnectionInfo. They represent the vertices and edges in the
18
clock diagram respectively.
19
20
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
21
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
22
Signed-off-by: Hao Wu <wuhaotsh@google.com>
23
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
24
Message-id: 20210108190945.949196-2-wuhaotsh@google.com
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
---
27
include/hw/misc/npcm7xx_clk.h | 140 +++++-
28
hw/misc/npcm7xx_clk.c | 805 +++++++++++++++++++++++++++++++++-
29
2 files changed, 932 insertions(+), 13 deletions(-)
30
31
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
32
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
33
--- a/include/hw/misc/npcm7xx_clk.h
21
--- a/target/arm/cpu-features.h
34
+++ b/include/hw/misc/npcm7xx_clk.h
22
+++ b/target/arm/cpu-features.h
35
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_ecv_traps(const ARMISARegisters *id)
36
#define NPCM7XX_CLK_H
24
return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 0;
37
25
}
38
#include "exec/memory.h"
26
39
+#include "hw/clock.h"
27
+static inline bool isar_feature_aa64_ecv(const ARMISARegisters *id)
40
#include "hw/sysbus.h"
41
42
/*
43
@@ -XXX,XX +XXX,XX @@
44
45
#define NPCM7XX_WATCHDOG_RESET_GPIO_IN "npcm7xx-clk-watchdog-reset-gpio-in"
46
47
-typedef struct NPCM7xxCLKState {
48
+/* Maximum amount of clock inputs in a SEL module. */
49
+#define NPCM7XX_CLK_SEL_MAX_INPUT 5
50
+
51
+/* PLLs in CLK module. */
52
+typedef enum NPCM7xxClockPLL {
53
+ NPCM7XX_CLOCK_PLL0,
54
+ NPCM7XX_CLOCK_PLL1,
55
+ NPCM7XX_CLOCK_PLL2,
56
+ NPCM7XX_CLOCK_PLLG,
57
+ NPCM7XX_CLOCK_NR_PLLS,
58
+} NPCM7xxClockPLL;
59
+
60
+/* SEL/MUX in CLK module. */
61
+typedef enum NPCM7xxClockSEL {
62
+ NPCM7XX_CLOCK_PIXCKSEL,
63
+ NPCM7XX_CLOCK_MCCKSEL,
64
+ NPCM7XX_CLOCK_CPUCKSEL,
65
+ NPCM7XX_CLOCK_CLKOUTSEL,
66
+ NPCM7XX_CLOCK_UARTCKSEL,
67
+ NPCM7XX_CLOCK_TIMCKSEL,
68
+ NPCM7XX_CLOCK_SDCKSEL,
69
+ NPCM7XX_CLOCK_GFXMSEL,
70
+ NPCM7XX_CLOCK_SUCKSEL,
71
+ NPCM7XX_CLOCK_NR_SELS,
72
+} NPCM7xxClockSEL;
73
+
74
+/* Dividers in CLK module. */
75
+typedef enum NPCM7xxClockDivider {
76
+ NPCM7XX_CLOCK_PLL1D2, /* PLL1/2 */
77
+ NPCM7XX_CLOCK_PLL2D2, /* PLL2/2 */
78
+ NPCM7XX_CLOCK_MC_DIVIDER,
79
+ NPCM7XX_CLOCK_AXI_DIVIDER,
80
+ NPCM7XX_CLOCK_AHB_DIVIDER,
81
+ NPCM7XX_CLOCK_AHB3_DIVIDER,
82
+ NPCM7XX_CLOCK_SPI0_DIVIDER,
83
+ NPCM7XX_CLOCK_SPIX_DIVIDER,
84
+ NPCM7XX_CLOCK_APB1_DIVIDER,
85
+ NPCM7XX_CLOCK_APB2_DIVIDER,
86
+ NPCM7XX_CLOCK_APB3_DIVIDER,
87
+ NPCM7XX_CLOCK_APB4_DIVIDER,
88
+ NPCM7XX_CLOCK_APB5_DIVIDER,
89
+ NPCM7XX_CLOCK_CLKOUT_DIVIDER,
90
+ NPCM7XX_CLOCK_UART_DIVIDER,
91
+ NPCM7XX_CLOCK_TIMER_DIVIDER,
92
+ NPCM7XX_CLOCK_ADC_DIVIDER,
93
+ NPCM7XX_CLOCK_MMC_DIVIDER,
94
+ NPCM7XX_CLOCK_SDHC_DIVIDER,
95
+ NPCM7XX_CLOCK_GFXM_DIVIDER, /* divide by 3 */
96
+ NPCM7XX_CLOCK_UTMI_DIVIDER,
97
+ NPCM7XX_CLOCK_NR_DIVIDERS,
98
+} NPCM7xxClockConverter;
99
+
100
+typedef struct NPCM7xxCLKState NPCM7xxCLKState;
101
+
102
+/**
103
+ * struct NPCM7xxClockPLLState - A PLL module in CLK module.
104
+ * @name: The name of the module.
105
+ * @clk: The CLK module that owns this module.
106
+ * @clock_in: The input clock of this module.
107
+ * @clock_out: The output clock of this module.
108
+ * @reg: The control registers for this PLL module.
109
+ */
110
+typedef struct NPCM7xxClockPLLState {
111
+ DeviceState parent;
112
+
113
+ const char *name;
114
+ NPCM7xxCLKState *clk;
115
+ Clock *clock_in;
116
+ Clock *clock_out;
117
+
118
+ int reg;
119
+} NPCM7xxClockPLLState;
120
+
121
+/**
122
+ * struct NPCM7xxClockSELState - A SEL module in CLK module.
123
+ * @name: The name of the module.
124
+ * @clk: The CLK module that owns this module.
125
+ * @input_size: The size of inputs of this module.
126
+ * @clock_in: The input clocks of this module.
127
+ * @clock_out: The output clocks of this module.
128
+ * @offset: The offset of this module in the control register.
129
+ * @len: The length of this module in the control register.
130
+ */
131
+typedef struct NPCM7xxClockSELState {
132
+ DeviceState parent;
133
+
134
+ const char *name;
135
+ NPCM7xxCLKState *clk;
136
+ uint8_t input_size;
137
+ Clock *clock_in[NPCM7XX_CLK_SEL_MAX_INPUT];
138
+ Clock *clock_out;
139
+
140
+ int offset;
141
+ int len;
142
+} NPCM7xxClockSELState;
143
+
144
+/**
145
+ * struct NPCM7xxClockDividerState - A Divider module in CLK module.
146
+ * @name: The name of the module.
147
+ * @clk: The CLK module that owns this module.
148
+ * @clock_in: The input clock of this module.
149
+ * @clock_out: The output clock of this module.
150
+ * @divide: The function the divider uses to divide the input.
151
+ * @reg: The index of the control register that contains the divisor.
152
+ * @offset: The offset of the divisor in the control register.
153
+ * @len: The length of the divisor in the control register.
154
+ * @divisor: The divisor for a constant divisor
155
+ */
156
+typedef struct NPCM7xxClockDividerState {
157
+ DeviceState parent;
158
+
159
+ const char *name;
160
+ NPCM7xxCLKState *clk;
161
+ Clock *clock_in;
162
+ Clock *clock_out;
163
+
164
+ uint32_t (*divide)(struct NPCM7xxClockDividerState *s);
165
+ union {
166
+ struct {
167
+ int reg;
168
+ int offset;
169
+ int len;
170
+ };
171
+ int divisor;
172
+ };
173
+} NPCM7xxClockDividerState;
174
+
175
+struct NPCM7xxCLKState {
176
SysBusDevice parent;
177
178
MemoryRegion iomem;
179
180
+ /* Clock converters */
181
+ NPCM7xxClockPLLState plls[NPCM7XX_CLOCK_NR_PLLS];
182
+ NPCM7xxClockSELState sels[NPCM7XX_CLOCK_NR_SELS];
183
+ NPCM7xxClockDividerState dividers[NPCM7XX_CLOCK_NR_DIVIDERS];
184
+
185
uint32_t regs[NPCM7XX_CLK_NR_REGS];
186
187
/* Time reference for SECCNT and CNTR25M, initialized by power on reset */
188
int64_t ref_ns;
189
-} NPCM7xxCLKState;
190
+
191
+ /* The incoming reference clock. */
192
+ Clock *clkref;
193
+};
194
195
#define TYPE_NPCM7XX_CLK "npcm7xx-clk"
196
#define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), TYPE_NPCM7XX_CLK)
197
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
198
index XXXXXXX..XXXXXXX 100644
199
--- a/hw/misc/npcm7xx_clk.c
200
+++ b/hw/misc/npcm7xx_clk.c
201
@@ -XXX,XX +XXX,XX @@
202
203
#include "hw/misc/npcm7xx_clk.h"
204
#include "hw/timer/npcm7xx_timer.h"
205
+#include "hw/qdev-clock.h"
206
#include "migration/vmstate.h"
207
#include "qemu/error-report.h"
208
#include "qemu/log.h"
209
@@ -XXX,XX +XXX,XX @@
210
#include "trace.h"
211
#include "sysemu/watchdog.h"
212
213
+/*
214
+ * The reference clock hz, and the SECCNT and CNTR25M registers in this module,
215
+ * is always 25 MHz.
216
+ */
217
+#define NPCM7XX_CLOCK_REF_HZ (25000000)
218
+
219
+/* Register Field Definitions */
220
+#define NPCM7XX_CLK_WDRCR_CA9C BIT(0) /* Cortex A9 Cores */
221
+
222
#define PLLCON_LOKI BIT(31)
223
#define PLLCON_LOKS BIT(30)
224
#define PLLCON_PWDEN BIT(12)
225
+#define PLLCON_FBDV(con) extract32((con), 16, 12)
226
+#define PLLCON_OTDV2(con) extract32((con), 13, 3)
227
+#define PLLCON_OTDV1(con) extract32((con), 8, 3)
228
+#define PLLCON_INDV(con) extract32((con), 0, 6)
229
230
enum NPCM7xxCLKRegisters {
231
NPCM7XX_CLK_CLKEN1,
232
@@ -XXX,XX +XXX,XX @@ static const uint32_t cold_reset_values[NPCM7XX_CLK_NR_REGS] = {
233
[NPCM7XX_CLK_AHBCKFI] = 0x000000c8,
234
};
235
236
-/* Register Field Definitions */
237
-#define NPCM7XX_CLK_WDRCR_CA9C BIT(0) /* Cortex A9 Cores */
238
-
239
/* The number of watchdogs that can trigger a reset. */
240
#define NPCM7XX_NR_WATCHDOGS (3)
241
242
+/* Clock converter functions */
243
+
244
+#define TYPE_NPCM7XX_CLOCK_PLL "npcm7xx-clock-pll"
245
+#define NPCM7XX_CLOCK_PLL(obj) OBJECT_CHECK(NPCM7xxClockPLLState, \
246
+ (obj), TYPE_NPCM7XX_CLOCK_PLL)
247
+#define TYPE_NPCM7XX_CLOCK_SEL "npcm7xx-clock-sel"
248
+#define NPCM7XX_CLOCK_SEL(obj) OBJECT_CHECK(NPCM7xxClockSELState, \
249
+ (obj), TYPE_NPCM7XX_CLOCK_SEL)
250
+#define TYPE_NPCM7XX_CLOCK_DIVIDER "npcm7xx-clock-divider"
251
+#define NPCM7XX_CLOCK_DIVIDER(obj) OBJECT_CHECK(NPCM7xxClockDividerState, \
252
+ (obj), TYPE_NPCM7XX_CLOCK_DIVIDER)
253
+
254
+static void npcm7xx_clk_update_pll(void *opaque)
255
+{
28
+{
256
+ NPCM7xxClockPLLState *s = opaque;
29
+ return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, ECV) > 1;
257
+ uint32_t con = s->clk->regs[s->reg];
258
+ uint64_t freq;
259
+
260
+ /* The PLL is grounded if it is not locked yet. */
261
+ if (con & PLLCON_LOKI) {
262
+ freq = clock_get_hz(s->clock_in);
263
+ freq *= PLLCON_FBDV(con);
264
+ freq /= PLLCON_INDV(con) * PLLCON_OTDV1(con) * PLLCON_OTDV2(con);
265
+ } else {
266
+ freq = 0;
267
+ }
268
+
269
+ clock_update_hz(s->clock_out, freq);
270
+}
30
+}
271
+
31
+
272
+static void npcm7xx_clk_update_sel(void *opaque)
32
static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
33
{
34
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
35
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/cpu.h
38
+++ b/target/arm/cpu.h
39
@@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState {
40
uint64_t c14_cntkctl; /* Timer Control register */
41
uint64_t cnthctl_el2; /* Counter/Timer Hyp Control register */
42
uint64_t cntvoff_el2; /* Counter Virtual Offset register */
43
+ uint64_t cntpoff_el2; /* Counter Physical Offset register */
44
ARMGenericTimer c14_timer[NUM_GTIMERS];
45
uint32_t c15_cpar; /* XScale Coprocessor Access Register */
46
uint32_t c15_ticonfig; /* TI925T configuration byte. */
47
diff --git a/target/arm/helper.c b/target/arm/helper.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/helper.c
50
+++ b/target/arm/helper.c
51
@@ -XXX,XX +XXX,XX @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
52
if (cpu_isar_feature(aa64_rme, cpu)) {
53
valid_mask |= SCR_NSE | SCR_GPF;
54
}
55
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
56
+ valid_mask |= SCR_ECVEN;
57
+ }
58
} else {
59
valid_mask &= ~(SCR_RW | SCR_ST);
60
if (cpu_isar_feature(aa32_ras, cpu)) {
61
@@ -XXX,XX +XXX,XX @@ void gt_rme_post_el_change(ARMCPU *cpu, void *ignored)
62
gt_update_irq(cpu, GTIMER_PHYS);
63
}
64
65
+static uint64_t gt_phys_raw_cnt_offset(CPUARMState *env)
273
+{
66
+{
274
+ NPCM7xxClockSELState *s = opaque;
67
+ if ((env->cp15.scr_el3 & SCR_ECVEN) &&
275
+ uint32_t index = extract32(s->clk->regs[NPCM7XX_CLK_CLKSEL], s->offset,
68
+ FIELD_EX64(env->cp15.cnthctl_el2, CNTHCTL, ECV) &&
276
+ s->len);
69
+ arm_is_el2_enabled(env) &&
277
+
70
+ (arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
278
+ if (index >= s->input_size) {
71
+ return env->cp15.cntpoff_el2;
279
+ qemu_log_mask(LOG_GUEST_ERROR,
280
+ "%s: SEL index: %u out of range\n",
281
+ __func__, index);
282
+ index = 0;
283
+ }
72
+ }
284
+ clock_update_hz(s->clock_out, clock_get_hz(s->clock_in[index]));
285
+}
286
+
287
+static void npcm7xx_clk_update_divider(void *opaque)
288
+{
289
+ NPCM7xxClockDividerState *s = opaque;
290
+ uint32_t freq;
291
+
292
+ freq = s->divide(s);
293
+ clock_update_hz(s->clock_out, freq);
294
+}
295
+
296
+static uint32_t divide_by_constant(NPCM7xxClockDividerState *s)
297
+{
298
+ return clock_get_hz(s->clock_in) / s->divisor;
299
+}
300
+
301
+static uint32_t divide_by_reg_divisor(NPCM7xxClockDividerState *s)
302
+{
303
+ return clock_get_hz(s->clock_in) /
304
+ (extract32(s->clk->regs[s->reg], s->offset, s->len) + 1);
305
+}
306
+
307
+static uint32_t divide_by_reg_divisor_times_2(NPCM7xxClockDividerState *s)
308
+{
309
+ return divide_by_reg_divisor(s) / 2;
310
+}
311
+
312
+static uint32_t shift_by_reg_divisor(NPCM7xxClockDividerState *s)
313
+{
314
+ return clock_get_hz(s->clock_in) >>
315
+ extract32(s->clk->regs[s->reg], s->offset, s->len);
316
+}
317
+
318
+static NPCM7xxClockPLL find_pll_by_reg(enum NPCM7xxCLKRegisters reg)
319
+{
320
+ switch (reg) {
321
+ case NPCM7XX_CLK_PLLCON0:
322
+ return NPCM7XX_CLOCK_PLL0;
323
+ case NPCM7XX_CLK_PLLCON1:
324
+ return NPCM7XX_CLOCK_PLL1;
325
+ case NPCM7XX_CLK_PLLCON2:
326
+ return NPCM7XX_CLOCK_PLL2;
327
+ case NPCM7XX_CLK_PLLCONG:
328
+ return NPCM7XX_CLOCK_PLLG;
329
+ default:
330
+ g_assert_not_reached();
331
+ }
332
+}
333
+
334
+static void npcm7xx_clk_update_all_plls(NPCM7xxCLKState *clk)
335
+{
336
+ int i;
337
+
338
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
339
+ npcm7xx_clk_update_pll(&clk->plls[i]);
340
+ }
341
+}
342
+
343
+static void npcm7xx_clk_update_all_sels(NPCM7xxCLKState *clk)
344
+{
345
+ int i;
346
+
347
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
348
+ npcm7xx_clk_update_sel(&clk->sels[i]);
349
+ }
350
+}
351
+
352
+static void npcm7xx_clk_update_all_dividers(NPCM7xxCLKState *clk)
353
+{
354
+ int i;
355
+
356
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
357
+ npcm7xx_clk_update_divider(&clk->dividers[i]);
358
+ }
359
+}
360
+
361
+static void npcm7xx_clk_update_all_clocks(NPCM7xxCLKState *clk)
362
+{
363
+ clock_update_hz(clk->clkref, NPCM7XX_CLOCK_REF_HZ);
364
+ npcm7xx_clk_update_all_plls(clk);
365
+ npcm7xx_clk_update_all_sels(clk);
366
+ npcm7xx_clk_update_all_dividers(clk);
367
+}
368
+
369
+/* Types of clock sources. */
370
+typedef enum ClockSrcType {
371
+ CLKSRC_REF,
372
+ CLKSRC_PLL,
373
+ CLKSRC_SEL,
374
+ CLKSRC_DIV,
375
+} ClockSrcType;
376
+
377
+typedef struct PLLInitInfo {
378
+ const char *name;
379
+ ClockSrcType src_type;
380
+ int src_index;
381
+ int reg;
382
+ const char *public_name;
383
+} PLLInitInfo;
384
+
385
+typedef struct SELInitInfo {
386
+ const char *name;
387
+ uint8_t input_size;
388
+ ClockSrcType src_type[NPCM7XX_CLK_SEL_MAX_INPUT];
389
+ int src_index[NPCM7XX_CLK_SEL_MAX_INPUT];
390
+ int offset;
391
+ int len;
392
+ const char *public_name;
393
+} SELInitInfo;
394
+
395
+typedef struct DividerInitInfo {
396
+ const char *name;
397
+ ClockSrcType src_type;
398
+ int src_index;
399
+ uint32_t (*divide)(NPCM7xxClockDividerState *s);
400
+ int reg; /* not used when type == CONSTANT */
401
+ int offset; /* not used when type == CONSTANT */
402
+ int len; /* not used when type == CONSTANT */
403
+ int divisor; /* used only when type == CONSTANT */
404
+ const char *public_name;
405
+} DividerInitInfo;
406
+
407
+static const PLLInitInfo pll_init_info_list[] = {
408
+ [NPCM7XX_CLOCK_PLL0] = {
409
+ .name = "pll0",
410
+ .src_type = CLKSRC_REF,
411
+ .reg = NPCM7XX_CLK_PLLCON0,
412
+ },
413
+ [NPCM7XX_CLOCK_PLL1] = {
414
+ .name = "pll1",
415
+ .src_type = CLKSRC_REF,
416
+ .reg = NPCM7XX_CLK_PLLCON1,
417
+ },
418
+ [NPCM7XX_CLOCK_PLL2] = {
419
+ .name = "pll2",
420
+ .src_type = CLKSRC_REF,
421
+ .reg = NPCM7XX_CLK_PLLCON2,
422
+ },
423
+ [NPCM7XX_CLOCK_PLLG] = {
424
+ .name = "pllg",
425
+ .src_type = CLKSRC_REF,
426
+ .reg = NPCM7XX_CLK_PLLCONG,
427
+ },
428
+};
429
+
430
+static const SELInitInfo sel_init_info_list[] = {
431
+ [NPCM7XX_CLOCK_PIXCKSEL] = {
432
+ .name = "pixcksel",
433
+ .input_size = 2,
434
+ .src_type = {CLKSRC_PLL, CLKSRC_REF},
435
+ .src_index = {NPCM7XX_CLOCK_PLLG, 0},
436
+ .offset = 5,
437
+ .len = 1,
438
+ .public_name = "pixel-clock",
439
+ },
440
+ [NPCM7XX_CLOCK_MCCKSEL] = {
441
+ .name = "mccksel",
442
+ .input_size = 4,
443
+ .src_type = {CLKSRC_DIV, CLKSRC_REF, CLKSRC_REF,
444
+ /*MCBPCK, shouldn't be used in normal operation*/
445
+ CLKSRC_REF},
446
+ .src_index = {NPCM7XX_CLOCK_PLL1D2, 0, 0, 0},
447
+ .offset = 12,
448
+ .len = 2,
449
+ .public_name = "mc-phy-clock",
450
+ },
451
+ [NPCM7XX_CLOCK_CPUCKSEL] = {
452
+ .name = "cpucksel",
453
+ .input_size = 4,
454
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF,
455
+ /*SYSBPCK, shouldn't be used in normal operation*/
456
+ CLKSRC_REF},
457
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0, 0},
458
+ .offset = 0,
459
+ .len = 2,
460
+ .public_name = "system-clock",
461
+ },
462
+ [NPCM7XX_CLOCK_CLKOUTSEL] = {
463
+ .name = "clkoutsel",
464
+ .input_size = 5,
465
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF,
466
+ CLKSRC_PLL, CLKSRC_DIV},
467
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
468
+ NPCM7XX_CLOCK_PLLG, NPCM7XX_CLOCK_PLL2D2},
469
+ .offset = 18,
470
+ .len = 3,
471
+ .public_name = "tock",
472
+ },
473
+ [NPCM7XX_CLOCK_UARTCKSEL] = {
474
+ .name = "uartcksel",
475
+ .input_size = 4,
476
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
477
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
478
+ NPCM7XX_CLOCK_PLL2D2},
479
+ .offset = 8,
480
+ .len = 2,
481
+ },
482
+ [NPCM7XX_CLOCK_TIMCKSEL] = {
483
+ .name = "timcksel",
484
+ .input_size = 4,
485
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
486
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
487
+ NPCM7XX_CLOCK_PLL2D2},
488
+ .offset = 14,
489
+ .len = 2,
490
+ },
491
+ [NPCM7XX_CLOCK_SDCKSEL] = {
492
+ .name = "sdcksel",
493
+ .input_size = 4,
494
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
495
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
496
+ NPCM7XX_CLOCK_PLL2D2},
497
+ .offset = 6,
498
+ .len = 2,
499
+ },
500
+ [NPCM7XX_CLOCK_GFXMSEL] = {
501
+ .name = "gfxmksel",
502
+ .input_size = 2,
503
+ .src_type = {CLKSRC_REF, CLKSRC_PLL},
504
+ .src_index = {0, NPCM7XX_CLOCK_PLL2},
505
+ .offset = 21,
506
+ .len = 1,
507
+ },
508
+ [NPCM7XX_CLOCK_SUCKSEL] = {
509
+ .name = "sucksel",
510
+ .input_size = 4,
511
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
512
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
513
+ NPCM7XX_CLOCK_PLL2D2},
514
+ .offset = 10,
515
+ .len = 2,
516
+ },
517
+};
518
+
519
+static const DividerInitInfo divider_init_info_list[] = {
520
+ [NPCM7XX_CLOCK_PLL1D2] = {
521
+ .name = "pll1d2",
522
+ .src_type = CLKSRC_PLL,
523
+ .src_index = NPCM7XX_CLOCK_PLL1,
524
+ .divide = divide_by_constant,
525
+ .divisor = 2,
526
+ },
527
+ [NPCM7XX_CLOCK_PLL2D2] = {
528
+ .name = "pll2d2",
529
+ .src_type = CLKSRC_PLL,
530
+ .src_index = NPCM7XX_CLOCK_PLL2,
531
+ .divide = divide_by_constant,
532
+ .divisor = 2,
533
+ },
534
+ [NPCM7XX_CLOCK_MC_DIVIDER] = {
535
+ .name = "mc-divider",
536
+ .src_type = CLKSRC_SEL,
537
+ .src_index = NPCM7XX_CLOCK_MCCKSEL,
538
+ .divide = divide_by_constant,
539
+ .divisor = 2,
540
+ .public_name = "mc-clock"
541
+ },
542
+ [NPCM7XX_CLOCK_AXI_DIVIDER] = {
543
+ .name = "axi-divider",
544
+ .src_type = CLKSRC_SEL,
545
+ .src_index = NPCM7XX_CLOCK_CPUCKSEL,
546
+ .divide = shift_by_reg_divisor,
547
+ .reg = NPCM7XX_CLK_CLKDIV1,
548
+ .offset = 0,
549
+ .len = 1,
550
+ .public_name = "clk2"
551
+ },
552
+ [NPCM7XX_CLOCK_AHB_DIVIDER] = {
553
+ .name = "ahb-divider",
554
+ .src_type = CLKSRC_DIV,
555
+ .src_index = NPCM7XX_CLOCK_AXI_DIVIDER,
556
+ .divide = divide_by_reg_divisor,
557
+ .reg = NPCM7XX_CLK_CLKDIV1,
558
+ .offset = 26,
559
+ .len = 2,
560
+ .public_name = "clk4"
561
+ },
562
+ [NPCM7XX_CLOCK_AHB3_DIVIDER] = {
563
+ .name = "ahb3-divider",
564
+ .src_type = CLKSRC_DIV,
565
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
566
+ .divide = divide_by_reg_divisor,
567
+ .reg = NPCM7XX_CLK_CLKDIV1,
568
+ .offset = 6,
569
+ .len = 5,
570
+ .public_name = "ahb3-spi3-clock"
571
+ },
572
+ [NPCM7XX_CLOCK_SPI0_DIVIDER] = {
573
+ .name = "spi0-divider",
574
+ .src_type = CLKSRC_DIV,
575
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
576
+ .divide = divide_by_reg_divisor,
577
+ .reg = NPCM7XX_CLK_CLKDIV3,
578
+ .offset = 6,
579
+ .len = 5,
580
+ .public_name = "spi0-clock",
581
+ },
582
+ [NPCM7XX_CLOCK_SPIX_DIVIDER] = {
583
+ .name = "spix-divider",
584
+ .src_type = CLKSRC_DIV,
585
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
586
+ .divide = divide_by_reg_divisor,
587
+ .reg = NPCM7XX_CLK_CLKDIV3,
588
+ .offset = 1,
589
+ .len = 5,
590
+ .public_name = "spix-clock",
591
+ },
592
+ [NPCM7XX_CLOCK_APB1_DIVIDER] = {
593
+ .name = "apb1-divider",
594
+ .src_type = CLKSRC_DIV,
595
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
596
+ .divide = shift_by_reg_divisor,
597
+ .reg = NPCM7XX_CLK_CLKDIV2,
598
+ .offset = 24,
599
+ .len = 2,
600
+ .public_name = "apb1-clock",
601
+ },
602
+ [NPCM7XX_CLOCK_APB2_DIVIDER] = {
603
+ .name = "apb2-divider",
604
+ .src_type = CLKSRC_DIV,
605
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
606
+ .divide = shift_by_reg_divisor,
607
+ .reg = NPCM7XX_CLK_CLKDIV2,
608
+ .offset = 26,
609
+ .len = 2,
610
+ .public_name = "apb2-clock",
611
+ },
612
+ [NPCM7XX_CLOCK_APB3_DIVIDER] = {
613
+ .name = "apb3-divider",
614
+ .src_type = CLKSRC_DIV,
615
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
616
+ .divide = shift_by_reg_divisor,
617
+ .reg = NPCM7XX_CLK_CLKDIV2,
618
+ .offset = 28,
619
+ .len = 2,
620
+ .public_name = "apb3-clock",
621
+ },
622
+ [NPCM7XX_CLOCK_APB4_DIVIDER] = {
623
+ .name = "apb4-divider",
624
+ .src_type = CLKSRC_DIV,
625
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
626
+ .divide = shift_by_reg_divisor,
627
+ .reg = NPCM7XX_CLK_CLKDIV2,
628
+ .offset = 30,
629
+ .len = 2,
630
+ .public_name = "apb4-clock",
631
+ },
632
+ [NPCM7XX_CLOCK_APB5_DIVIDER] = {
633
+ .name = "apb5-divider",
634
+ .src_type = CLKSRC_DIV,
635
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
636
+ .divide = shift_by_reg_divisor,
637
+ .reg = NPCM7XX_CLK_CLKDIV2,
638
+ .offset = 22,
639
+ .len = 2,
640
+ .public_name = "apb5-clock",
641
+ },
642
+ [NPCM7XX_CLOCK_CLKOUT_DIVIDER] = {
643
+ .name = "clkout-divider",
644
+ .src_type = CLKSRC_SEL,
645
+ .src_index = NPCM7XX_CLOCK_CLKOUTSEL,
646
+ .divide = divide_by_reg_divisor,
647
+ .reg = NPCM7XX_CLK_CLKDIV2,
648
+ .offset = 16,
649
+ .len = 5,
650
+ .public_name = "clkout",
651
+ },
652
+ [NPCM7XX_CLOCK_UART_DIVIDER] = {
653
+ .name = "uart-divider",
654
+ .src_type = CLKSRC_SEL,
655
+ .src_index = NPCM7XX_CLOCK_UARTCKSEL,
656
+ .divide = divide_by_reg_divisor,
657
+ .reg = NPCM7XX_CLK_CLKDIV1,
658
+ .offset = 16,
659
+ .len = 5,
660
+ .public_name = "uart-clock",
661
+ },
662
+ [NPCM7XX_CLOCK_TIMER_DIVIDER] = {
663
+ .name = "timer-divider",
664
+ .src_type = CLKSRC_SEL,
665
+ .src_index = NPCM7XX_CLOCK_TIMCKSEL,
666
+ .divide = divide_by_reg_divisor,
667
+ .reg = NPCM7XX_CLK_CLKDIV1,
668
+ .offset = 21,
669
+ .len = 5,
670
+ .public_name = "timer-clock",
671
+ },
672
+ [NPCM7XX_CLOCK_ADC_DIVIDER] = {
673
+ .name = "adc-divider",
674
+ .src_type = CLKSRC_DIV,
675
+ .src_index = NPCM7XX_CLOCK_TIMER_DIVIDER,
676
+ .divide = shift_by_reg_divisor,
677
+ .reg = NPCM7XX_CLK_CLKDIV1,
678
+ .offset = 28,
679
+ .len = 3,
680
+ .public_name = "adc-clock",
681
+ },
682
+ [NPCM7XX_CLOCK_MMC_DIVIDER] = {
683
+ .name = "mmc-divider",
684
+ .src_type = CLKSRC_SEL,
685
+ .src_index = NPCM7XX_CLOCK_SDCKSEL,
686
+ .divide = divide_by_reg_divisor,
687
+ .reg = NPCM7XX_CLK_CLKDIV1,
688
+ .offset = 11,
689
+ .len = 5,
690
+ .public_name = "mmc-clock",
691
+ },
692
+ [NPCM7XX_CLOCK_SDHC_DIVIDER] = {
693
+ .name = "sdhc-divider",
694
+ .src_type = CLKSRC_SEL,
695
+ .src_index = NPCM7XX_CLOCK_SDCKSEL,
696
+ .divide = divide_by_reg_divisor_times_2,
697
+ .reg = NPCM7XX_CLK_CLKDIV2,
698
+ .offset = 0,
699
+ .len = 4,
700
+ .public_name = "sdhc-clock",
701
+ },
702
+ [NPCM7XX_CLOCK_GFXM_DIVIDER] = {
703
+ .name = "gfxm-divider",
704
+ .src_type = CLKSRC_SEL,
705
+ .src_index = NPCM7XX_CLOCK_GFXMSEL,
706
+ .divide = divide_by_constant,
707
+ .divisor = 3,
708
+ .public_name = "gfxm-clock",
709
+ },
710
+ [NPCM7XX_CLOCK_UTMI_DIVIDER] = {
711
+ .name = "utmi-divider",
712
+ .src_type = CLKSRC_SEL,
713
+ .src_index = NPCM7XX_CLOCK_SUCKSEL,
714
+ .divide = divide_by_reg_divisor,
715
+ .reg = NPCM7XX_CLK_CLKDIV2,
716
+ .offset = 8,
717
+ .len = 5,
718
+ .public_name = "utmi-clock",
719
+ },
720
+};
721
+
722
+static void npcm7xx_clk_pll_init(Object *obj)
723
+{
724
+ NPCM7xxClockPLLState *pll = NPCM7XX_CLOCK_PLL(obj);
725
+
726
+ pll->clock_in = qdev_init_clock_in(DEVICE(pll), "clock-in",
727
+ npcm7xx_clk_update_pll, pll);
728
+ pll->clock_out = qdev_init_clock_out(DEVICE(pll), "clock-out");
729
+}
730
+
731
+static void npcm7xx_clk_sel_init(Object *obj)
732
+{
733
+ int i;
734
+ NPCM7xxClockSELState *sel = NPCM7XX_CLOCK_SEL(obj);
735
+
736
+ for (i = 0; i < NPCM7XX_CLK_SEL_MAX_INPUT; ++i) {
737
+ sel->clock_in[i] = qdev_init_clock_in(DEVICE(sel),
738
+ g_strdup_printf("clock-in[%d]", i),
739
+ npcm7xx_clk_update_sel, sel);
740
+ }
741
+ sel->clock_out = qdev_init_clock_out(DEVICE(sel), "clock-out");
742
+}
743
+static void npcm7xx_clk_divider_init(Object *obj)
744
+{
745
+ NPCM7xxClockDividerState *div = NPCM7XX_CLOCK_DIVIDER(obj);
746
+
747
+ div->clock_in = qdev_init_clock_in(DEVICE(div), "clock-in",
748
+ npcm7xx_clk_update_divider, div);
749
+ div->clock_out = qdev_init_clock_out(DEVICE(div), "clock-out");
750
+}
751
+
752
+static void npcm7xx_init_clock_pll(NPCM7xxClockPLLState *pll,
753
+ NPCM7xxCLKState *clk, const PLLInitInfo *init_info)
754
+{
755
+ pll->name = init_info->name;
756
+ pll->clk = clk;
757
+ pll->reg = init_info->reg;
758
+ if (init_info->public_name != NULL) {
759
+ qdev_alias_clock(DEVICE(pll), "clock-out", DEVICE(clk),
760
+ init_info->public_name);
761
+ }
762
+}
763
+
764
+static void npcm7xx_init_clock_sel(NPCM7xxClockSELState *sel,
765
+ NPCM7xxCLKState *clk, const SELInitInfo *init_info)
766
+{
767
+ int input_size = init_info->input_size;
768
+
769
+ sel->name = init_info->name;
770
+ sel->clk = clk;
771
+ sel->input_size = init_info->input_size;
772
+ g_assert(input_size <= NPCM7XX_CLK_SEL_MAX_INPUT);
773
+ sel->offset = init_info->offset;
774
+ sel->len = init_info->len;
775
+ if (init_info->public_name != NULL) {
776
+ qdev_alias_clock(DEVICE(sel), "clock-out", DEVICE(clk),
777
+ init_info->public_name);
778
+ }
779
+}
780
+
781
+static void npcm7xx_init_clock_divider(NPCM7xxClockDividerState *div,
782
+ NPCM7xxCLKState *clk, const DividerInitInfo *init_info)
783
+{
784
+ div->name = init_info->name;
785
+ div->clk = clk;
786
+
787
+ div->divide = init_info->divide;
788
+ if (div->divide == divide_by_constant) {
789
+ div->divisor = init_info->divisor;
790
+ } else {
791
+ div->reg = init_info->reg;
792
+ div->offset = init_info->offset;
793
+ div->len = init_info->len;
794
+ }
795
+ if (init_info->public_name != NULL) {
796
+ qdev_alias_clock(DEVICE(div), "clock-out", DEVICE(clk),
797
+ init_info->public_name);
798
+ }
799
+}
800
+
801
+static Clock *npcm7xx_get_clock(NPCM7xxCLKState *clk, ClockSrcType type,
802
+ int index)
803
+{
804
+ switch (type) {
805
+ case CLKSRC_REF:
806
+ return clk->clkref;
807
+ case CLKSRC_PLL:
808
+ return clk->plls[index].clock_out;
809
+ case CLKSRC_SEL:
810
+ return clk->sels[index].clock_out;
811
+ case CLKSRC_DIV:
812
+ return clk->dividers[index].clock_out;
813
+ default:
814
+ g_assert_not_reached();
815
+ }
816
+}
817
+
818
+static void npcm7xx_connect_clocks(NPCM7xxCLKState *clk)
819
+{
820
+ int i, j;
821
+ Clock *src;
822
+
823
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
824
+ src = npcm7xx_get_clock(clk, pll_init_info_list[i].src_type,
825
+ pll_init_info_list[i].src_index);
826
+ clock_set_source(clk->plls[i].clock_in, src);
827
+ }
828
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
829
+ for (j = 0; j < sel_init_info_list[i].input_size; ++j) {
830
+ src = npcm7xx_get_clock(clk, sel_init_info_list[i].src_type[j],
831
+ sel_init_info_list[i].src_index[j]);
832
+ clock_set_source(clk->sels[i].clock_in[j], src);
833
+ }
834
+ }
835
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
836
+ src = npcm7xx_get_clock(clk, divider_init_info_list[i].src_type,
837
+ divider_init_info_list[i].src_index);
838
+ clock_set_source(clk->dividers[i].clock_in, src);
839
+ }
840
+}
841
+
842
static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size)
843
{
844
uint32_t reg = offset / sizeof(uint32_t);
845
@@ -XXX,XX +XXX,XX @@ static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size)
846
*
847
* The 4 LSBs are always zero: (1e9 / 640) << 4 = 25000000.
848
*/
849
- value = (((now_ns - s->ref_ns) / 640) << 4) % NPCM7XX_TIMER_REF_HZ;
850
+ value = (((now_ns - s->ref_ns) / 640) << 4) % NPCM7XX_CLOCK_REF_HZ;
851
break;
852
853
default:
854
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_write(void *opaque, hwaddr offset,
855
value |= (value & PLLCON_LOKS);
856
}
857
}
858
+ /* Only update PLL when it is locked. */
859
+ if (value & PLLCON_LOKI) {
860
+ npcm7xx_clk_update_pll(&s->plls[find_pll_by_reg(reg)]);
861
+ }
862
+ break;
863
+
864
+ case NPCM7XX_CLK_CLKSEL:
865
+ npcm7xx_clk_update_all_sels(s);
866
+ break;
867
+
868
+ case NPCM7XX_CLK_CLKDIV1:
869
+ case NPCM7XX_CLK_CLKDIV2:
870
+ case NPCM7XX_CLK_CLKDIV3:
871
+ npcm7xx_clk_update_all_dividers(s);
872
break;
873
874
case NPCM7XX_CLK_CNTR25M:
875
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_enter_reset(Object *obj, ResetType type)
876
case RESET_TYPE_COLD:
877
memcpy(s->regs, cold_reset_values, sizeof(cold_reset_values));
878
s->ref_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
879
+ npcm7xx_clk_update_all_clocks(s);
880
return;
881
}
882
883
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_enter_reset(Object *obj, ResetType type)
884
__func__, type);
885
}
886
887
+static void npcm7xx_clk_init_clock_hierarchy(NPCM7xxCLKState *s)
888
+{
889
+ int i;
890
+
891
+ s->clkref = qdev_init_clock_in(DEVICE(s), "clkref", NULL, NULL);
892
+
893
+ /* First pass: init all converter modules */
894
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(pll_init_info_list) != NPCM7XX_CLOCK_NR_PLLS);
895
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(sel_init_info_list) != NPCM7XX_CLOCK_NR_SELS);
896
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(divider_init_info_list)
897
+ != NPCM7XX_CLOCK_NR_DIVIDERS);
898
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
899
+ object_initialize_child(OBJECT(s), pll_init_info_list[i].name,
900
+ &s->plls[i], TYPE_NPCM7XX_CLOCK_PLL);
901
+ npcm7xx_init_clock_pll(&s->plls[i], s,
902
+ &pll_init_info_list[i]);
903
+ }
904
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
905
+ object_initialize_child(OBJECT(s), sel_init_info_list[i].name,
906
+ &s->sels[i], TYPE_NPCM7XX_CLOCK_SEL);
907
+ npcm7xx_init_clock_sel(&s->sels[i], s,
908
+ &sel_init_info_list[i]);
909
+ }
910
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
911
+ object_initialize_child(OBJECT(s), divider_init_info_list[i].name,
912
+ &s->dividers[i], TYPE_NPCM7XX_CLOCK_DIVIDER);
913
+ npcm7xx_init_clock_divider(&s->dividers[i], s,
914
+ &divider_init_info_list[i]);
915
+ }
916
+
917
+ /* Second pass: connect converter modules */
918
+ npcm7xx_connect_clocks(s);
919
+
920
+ clock_update_hz(s->clkref, NPCM7XX_CLOCK_REF_HZ);
921
+}
922
+
923
static void npcm7xx_clk_init(Object *obj)
924
{
925
NPCM7xxCLKState *s = NPCM7XX_CLK(obj);
926
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_init(Object *obj)
927
memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s,
928
TYPE_NPCM7XX_CLK, 4 * KiB);
929
sysbus_init_mmio(&s->parent, &s->iomem);
930
- qdev_init_gpio_in_named(DEVICE(s), npcm7xx_clk_perform_watchdog_reset,
931
- NPCM7XX_WATCHDOG_RESET_GPIO_IN, NPCM7XX_NR_WATCHDOGS);
932
}
933
934
-static const VMStateDescription vmstate_npcm7xx_clk = {
935
- .name = "npcm7xx-clk",
936
+static int npcm7xx_clk_post_load(void *opaque, int version_id)
937
+{
938
+ if (version_id >= 1) {
939
+ NPCM7xxCLKState *clk = opaque;
940
+
941
+ npcm7xx_clk_update_all_clocks(clk);
942
+ }
943
+
944
+ return 0;
73
+ return 0;
945
+}
74
+}
946
+
75
+
947
+static void npcm7xx_clk_realize(DeviceState *dev, Error **errp)
76
+static uint64_t gt_phys_cnt_offset(CPUARMState *env)
948
+{
77
+{
949
+ int i;
78
+ if (arm_current_el(env) >= 2) {
950
+ NPCM7xxCLKState *s = NPCM7XX_CLK(dev);
79
+ return 0;
951
+
952
+ qdev_init_gpio_in_named(DEVICE(s), npcm7xx_clk_perform_watchdog_reset,
953
+ NPCM7XX_WATCHDOG_RESET_GPIO_IN, NPCM7XX_NR_WATCHDOGS);
954
+ npcm7xx_clk_init_clock_hierarchy(s);
955
+
956
+ /* Realize child devices */
957
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
958
+ if (!qdev_realize(DEVICE(&s->plls[i]), NULL, errp)) {
959
+ return;
960
+ }
961
+ }
80
+ }
962
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
81
+ return gt_phys_raw_cnt_offset(env);
963
+ if (!qdev_realize(DEVICE(&s->sels[i]), NULL, errp)) {
964
+ return;
965
+ }
966
+ }
967
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
968
+ if (!qdev_realize(DEVICE(&s->dividers[i]), NULL, errp)) {
969
+ return;
970
+ }
971
+ }
972
+}
82
+}
973
+
83
+
974
+static const VMStateDescription vmstate_npcm7xx_clk_pll = {
84
static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
975
+ .name = "npcm7xx-clock-pll",
85
{
976
.version_id = 0,
86
ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
977
.minimum_version_id = 0,
87
@@ -XXX,XX +XXX,XX @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
978
- .fields = (VMStateField[]) {
88
* reset timer to when ISTATUS next has to change
979
- VMSTATE_UINT32_ARRAY(regs, NPCM7xxCLKState, NPCM7XX_CLK_NR_REGS),
89
*/
980
- VMSTATE_INT64(ref_ns, NPCM7xxCLKState),
90
uint64_t offset = timeridx == GTIMER_VIRT ?
981
+ .fields = (VMStateField[]) {
91
- cpu->env.cp15.cntvoff_el2 : 0;
982
+ VMSTATE_CLOCK(clock_in, NPCM7xxClockPLLState),
92
+ cpu->env.cp15.cntvoff_el2 : gt_phys_raw_cnt_offset(&cpu->env);
983
VMSTATE_END_OF_LIST(),
93
uint64_t count = gt_get_countervalue(&cpu->env);
94
/* Note that this must be unsigned 64 bit arithmetic: */
95
int istatus = count - offset >= gt->cval;
96
@@ -XXX,XX +XXX,XX @@ static void gt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri,
97
98
static uint64_t gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
99
{
100
- return gt_get_countervalue(env);
101
+ return gt_get_countervalue(env) - gt_phys_cnt_offset(env);
102
}
103
104
static uint64_t gt_virt_cnt_offset(CPUARMState *env)
105
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
106
case GTIMER_HYPVIRT:
107
offset = gt_virt_cnt_offset(env);
108
break;
109
+ case GTIMER_PHYS:
110
+ offset = gt_phys_cnt_offset(env);
111
+ break;
112
}
113
114
return (uint32_t)(env->cp15.c14_timer[timeridx].cval -
115
@@ -XXX,XX +XXX,XX @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
116
case GTIMER_HYPVIRT:
117
offset = gt_virt_cnt_offset(env);
118
break;
119
+ case GTIMER_PHYS:
120
+ offset = gt_phys_cnt_offset(env);
121
+ break;
122
}
123
124
trace_arm_gt_tval_write(timeridx, value);
125
@@ -XXX,XX +XXX,XX @@ static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
126
R_CNTHCTL_EL1NVVCT_MASK |
127
R_CNTHCTL_EVNTIS_MASK;
128
}
129
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
130
+ valid_mask |= R_CNTHCTL_ECV_MASK;
131
+ }
132
133
/* Clear RES0 bits */
134
value &= valid_mask;
135
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gen_timer_ecv_cp_reginfo[] = {
984
},
136
},
985
};
137
};
986
138
987
+static const VMStateDescription vmstate_npcm7xx_clk_sel = {
139
+static CPAccessResult gt_cntpoff_access(CPUARMState *env,
988
+ .name = "npcm7xx-clock-sel",
140
+ const ARMCPRegInfo *ri,
989
+ .version_id = 0,
141
+ bool isread)
990
+ .minimum_version_id = 0,
991
+ .fields = (VMStateField[]) {
992
+ VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(clock_in, NPCM7xxClockSELState,
993
+ NPCM7XX_CLK_SEL_MAX_INPUT, 0, vmstate_clock, Clock),
994
+ VMSTATE_END_OF_LIST(),
995
+ },
996
+};
997
+
998
+static const VMStateDescription vmstate_npcm7xx_clk_divider = {
999
+ .name = "npcm7xx-clock-divider",
1000
+ .version_id = 0,
1001
+ .minimum_version_id = 0,
1002
+ .fields = (VMStateField[]) {
1003
+ VMSTATE_CLOCK(clock_in, NPCM7xxClockDividerState),
1004
+ VMSTATE_END_OF_LIST(),
1005
+ },
1006
+};
1007
+
1008
+static const VMStateDescription vmstate_npcm7xx_clk = {
1009
+ .name = "npcm7xx-clk",
1010
+ .version_id = 1,
1011
+ .minimum_version_id = 1,
1012
+ .post_load = npcm7xx_clk_post_load,
1013
+ .fields = (VMStateField[]) {
1014
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxCLKState, NPCM7XX_CLK_NR_REGS),
1015
+ VMSTATE_INT64(ref_ns, NPCM7xxCLKState),
1016
+ VMSTATE_CLOCK(clkref, NPCM7xxCLKState),
1017
+ VMSTATE_END_OF_LIST(),
1018
+ },
1019
+};
1020
+
1021
+static void npcm7xx_clk_pll_class_init(ObjectClass *klass, void *data)
1022
+{
142
+{
1023
+ DeviceClass *dc = DEVICE_CLASS(klass);
143
+ if (arm_current_el(env) == 2 && !(env->cp15.scr_el3 & SCR_ECVEN)) {
1024
+
144
+ return CP_ACCESS_TRAP_EL3;
1025
+ dc->desc = "NPCM7xx Clock PLL Module";
145
+ }
1026
+ dc->vmsd = &vmstate_npcm7xx_clk_pll;
146
+ return CP_ACCESS_OK;
1027
+}
147
+}
1028
+
148
+
1029
+static void npcm7xx_clk_sel_class_init(ObjectClass *klass, void *data)
149
+static void gt_cntpoff_write(CPUARMState *env, const ARMCPRegInfo *ri,
150
+ uint64_t value)
1030
+{
151
+{
1031
+ DeviceClass *dc = DEVICE_CLASS(klass);
152
+ ARMCPU *cpu = env_archcpu(env);
1032
+
153
+
1033
+ dc->desc = "NPCM7xx Clock SEL Module";
154
+ trace_arm_gt_cntpoff_write(value);
1034
+ dc->vmsd = &vmstate_npcm7xx_clk_sel;
155
+ raw_write(env, ri, value);
156
+ gt_recalc_timer(cpu, GTIMER_PHYS);
1035
+}
157
+}
1036
+
158
+
1037
+static void npcm7xx_clk_divider_class_init(ObjectClass *klass, void *data)
159
+static const ARMCPRegInfo gen_timer_cntpoff_reginfo = {
1038
+{
160
+ .name = "CNTPOFF_EL2", .state = ARM_CP_STATE_AA64,
1039
+ DeviceClass *dc = DEVICE_CLASS(klass);
161
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 0, .opc2 = 6,
1040
+
162
+ .access = PL2_RW, .type = ARM_CP_IO, .resetvalue = 0,
1041
+ dc->desc = "NPCM7xx Clock Divider Module";
163
+ .accessfn = gt_cntpoff_access, .writefn = gt_cntpoff_write,
1042
+ dc->vmsd = &vmstate_npcm7xx_clk_divider;
164
+ .nv2_redirect_offset = 0x1a8,
1043
+}
165
+ .fieldoffset = offsetof(CPUARMState, cp15.cntpoff_el2),
1044
+
1045
static void npcm7xx_clk_class_init(ObjectClass *klass, void *data)
1046
{
1047
ResettableClass *rc = RESETTABLE_CLASS(klass);
1048
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_class_init(ObjectClass *klass, void *data)
1049
1050
dc->desc = "NPCM7xx Clock Control Registers";
1051
dc->vmsd = &vmstate_npcm7xx_clk;
1052
+ dc->realize = npcm7xx_clk_realize;
1053
rc->phases.enter = npcm7xx_clk_enter_reset;
1054
}
1055
1056
+static const TypeInfo npcm7xx_clk_pll_info = {
1057
+ .name = TYPE_NPCM7XX_CLOCK_PLL,
1058
+ .parent = TYPE_DEVICE,
1059
+ .instance_size = sizeof(NPCM7xxClockPLLState),
1060
+ .instance_init = npcm7xx_clk_pll_init,
1061
+ .class_init = npcm7xx_clk_pll_class_init,
1062
+};
166
+};
1063
+
167
#else
1064
+static const TypeInfo npcm7xx_clk_sel_info = {
168
1065
+ .name = TYPE_NPCM7XX_CLOCK_SEL,
169
/*
1066
+ .parent = TYPE_DEVICE,
170
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
1067
+ .instance_size = sizeof(NPCM7xxClockSELState),
171
if (cpu_isar_feature(aa64_ecv_traps, cpu)) {
1068
+ .instance_init = npcm7xx_clk_sel_init,
172
define_arm_cp_regs(cpu, gen_timer_ecv_cp_reginfo);
1069
+ .class_init = npcm7xx_clk_sel_class_init,
173
}
1070
+};
174
+#ifndef CONFIG_USER_ONLY
1071
+
175
+ if (cpu_isar_feature(aa64_ecv, cpu)) {
1072
+static const TypeInfo npcm7xx_clk_divider_info = {
176
+ define_one_arm_cp_reg(cpu, &gen_timer_cntpoff_reginfo);
1073
+ .name = TYPE_NPCM7XX_CLOCK_DIVIDER,
177
+ }
1074
+ .parent = TYPE_DEVICE,
178
+#endif
1075
+ .instance_size = sizeof(NPCM7xxClockDividerState),
179
if (arm_feature(env, ARM_FEATURE_VAPA)) {
1076
+ .instance_init = npcm7xx_clk_divider_init,
180
ARMCPRegInfo vapa_cp_reginfo[] = {
1077
+ .class_init = npcm7xx_clk_divider_class_init,
181
{ .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0,
1078
+};
182
diff --git a/target/arm/trace-events b/target/arm/trace-events
1079
+
183
index XXXXXXX..XXXXXXX 100644
1080
static const TypeInfo npcm7xx_clk_info = {
184
--- a/target/arm/trace-events
1081
.name = TYPE_NPCM7XX_CLK,
185
+++ b/target/arm/trace-events
1082
.parent = TYPE_SYS_BUS_DEVICE,
186
@@ -XXX,XX +XXX,XX @@ arm_gt_tval_write(int timer, uint64_t value) "gt_tval_write: timer %d value 0x%"
1083
@@ -XXX,XX +XXX,XX @@ static const TypeInfo npcm7xx_clk_info = {
187
arm_gt_ctl_write(int timer, uint64_t value) "gt_ctl_write: timer %d value 0x%" PRIx64
1084
188
arm_gt_imask_toggle(int timer) "gt_ctl_write: timer %d IMASK toggle"
1085
static void npcm7xx_clk_register_type(void)
189
arm_gt_cntvoff_write(uint64_t value) "gt_cntvoff_write: value 0x%" PRIx64
1086
{
190
+arm_gt_cntpoff_write(uint64_t value) "gt_cntpoff_write: value 0x%" PRIx64
1087
+ type_register_static(&npcm7xx_clk_pll_info);
191
arm_gt_update_irq(int timer, int irqstate) "gt_update_irq: timer %d irqstate %d"
1088
+ type_register_static(&npcm7xx_clk_sel_info);
192
1089
+ type_register_static(&npcm7xx_clk_divider_info);
193
# kvm.c
1090
type_register_static(&npcm7xx_clk_info);
1091
}
1092
type_init(npcm7xx_clk_register_type);
1093
--
194
--
1094
2.20.1
195
2.34.1
1095
1096
diff view generated by jsdifflib
1
In commit 1982e1602d15 we added a new qemu-storage-daemon(1) manpage.
1
Enable all FEAT_ECV features on the 'max' CPU.
2
At the moment new manpages have to be listed both in the conf.py for
3
Sphinx and also in docs/meson.build for Meson. We forgot the second
4
of those -- correct the omission.
5
2
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
4
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210108161416.21129-2-peter.maydell@linaro.org
6
Message-id: 20240301183219.2424889-9-peter.maydell@linaro.org
10
---
7
---
11
docs/meson.build | 1 +
8
docs/system/arm/emulation.rst | 1 +
12
1 file changed, 1 insertion(+)
9
target/arm/tcg/cpu64.c | 1 +
10
2 files changed, 2 insertions(+)
13
11
14
diff --git a/docs/meson.build b/docs/meson.build
12
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
15
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
16
--- a/docs/meson.build
14
--- a/docs/system/arm/emulation.rst
17
+++ b/docs/meson.build
15
+++ b/docs/system/arm/emulation.rst
18
@@ -XXX,XX +XXX,XX @@ if build_docs
16
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
19
'qemu-img.1': (have_tools ? 'man1' : ''),
17
- FEAT_DotProd (Advanced SIMD dot product instructions)
20
'qemu-nbd.8': (have_tools ? 'man8' : ''),
18
- FEAT_DoubleFault (Double Fault Extension)
21
'qemu-pr-helper.8': (have_tools ? 'man8' : ''),
19
- FEAT_E0PD (Preventing EL0 access to halves of address maps)
22
+ 'qemu-storage-daemon.1': (have_tools ? 'man1' : ''),
20
+- FEAT_ECV (Enhanced Counter Virtualization)
23
'qemu-trace-stap.1': (config_host.has_key('CONFIG_TRACE_SYSTEMTAP') ? 'man1' : ''),
21
- FEAT_EPAC (Enhanced pointer authentication)
24
'virtfs-proxy-helper.1': (have_virtfs_proxy_helper ? 'man1' : ''),
22
- FEAT_ETS (Enhanced Translation Synchronization)
25
'virtiofsd.1': (have_virtiofsd ? 'man1' : ''),
23
- FEAT_EVT (Enhanced Virtualization Traps)
24
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/tcg/cpu64.c
27
+++ b/target/arm/tcg/cpu64.c
28
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
29
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN64_2, 2); /* 64k stage2 supported */
30
t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 2); /* 4k stage2 supported */
31
t = FIELD_DP64(t, ID_AA64MMFR0, FGT, 1); /* FEAT_FGT */
32
+ t = FIELD_DP64(t, ID_AA64MMFR0, ECV, 2); /* FEAT_ECV */
33
cpu->isar.id_aa64mmfr0 = t;
34
35
t = cpu->isar.id_aa64mmfr1;
26
--
36
--
27
2.20.1
37
2.34.1
28
38
29
39
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
The PWM module is part of NPCM7XX module. Each NPCM7XX module has two
3
Features supported :
4
identical PWM modules. Each module contains 4 PWM entries. Each PWM has
4
- the 8 STM32L4x5 GPIOs are initialized with their reset values
5
two outputs: frequency and duty_cycle. Both are computed using inputs
5
(except IDR, see below)
6
from software side.
6
- input mode : setting a pin in input mode "externally" (using input
7
irqs) results in an out irq (transmitted to SYSCFG)
8
- output mode : setting a bit in ODR sets the corresponding out irq
9
(if this line is configured in output mode)
10
- pull-up, pull-down
11
- push-pull, open-drain
7
12
8
This module does not model detail pulse signals since it is expensive.
13
Difference with the real GPIOs :
9
It also does not model interrupts and watchdogs that are dependant on
14
- Alternate Function and Analog mode aren't implemented :
10
the detail models. The interfaces for these are left in the module so
15
pins in AF/Analog behave like pins in input mode
11
that anyone in need for these functionalities can implement on their
16
- floating pins stay at their last value
12
own.
17
- register IDR reset values differ from the real one :
18
values are coherent with the other registers reset values
19
and the fact that AF/Analog modes aren't implemented
20
- setting I/O output speed isn't supported
21
- locking port bits isn't supported
22
- ADC function isn't supported
23
- GPIOH has 16 pins instead of 2 pins
24
- writing to registers LCKR, AFRL, AFRH and ASCR is ineffective
13
25
14
The user can read the duty cycle and frequency using qom-get command.
26
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
15
27
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
16
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
28
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
17
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
29
Acked-by: Alistair Francis <alistair.francis@wdc.com>
18
Signed-off-by: Hao Wu <wuhaotsh@google.com>
30
Message-id: 20240305210444.310665-2-ines.varhol@telecom-paris.fr
19
Message-id: 20210108190945.949196-5-wuhaotsh@google.com
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
31
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
32
---
23
docs/system/arm/nuvoton.rst | 2 +-
33
MAINTAINERS | 1 +
24
include/hw/arm/npcm7xx.h | 2 +
34
docs/system/arm/b-l475e-iot01a.rst | 2 +-
25
include/hw/misc/npcm7xx_pwm.h | 105 +++++++
35
include/hw/gpio/stm32l4x5_gpio.h | 70 +++++
26
hw/arm/npcm7xx.c | 26 +-
36
hw/gpio/stm32l4x5_gpio.c | 477 +++++++++++++++++++++++++++++
27
hw/misc/npcm7xx_pwm.c | 550 ++++++++++++++++++++++++++++++++++
37
hw/gpio/Kconfig | 3 +
28
hw/misc/meson.build | 1 +
38
hw/gpio/meson.build | 1 +
29
hw/misc/trace-events | 6 +
39
hw/gpio/trace-events | 6 +
30
7 files changed, 689 insertions(+), 3 deletions(-)
40
7 files changed, 559 insertions(+), 1 deletion(-)
31
create mode 100644 include/hw/misc/npcm7xx_pwm.h
41
create mode 100644 include/hw/gpio/stm32l4x5_gpio.h
32
create mode 100644 hw/misc/npcm7xx_pwm.c
42
create mode 100644 hw/gpio/stm32l4x5_gpio.c
33
43
34
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
44
diff --git a/MAINTAINERS b/MAINTAINERS
35
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
36
--- a/docs/system/arm/nuvoton.rst
46
--- a/MAINTAINERS
37
+++ b/docs/system/arm/nuvoton.rst
47
+++ b/MAINTAINERS
38
@@ -XXX,XX +XXX,XX @@ Supported devices
48
@@ -XXX,XX +XXX,XX @@ F: hw/arm/stm32l4x5_soc.c
39
* USB host (USBH)
49
F: hw/misc/stm32l4x5_exti.c
40
* GPIO controller
50
F: hw/misc/stm32l4x5_syscfg.c
41
* Analog to Digital Converter (ADC)
51
F: hw/misc/stm32l4x5_rcc.c
42
+ * Pulse Width Modulation (PWM)
52
+F: hw/gpio/stm32l4x5_gpio.c
53
F: include/hw/*/stm32l4x5_*.h
54
55
B-L475E-IOT01A IoT Node
56
diff --git a/docs/system/arm/b-l475e-iot01a.rst b/docs/system/arm/b-l475e-iot01a.rst
57
index XXXXXXX..XXXXXXX 100644
58
--- a/docs/system/arm/b-l475e-iot01a.rst
59
+++ b/docs/system/arm/b-l475e-iot01a.rst
60
@@ -XXX,XX +XXX,XX @@ Currently B-L475E-IOT01A machine's only supports the following devices:
61
- STM32L4x5 EXTI (Extended interrupts and events controller)
62
- STM32L4x5 SYSCFG (System configuration controller)
63
- STM32L4x5 RCC (Reset and clock control)
64
+- STM32L4x5 GPIOs (General-purpose I/Os)
43
65
44
Missing devices
66
Missing devices
45
---------------
67
"""""""""""""""
46
@@ -XXX,XX +XXX,XX @@ Missing devices
68
@@ -XXX,XX +XXX,XX @@ Missing devices
47
* Peripheral SPI controller (PSPI)
69
The B-L475E-IOT01A does *not* support the following devices:
48
* SD/MMC host
70
49
* PECI interface
71
- Serial ports (UART)
50
- * Pulse Width Modulation (PWM)
72
-- General-purpose I/Os (GPIO)
51
* Tachometer
73
- Analog to Digital Converter (ADC)
52
* PCI and PCIe root complex and bridges
74
- SPI controller
53
* VDM and MCTP support
75
- Timer controller (TIMER)
54
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
76
diff --git a/include/hw/gpio/stm32l4x5_gpio.h b/include/hw/gpio/stm32l4x5_gpio.h
55
index XXXXXXX..XXXXXXX 100644
56
--- a/include/hw/arm/npcm7xx.h
57
+++ b/include/hw/arm/npcm7xx.h
58
@@ -XXX,XX +XXX,XX @@
59
#include "hw/mem/npcm7xx_mc.h"
60
#include "hw/misc/npcm7xx_clk.h"
61
#include "hw/misc/npcm7xx_gcr.h"
62
+#include "hw/misc/npcm7xx_pwm.h"
63
#include "hw/misc/npcm7xx_rng.h"
64
#include "hw/nvram/npcm7xx_otp.h"
65
#include "hw/timer/npcm7xx_timer.h"
66
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
67
NPCM7xxCLKState clk;
68
NPCM7xxTimerCtrlState tim[3];
69
NPCM7xxADCState adc;
70
+ NPCM7xxPWMState pwm[2];
71
NPCM7xxOTPState key_storage;
72
NPCM7xxOTPState fuse_array;
73
NPCM7xxMCState mc;
74
diff --git a/include/hw/misc/npcm7xx_pwm.h b/include/hw/misc/npcm7xx_pwm.h
75
new file mode 100644
77
new file mode 100644
76
index XXXXXXX..XXXXXXX
78
index XXXXXXX..XXXXXXX
77
--- /dev/null
79
--- /dev/null
78
+++ b/include/hw/misc/npcm7xx_pwm.h
80
+++ b/include/hw/gpio/stm32l4x5_gpio.h
79
@@ -XXX,XX +XXX,XX @@
81
@@ -XXX,XX +XXX,XX @@
80
+/*
82
+/*
81
+ * Nuvoton NPCM7xx PWM Module
83
+ * STM32L4x5 GPIO (General Purpose Input/Ouput)
82
+ *
84
+ *
83
+ * Copyright 2020 Google LLC
85
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
86
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
84
+ *
87
+ *
85
+ * This program is free software; you can redistribute it and/or modify it
88
+ * SPDX-License-Identifier: GPL-2.0-or-later
86
+ * under the terms of the GNU General Public License as published by the
87
+ * Free Software Foundation; either version 2 of the License, or
88
+ * (at your option) any later version.
89
+ *
89
+ *
90
+ * This program is distributed in the hope that it will be useful, but WITHOUT
90
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
91
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
91
+ * See the COPYING file in the top-level directory.
92
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
93
+ * for more details.
94
+ */
92
+ */
95
+#ifndef NPCM7XX_PWM_H
93
+
96
+#define NPCM7XX_PWM_H
94
+/*
97
+
95
+ * The reference used is the STMicroElectronics RM0351 Reference manual
98
+#include "hw/clock.h"
96
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
97
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
98
+ */
99
+
100
+#ifndef HW_STM32L4X5_GPIO_H
101
+#define HW_STM32L4X5_GPIO_H
102
+
99
+#include "hw/sysbus.h"
103
+#include "hw/sysbus.h"
100
+#include "hw/irq.h"
104
+#include "qom/object.h"
101
+
105
+
102
+/* Each PWM module holds 4 PWM channels. */
106
+#define TYPE_STM32L4X5_GPIO "stm32l4x5-gpio"
103
+#define NPCM7XX_PWM_PER_MODULE 4
107
+OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5GpioState, STM32L4X5_GPIO)
104
+
108
+
105
+/*
109
+#define GPIO_NUM_PINS 16
106
+ * Number of registers in one pwm module. Don't change this without increasing
110
+
107
+ * the version_id in vmstate.
111
+struct Stm32l4x5GpioState {
108
+ */
112
+ SysBusDevice parent_obj;
109
+#define NPCM7XX_PWM_NR_REGS (0x54 / sizeof(uint32_t))
113
+
110
+
114
+ MemoryRegion mmio;
111
+/*
115
+
112
+ * The maximum duty values. Each duty unit represents 1/NPCM7XX_PWM_MAX_DUTY
116
+ /* GPIO registers */
113
+ * cycles. For example, if NPCM7XX_PWM_MAX_DUTY=1,000,000 and a PWM has a duty
117
+ uint32_t moder;
114
+ * value of 100,000 the duty cycle for that PWM is 10%.
118
+ uint32_t otyper;
115
+ */
119
+ uint32_t ospeedr;
116
+#define NPCM7XX_PWM_MAX_DUTY 1000000
120
+ uint32_t pupdr;
117
+
121
+ uint32_t idr;
118
+typedef struct NPCM7xxPWMState NPCM7xxPWMState;
122
+ uint32_t odr;
119
+
123
+ uint32_t lckr;
120
+/**
124
+ uint32_t afrl;
121
+ * struct NPCM7xxPWM - The state of a single PWM channel.
125
+ uint32_t afrh;
122
+ * @module: The PWM module that contains this channel.
126
+ uint32_t ascr;
123
+ * @irq: GIC interrupt line to fire on expiration if enabled.
127
+
124
+ * @running: Whether this PWM channel is generating output.
128
+ /* GPIO registers reset values */
125
+ * @inverted: Whether this PWM channel is inverted.
129
+ uint32_t moder_reset;
126
+ * @index: The index of this PWM channel.
130
+ uint32_t ospeedr_reset;
127
+ * @cnr: The counter register.
131
+ uint32_t pupdr_reset;
128
+ * @cmr: The comparator register.
132
+
129
+ * @pdr: The data register.
133
+ /*
130
+ * @pwdr: The watchdog register.
134
+ * External driving of pins.
131
+ * @freq: The frequency of this PWM channel.
135
+ * The pins can be set externally through the device
132
+ * @duty: The duty cycle of this PWM channel. One unit represents
136
+ * anonymous input GPIOs lines under certain conditions.
133
+ * 1/NPCM7XX_MAX_DUTY cycles.
137
+ * The pin must not be in push-pull output mode,
134
+ */
138
+ * and can't be set high in open-drain mode.
135
+typedef struct NPCM7xxPWM {
139
+ * Pins driven externally and configured to
136
+ NPCM7xxPWMState *module;
140
+ * output mode will in general be "disconnected"
137
+
141
+ * (see `get_gpio_pinmask_to_disconnect()`)
138
+ qemu_irq irq;
142
+ */
139
+
143
+ uint16_t disconnected_pins;
140
+ bool running;
144
+ uint16_t pins_connected_high;
141
+ bool inverted;
145
+
142
+
146
+ char *name;
143
+ uint8_t index;
147
+ Clock *clk;
144
+ uint32_t cnr;
148
+ qemu_irq pin[GPIO_NUM_PINS];
145
+ uint32_t cmr;
146
+ uint32_t pdr;
147
+ uint32_t pwdr;
148
+
149
+ uint32_t freq;
150
+ uint32_t duty;
151
+} NPCM7xxPWM;
152
+
153
+/**
154
+ * struct NPCM7xxPWMState - Pulse Width Modulation device state.
155
+ * @parent: System bus device.
156
+ * @iomem: Memory region through which registers are accessed.
157
+ * @clock: The PWM clock.
158
+ * @pwm: The PWM channels owned by this module.
159
+ * @ppr: The prescaler register.
160
+ * @csr: The clock selector register.
161
+ * @pcr: The control register.
162
+ * @pier: The interrupt enable register.
163
+ * @piir: The interrupt indication register.
164
+ */
165
+struct NPCM7xxPWMState {
166
+ SysBusDevice parent;
167
+
168
+ MemoryRegion iomem;
169
+
170
+ Clock *clock;
171
+ NPCM7xxPWM pwm[NPCM7XX_PWM_PER_MODULE];
172
+
173
+ uint32_t ppr;
174
+ uint32_t csr;
175
+ uint32_t pcr;
176
+ uint32_t pier;
177
+ uint32_t piir;
178
+};
149
+};
179
+
150
+
180
+#define TYPE_NPCM7XX_PWM "npcm7xx-pwm"
151
+#endif
181
+#define NPCM7XX_PWM(obj) \
152
diff --git a/hw/gpio/stm32l4x5_gpio.c b/hw/gpio/stm32l4x5_gpio.c
182
+ OBJECT_CHECK(NPCM7xxPWMState, (obj), TYPE_NPCM7XX_PWM)
183
+
184
+#endif /* NPCM7XX_PWM_H */
185
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
186
index XXXXXXX..XXXXXXX 100644
187
--- a/hw/arm/npcm7xx.c
188
+++ b/hw/arm/npcm7xx.c
189
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
190
NPCM7XX_WDG2_IRQ, /* Timer Module 2 Watchdog */
191
NPCM7XX_EHCI_IRQ = 61,
192
NPCM7XX_OHCI_IRQ = 62,
193
+ NPCM7XX_PWM0_IRQ = 93, /* PWM module 0 */
194
+ NPCM7XX_PWM1_IRQ, /* PWM module 1 */
195
NPCM7XX_GPIO0_IRQ = 116,
196
NPCM7XX_GPIO1_IRQ,
197
NPCM7XX_GPIO2_IRQ,
198
@@ -XXX,XX +XXX,XX @@ static const hwaddr npcm7xx_fiu3_flash_addr[] = {
199
0xb8000000, /* CS3 */
200
};
201
202
+/* Register base address for each PWM Module */
203
+static const hwaddr npcm7xx_pwm_addr[] = {
204
+ 0xf0103000,
205
+ 0xf0104000,
206
+};
207
+
208
static const struct {
209
hwaddr regs_addr;
210
uint32_t unconnected_pins;
211
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
212
object_initialize_child(obj, npcm7xx_fiu[i].name, &s->fiu[i],
213
TYPE_NPCM7XX_FIU);
214
}
215
+
216
+ for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
217
+ object_initialize_child(obj, "pwm[*]", &s->pwm[i], TYPE_NPCM7XX_PWM);
218
+ }
219
}
220
221
static void npcm7xx_realize(DeviceState *dev, Error **errp)
222
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
223
sysbus_connect_irq(SYS_BUS_DEVICE(&s->ohci), 0,
224
npcm7xx_irq(s, NPCM7XX_OHCI_IRQ));
225
226
+ /* PWM Modules. Cannot fail. */
227
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_pwm_addr) != ARRAY_SIZE(s->pwm));
228
+ for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
229
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->pwm[i]);
230
+
231
+ qdev_connect_clock_in(DEVICE(&s->pwm[i]), "clock", qdev_get_clock_out(
232
+ DEVICE(&s->clk), "apb3-clock"));
233
+ sysbus_realize(sbd, &error_abort);
234
+ sysbus_mmio_map(sbd, 0, npcm7xx_pwm_addr[i]);
235
+ sysbus_connect_irq(sbd, i, npcm7xx_irq(s, NPCM7XX_PWM0_IRQ + i));
236
+ }
237
+
238
/*
239
* Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
240
* specified, but this is a programming error.
241
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
242
create_unimplemented_device("npcm7xx.peci", 0xf0100000, 4 * KiB);
243
create_unimplemented_device("npcm7xx.siox[1]", 0xf0101000, 4 * KiB);
244
create_unimplemented_device("npcm7xx.siox[2]", 0xf0102000, 4 * KiB);
245
- create_unimplemented_device("npcm7xx.pwm[0]", 0xf0103000, 4 * KiB);
246
- create_unimplemented_device("npcm7xx.pwm[1]", 0xf0104000, 4 * KiB);
247
create_unimplemented_device("npcm7xx.mft[0]", 0xf0180000, 4 * KiB);
248
create_unimplemented_device("npcm7xx.mft[1]", 0xf0181000, 4 * KiB);
249
create_unimplemented_device("npcm7xx.mft[2]", 0xf0182000, 4 * KiB);
250
diff --git a/hw/misc/npcm7xx_pwm.c b/hw/misc/npcm7xx_pwm.c
251
new file mode 100644
153
new file mode 100644
252
index XXXXXXX..XXXXXXX
154
index XXXXXXX..XXXXXXX
253
--- /dev/null
155
--- /dev/null
254
+++ b/hw/misc/npcm7xx_pwm.c
156
+++ b/hw/gpio/stm32l4x5_gpio.c
255
@@ -XXX,XX +XXX,XX @@
157
@@ -XXX,XX +XXX,XX @@
256
+/*
158
+/*
257
+ * Nuvoton NPCM7xx PWM Module
159
+ * STM32L4x5 GPIO (General Purpose Input/Ouput)
258
+ *
160
+ *
259
+ * Copyright 2020 Google LLC
161
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
162
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
260
+ *
163
+ *
261
+ * This program is free software; you can redistribute it and/or modify it
164
+ * SPDX-License-Identifier: GPL-2.0-or-later
262
+ * under the terms of the GNU General Public License as published by the
263
+ * Free Software Foundation; either version 2 of the License, or
264
+ * (at your option) any later version.
265
+ *
165
+ *
266
+ * This program is distributed in the hope that it will be useful, but WITHOUT
166
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
267
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
167
+ * See the COPYING file in the top-level directory.
268
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
269
+ * for more details.
270
+ */
168
+ */
271
+
169
+
170
+/*
171
+ * The reference used is the STMicroElectronics RM0351 Reference manual
172
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
173
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
174
+ */
175
+
272
+#include "qemu/osdep.h"
176
+#include "qemu/osdep.h"
177
+#include "qemu/log.h"
178
+#include "hw/gpio/stm32l4x5_gpio.h"
273
+#include "hw/irq.h"
179
+#include "hw/irq.h"
274
+#include "hw/qdev-clock.h"
180
+#include "hw/qdev-clock.h"
275
+#include "hw/qdev-properties.h"
181
+#include "hw/qdev-properties.h"
276
+#include "hw/misc/npcm7xx_pwm.h"
182
+#include "qapi/visitor.h"
277
+#include "hw/registerfields.h"
183
+#include "qapi/error.h"
278
+#include "migration/vmstate.h"
184
+#include "migration/vmstate.h"
279
+#include "qemu/bitops.h"
280
+#include "qemu/error-report.h"
281
+#include "qemu/log.h"
282
+#include "qemu/module.h"
283
+#include "qemu/units.h"
284
+#include "trace.h"
185
+#include "trace.h"
285
+
186
+
286
+REG32(NPCM7XX_PWM_PPR, 0x00);
187
+#define GPIO_MODER 0x00
287
+REG32(NPCM7XX_PWM_CSR, 0x04);
188
+#define GPIO_OTYPER 0x04
288
+REG32(NPCM7XX_PWM_PCR, 0x08);
189
+#define GPIO_OSPEEDR 0x08
289
+REG32(NPCM7XX_PWM_CNR0, 0x0c);
190
+#define GPIO_PUPDR 0x0C
290
+REG32(NPCM7XX_PWM_CMR0, 0x10);
191
+#define GPIO_IDR 0x10
291
+REG32(NPCM7XX_PWM_PDR0, 0x14);
192
+#define GPIO_ODR 0x14
292
+REG32(NPCM7XX_PWM_CNR1, 0x18);
193
+#define GPIO_BSRR 0x18
293
+REG32(NPCM7XX_PWM_CMR1, 0x1c);
194
+#define GPIO_LCKR 0x1C
294
+REG32(NPCM7XX_PWM_PDR1, 0x20);
195
+#define GPIO_AFRL 0x20
295
+REG32(NPCM7XX_PWM_CNR2, 0x24);
196
+#define GPIO_AFRH 0x24
296
+REG32(NPCM7XX_PWM_CMR2, 0x28);
197
+#define GPIO_BRR 0x28
297
+REG32(NPCM7XX_PWM_PDR2, 0x2c);
198
+#define GPIO_ASCR 0x2C
298
+REG32(NPCM7XX_PWM_CNR3, 0x30);
199
+
299
+REG32(NPCM7XX_PWM_CMR3, 0x34);
200
+/* 0b11111111_11111111_00000000_00000000 */
300
+REG32(NPCM7XX_PWM_PDR3, 0x38);
201
+#define RESERVED_BITS_MASK 0xFFFF0000
301
+REG32(NPCM7XX_PWM_PIER, 0x3c);
202
+
302
+REG32(NPCM7XX_PWM_PIIR, 0x40);
203
+static void update_gpio_idr(Stm32l4x5GpioState *s);
303
+REG32(NPCM7XX_PWM_PWDR0, 0x44);
204
+
304
+REG32(NPCM7XX_PWM_PWDR1, 0x48);
205
+static bool is_pull_up(Stm32l4x5GpioState *s, unsigned pin)
305
+REG32(NPCM7XX_PWM_PWDR2, 0x4c);
206
+{
306
+REG32(NPCM7XX_PWM_PWDR3, 0x50);
207
+ return extract32(s->pupdr, 2 * pin, 2) == 1;
307
+
208
+}
308
+/* Register field definitions. */
209
+
309
+#define NPCM7XX_PPR(rv, index) extract32((rv), npcm7xx_ppr_base[index], 8)
210
+static bool is_pull_down(Stm32l4x5GpioState *s, unsigned pin)
310
+#define NPCM7XX_CSR(rv, index) extract32((rv), npcm7xx_csr_base[index], 3)
211
+{
311
+#define NPCM7XX_CH(rv, index) extract32((rv), npcm7xx_ch_base[index], 4)
212
+ return extract32(s->pupdr, 2 * pin, 2) == 2;
312
+#define NPCM7XX_CH_EN BIT(0)
213
+}
313
+#define NPCM7XX_CH_INV BIT(2)
214
+
314
+#define NPCM7XX_CH_MOD BIT(3)
215
+static bool is_output(Stm32l4x5GpioState *s, unsigned pin)
315
+
216
+{
316
+/* Offset of each PWM channel's prescaler in the PPR register. */
217
+ return extract32(s->moder, 2 * pin, 2) == 1;
317
+static const int npcm7xx_ppr_base[] = { 0, 0, 8, 8 };
218
+}
318
+/* Offset of each PWM channel's clock selector in the CSR register. */
219
+
319
+static const int npcm7xx_csr_base[] = { 0, 4, 8, 12 };
220
+static bool is_open_drain(Stm32l4x5GpioState *s, unsigned pin)
320
+/* Offset of each PWM channel's control variable in the PCR register. */
221
+{
321
+static const int npcm7xx_ch_base[] = { 0, 8, 12, 16 };
222
+ return extract32(s->otyper, pin, 1) == 1;
322
+
223
+}
323
+static uint32_t npcm7xx_pwm_calculate_freq(NPCM7xxPWM *p)
224
+
324
+{
225
+static bool is_push_pull(Stm32l4x5GpioState *s, unsigned pin)
325
+ uint32_t ppr;
226
+{
326
+ uint32_t csr;
227
+ return extract32(s->otyper, pin, 1) == 0;
327
+ uint32_t freq;
228
+}
328
+
229
+
329
+ if (!p->running) {
230
+static void stm32l4x5_gpio_reset_hold(Object *obj)
330
+ return 0;
231
+{
331
+ }
232
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
332
+
233
+
333
+ csr = NPCM7XX_CSR(p->module->csr, p->index);
234
+ s->moder = s->moder_reset;
334
+ ppr = NPCM7XX_PPR(p->module->ppr, p->index);
235
+ s->otyper = 0x00000000;
335
+ freq = clock_get_hz(p->module->clock);
236
+ s->ospeedr = s->ospeedr_reset;
336
+ freq /= ppr + 1;
237
+ s->pupdr = s->pupdr_reset;
337
+ /* csr can only be 0~4 */
238
+ s->idr = 0x00000000;
338
+ if (csr > 4) {
239
+ s->odr = 0x00000000;
339
+ qemu_log_mask(LOG_GUEST_ERROR,
240
+ s->lckr = 0x00000000;
340
+ "%s: invalid csr value %u\n",
241
+ s->afrl = 0x00000000;
341
+ __func__, csr);
242
+ s->afrh = 0x00000000;
342
+ csr = 4;
243
+ s->ascr = 0x00000000;
343
+ }
244
+
344
+ /* freq won't be changed if csr == 4. */
245
+ s->disconnected_pins = 0xFFFF;
345
+ if (csr < 4) {
246
+ s->pins_connected_high = 0x0000;
346
+ freq >>= csr + 1;
247
+ update_gpio_idr(s);
347
+ }
248
+}
348
+
249
+
349
+ return freq / (p->cnr + 1);
250
+static void stm32l4x5_gpio_set(void *opaque, int line, int level)
350
+}
251
+{
351
+
252
+ Stm32l4x5GpioState *s = opaque;
352
+static uint32_t npcm7xx_pwm_calculate_duty(NPCM7xxPWM *p)
253
+ /*
353
+{
254
+ * The pin isn't set if line is configured in output mode
354
+ uint64_t duty;
255
+ * except if level is 0 and the output is open-drain.
355
+
256
+ * This way there will be no short-circuit prone situations.
356
+ if (p->running) {
257
+ */
357
+ if (p->cnr == 0) {
258
+ if (is_output(s, line) && !(is_open_drain(s, line) && (level == 0))) {
358
+ duty = 0;
259
+ qemu_log_mask(LOG_GUEST_ERROR, "Line %d can't be driven externally\n",
359
+ } else if (p->cmr >= p->cnr) {
260
+ line);
360
+ duty = NPCM7XX_PWM_MAX_DUTY;
261
+ return;
262
+ }
263
+
264
+ s->disconnected_pins &= ~(1 << line);
265
+ if (level) {
266
+ s->pins_connected_high |= (1 << line);
267
+ } else {
268
+ s->pins_connected_high &= ~(1 << line);
269
+ }
270
+ trace_stm32l4x5_gpio_pins(s->name, s->disconnected_pins,
271
+ s->pins_connected_high);
272
+ update_gpio_idr(s);
273
+}
274
+
275
+
276
+static void update_gpio_idr(Stm32l4x5GpioState *s)
277
+{
278
+ uint32_t new_idr_mask = 0;
279
+ uint32_t new_idr = s->odr;
280
+ uint32_t old_idr = s->idr;
281
+ int new_pin_state, old_pin_state;
282
+
283
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
284
+ if (is_output(s, i)) {
285
+ if (is_push_pull(s, i)) {
286
+ new_idr_mask |= (1 << i);
287
+ } else if (!(s->odr & (1 << i))) {
288
+ /* open-drain ODR 0 */
289
+ new_idr_mask |= (1 << i);
290
+ /* open-drain ODR 1 */
291
+ } else if (!(s->disconnected_pins & (1 << i)) &&
292
+ !(s->pins_connected_high & (1 << i))) {
293
+ /* open-drain ODR 1 with pin connected low */
294
+ new_idr_mask |= (1 << i);
295
+ new_idr &= ~(1 << i);
296
+ /* open-drain ODR 1 with unactive pin */
297
+ } else if (is_pull_up(s, i)) {
298
+ new_idr_mask |= (1 << i);
299
+ } else if (is_pull_down(s, i)) {
300
+ new_idr_mask |= (1 << i);
301
+ new_idr &= ~(1 << i);
302
+ }
303
+ /*
304
+ * The only case left is for open-drain ODR 1
305
+ * with unactive pin without pull-up or pull-down :
306
+ * the value is floating.
307
+ */
308
+ /* input or analog mode with connected pin */
309
+ } else if (!(s->disconnected_pins & (1 << i))) {
310
+ if (s->pins_connected_high & (1 << i)) {
311
+ /* pin high */
312
+ new_idr_mask |= (1 << i);
313
+ new_idr |= (1 << i);
314
+ } else {
315
+ /* pin low */
316
+ new_idr_mask |= (1 << i);
317
+ new_idr &= ~(1 << i);
318
+ }
319
+ /* input or analog mode with disconnected pin */
361
+ } else {
320
+ } else {
362
+ duty = NPCM7XX_PWM_MAX_DUTY * (p->cmr + 1) / (p->cnr + 1);
321
+ if (is_pull_up(s, i)) {
322
+ /* pull-up */
323
+ new_idr_mask |= (1 << i);
324
+ new_idr |= (1 << i);
325
+ } else if (is_pull_down(s, i)) {
326
+ /* pull-down */
327
+ new_idr_mask |= (1 << i);
328
+ new_idr &= ~(1 << i);
329
+ }
330
+ /*
331
+ * The only case left is for a disconnected pin
332
+ * without pull-up or pull-down :
333
+ * the value is floating.
334
+ */
363
+ }
335
+ }
364
+ } else {
336
+ }
365
+ duty = 0;
337
+
366
+ }
338
+ s->idr = (old_idr & ~new_idr_mask) | (new_idr & new_idr_mask);
367
+
339
+ trace_stm32l4x5_gpio_update_idr(s->name, old_idr, s->idr);
368
+ if (p->inverted) {
340
+
369
+ duty = NPCM7XX_PWM_MAX_DUTY - duty;
341
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
370
+ }
342
+ if (new_idr_mask & (1 << i)) {
371
+
343
+ new_pin_state = (new_idr & (1 << i)) > 0;
372
+ return duty;
344
+ old_pin_state = (old_idr & (1 << i)) > 0;
373
+}
345
+ if (new_pin_state > old_pin_state) {
374
+
346
+ qemu_irq_raise(s->pin[i]);
375
+static void npcm7xx_pwm_update_freq(NPCM7xxPWM *p)
347
+ } else if (new_pin_state < old_pin_state) {
376
+{
348
+ qemu_irq_lower(s->pin[i]);
377
+ uint32_t freq = npcm7xx_pwm_calculate_freq(p);
349
+ }
378
+
379
+ if (freq != p->freq) {
380
+ trace_npcm7xx_pwm_update_freq(DEVICE(p->module)->canonical_path,
381
+ p->index, p->freq, freq);
382
+ p->freq = freq;
383
+ }
384
+}
385
+
386
+static void npcm7xx_pwm_update_duty(NPCM7xxPWM *p)
387
+{
388
+ uint32_t duty = npcm7xx_pwm_calculate_duty(p);
389
+
390
+ if (duty != p->duty) {
391
+ trace_npcm7xx_pwm_update_duty(DEVICE(p->module)->canonical_path,
392
+ p->index, p->duty, duty);
393
+ p->duty = duty;
394
+ }
395
+}
396
+
397
+static void npcm7xx_pwm_update_output(NPCM7xxPWM *p)
398
+{
399
+ npcm7xx_pwm_update_freq(p);
400
+ npcm7xx_pwm_update_duty(p);
401
+}
402
+
403
+static void npcm7xx_pwm_write_ppr(NPCM7xxPWMState *s, uint32_t new_ppr)
404
+{
405
+ int i;
406
+ uint32_t old_ppr = s->ppr;
407
+
408
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_ppr_base) != NPCM7XX_PWM_PER_MODULE);
409
+ s->ppr = new_ppr;
410
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
411
+ if (NPCM7XX_PPR(old_ppr, i) != NPCM7XX_PPR(new_ppr, i)) {
412
+ npcm7xx_pwm_update_freq(&s->pwm[i]);
413
+ }
350
+ }
414
+ }
351
+ }
415
+}
352
+}
416
+
353
+
417
+static void npcm7xx_pwm_write_csr(NPCM7xxPWMState *s, uint32_t new_csr)
354
+/*
418
+{
355
+ * Return mask of pins that are both configured in output
419
+ int i;
356
+ * mode and externally driven (except pins in open-drain
420
+ uint32_t old_csr = s->csr;
357
+ * mode externally set to 0).
421
+
358
+ */
422
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_csr_base) != NPCM7XX_PWM_PER_MODULE);
359
+static uint32_t get_gpio_pinmask_to_disconnect(Stm32l4x5GpioState *s)
423
+ s->csr = new_csr;
360
+{
424
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
361
+ uint32_t pins_to_disconnect = 0;
425
+ if (NPCM7XX_CSR(old_csr, i) != NPCM7XX_CSR(new_csr, i)) {
362
+ for (int i = 0; i < GPIO_NUM_PINS; i++) {
426
+ npcm7xx_pwm_update_freq(&s->pwm[i]);
363
+ /* for each connected pin in output mode */
364
+ if (!(s->disconnected_pins & (1 << i)) && is_output(s, i)) {
365
+ /* if either push-pull or high level */
366
+ if (is_push_pull(s, i) || s->pins_connected_high & (1 << i)) {
367
+ pins_to_disconnect |= (1 << i);
368
+ qemu_log_mask(LOG_GUEST_ERROR,
369
+ "Line %d can't be driven externally\n",
370
+ i);
371
+ }
427
+ }
372
+ }
428
+ }
373
+ }
429
+}
374
+ return pins_to_disconnect;
430
+
375
+}
431
+static void npcm7xx_pwm_write_pcr(NPCM7xxPWMState *s, uint32_t new_pcr)
376
+
432
+{
377
+/*
433
+ int i;
378
+ * Set field `disconnected_pins` and call `update_gpio_idr()`
434
+ bool inverted;
379
+ */
435
+ uint32_t pcr;
380
+static void disconnect_gpio_pins(Stm32l4x5GpioState *s, uint16_t lines)
436
+ NPCM7xxPWM *p;
381
+{
437
+
382
+ s->disconnected_pins |= lines;
438
+ s->pcr = new_pcr;
383
+ trace_stm32l4x5_gpio_pins(s->name, s->disconnected_pins,
439
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_ch_base) != NPCM7XX_PWM_PER_MODULE);
384
+ s->pins_connected_high);
440
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
385
+ update_gpio_idr(s);
441
+ p = &s->pwm[i];
386
+}
442
+ pcr = NPCM7XX_CH(new_pcr, i);
387
+
443
+ inverted = pcr & NPCM7XX_CH_INV;
388
+static void disconnected_pins_set(Object *obj, Visitor *v,
444
+
389
+ const char *name, void *opaque, Error **errp)
445
+ /*
390
+{
446
+ * We only run a PWM channel with toggle mode. Single-shot mode does not
391
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
447
+ * generate frequency and duty-cycle values.
392
+ uint16_t value;
448
+ */
393
+ if (!visit_type_uint16(v, name, &value, errp)) {
449
+ if ((pcr & NPCM7XX_CH_EN) && (pcr & NPCM7XX_CH_MOD)) {
394
+ return;
450
+ if (p->running) {
395
+ }
451
+ /* Re-run this PWM channel if inverted changed. */
396
+ disconnect_gpio_pins(s, value);
452
+ if (p->inverted ^ inverted) {
397
+}
453
+ p->inverted = inverted;
398
+
454
+ npcm7xx_pwm_update_duty(p);
399
+static void disconnected_pins_get(Object *obj, Visitor *v,
455
+ }
400
+ const char *name, void *opaque, Error **errp)
456
+ } else {
401
+{
457
+ /* Run this PWM channel. */
402
+ visit_type_uint16(v, name, (uint16_t *)opaque, errp);
458
+ p->running = true;
403
+}
459
+ p->inverted = inverted;
404
+
460
+ npcm7xx_pwm_update_output(p);
405
+static void clock_freq_get(Object *obj, Visitor *v,
461
+ }
406
+ const char *name, void *opaque, Error **errp)
462
+ } else {
407
+{
463
+ /* Clear this PWM channel. */
408
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
464
+ p->running = false;
409
+ uint32_t clock_freq_hz = clock_get_hz(s->clk);
465
+ p->inverted = inverted;
410
+ visit_type_uint32(v, name, &clock_freq_hz, errp);
466
+ npcm7xx_pwm_update_output(p);
411
+}
467
+ }
412
+
468
+ }
413
+static void stm32l4x5_gpio_write(void *opaque, hwaddr addr,
469
+
414
+ uint64_t val64, unsigned int size)
470
+}
415
+{
471
+
416
+ Stm32l4x5GpioState *s = opaque;
472
+static hwaddr npcm7xx_cnr_index(hwaddr offset)
417
+
473
+{
418
+ uint32_t value = val64;
474
+ switch (offset) {
419
+ trace_stm32l4x5_gpio_write(s->name, addr, val64);
475
+ case A_NPCM7XX_PWM_CNR0:
420
+
476
+ return 0;
421
+ switch (addr) {
477
+ case A_NPCM7XX_PWM_CNR1:
422
+ case GPIO_MODER:
478
+ return 1;
423
+ s->moder = value;
479
+ case A_NPCM7XX_PWM_CNR2:
424
+ disconnect_gpio_pins(s, get_gpio_pinmask_to_disconnect(s));
480
+ return 2;
425
+ qemu_log_mask(LOG_UNIMP,
481
+ case A_NPCM7XX_PWM_CNR3:
426
+ "%s: Analog and AF modes aren't supported\n\
482
+ return 3;
427
+ Analog and AF mode behave like input mode\n",
483
+ default:
428
+ __func__);
484
+ g_assert_not_reached();
429
+ return;
485
+ }
430
+ case GPIO_OTYPER:
486
+}
431
+ s->otyper = value & ~RESERVED_BITS_MASK;
487
+
432
+ disconnect_gpio_pins(s, get_gpio_pinmask_to_disconnect(s));
488
+static hwaddr npcm7xx_cmr_index(hwaddr offset)
433
+ return;
489
+{
434
+ case GPIO_OSPEEDR:
490
+ switch (offset) {
435
+ qemu_log_mask(LOG_UNIMP,
491
+ case A_NPCM7XX_PWM_CMR0:
436
+ "%s: Changing I/O output speed isn't supported\n\
492
+ return 0;
437
+ I/O speed is already maximal\n",
493
+ case A_NPCM7XX_PWM_CMR1:
438
+ __func__);
494
+ return 1;
439
+ s->ospeedr = value;
495
+ case A_NPCM7XX_PWM_CMR2:
440
+ return;
496
+ return 2;
441
+ case GPIO_PUPDR:
497
+ case A_NPCM7XX_PWM_CMR3:
442
+ s->pupdr = value;
498
+ return 3;
443
+ update_gpio_idr(s);
499
+ default:
444
+ return;
500
+ g_assert_not_reached();
445
+ case GPIO_IDR:
501
+ }
446
+ qemu_log_mask(LOG_UNIMP,
502
+}
447
+ "%s: GPIO->IDR is read-only\n",
503
+
448
+ __func__);
504
+static hwaddr npcm7xx_pdr_index(hwaddr offset)
449
+ return;
505
+{
450
+ case GPIO_ODR:
506
+ switch (offset) {
451
+ s->odr = value & ~RESERVED_BITS_MASK;
507
+ case A_NPCM7XX_PWM_PDR0:
452
+ update_gpio_idr(s);
508
+ return 0;
453
+ return;
509
+ case A_NPCM7XX_PWM_PDR1:
454
+ case GPIO_BSRR: {
510
+ return 1;
455
+ uint32_t bits_to_reset = (value & RESERVED_BITS_MASK) >> GPIO_NUM_PINS;
511
+ case A_NPCM7XX_PWM_PDR2:
456
+ uint32_t bits_to_set = value & ~RESERVED_BITS_MASK;
512
+ return 2;
457
+ /* If both BSx and BRx are set, BSx has priority.*/
513
+ case A_NPCM7XX_PWM_PDR3:
458
+ s->odr &= ~bits_to_reset;
514
+ return 3;
459
+ s->odr |= bits_to_set;
515
+ default:
460
+ update_gpio_idr(s);
516
+ g_assert_not_reached();
461
+ return;
517
+ }
462
+ }
518
+}
463
+ case GPIO_LCKR:
519
+
464
+ qemu_log_mask(LOG_UNIMP,
520
+static hwaddr npcm7xx_pwdr_index(hwaddr offset)
465
+ "%s: Locking port bits configuration isn't supported\n",
521
+{
466
+ __func__);
522
+ switch (offset) {
467
+ s->lckr = value & ~RESERVED_BITS_MASK;
523
+ case A_NPCM7XX_PWM_PWDR0:
468
+ return;
524
+ return 0;
469
+ case GPIO_AFRL:
525
+ case A_NPCM7XX_PWM_PWDR1:
470
+ qemu_log_mask(LOG_UNIMP,
526
+ return 1;
471
+ "%s: Alternate functions aren't supported\n",
527
+ case A_NPCM7XX_PWM_PWDR2:
472
+ __func__);
528
+ return 2;
473
+ s->afrl = value;
529
+ case A_NPCM7XX_PWM_PWDR3:
474
+ return;
530
+ return 3;
475
+ case GPIO_AFRH:
531
+ default:
476
+ qemu_log_mask(LOG_UNIMP,
532
+ g_assert_not_reached();
477
+ "%s: Alternate functions aren't supported\n",
533
+ }
478
+ __func__);
534
+}
479
+ s->afrh = value;
535
+
480
+ return;
536
+static uint64_t npcm7xx_pwm_read(void *opaque, hwaddr offset, unsigned size)
481
+ case GPIO_BRR: {
537
+{
482
+ uint32_t bits_to_reset = value & ~RESERVED_BITS_MASK;
538
+ NPCM7xxPWMState *s = opaque;
483
+ s->odr &= ~bits_to_reset;
539
+ uint64_t value = 0;
484
+ update_gpio_idr(s);
540
+
485
+ return;
541
+ switch (offset) {
486
+ }
542
+ case A_NPCM7XX_PWM_CNR0:
487
+ case GPIO_ASCR:
543
+ case A_NPCM7XX_PWM_CNR1:
488
+ qemu_log_mask(LOG_UNIMP,
544
+ case A_NPCM7XX_PWM_CNR2:
489
+ "%s: ADC function isn't supported\n",
545
+ case A_NPCM7XX_PWM_CNR3:
490
+ __func__);
546
+ value = s->pwm[npcm7xx_cnr_index(offset)].cnr;
491
+ s->ascr = value & ~RESERVED_BITS_MASK;
547
+ break;
492
+ return;
548
+
549
+ case A_NPCM7XX_PWM_CMR0:
550
+ case A_NPCM7XX_PWM_CMR1:
551
+ case A_NPCM7XX_PWM_CMR2:
552
+ case A_NPCM7XX_PWM_CMR3:
553
+ value = s->pwm[npcm7xx_cmr_index(offset)].cmr;
554
+ break;
555
+
556
+ case A_NPCM7XX_PWM_PDR0:
557
+ case A_NPCM7XX_PWM_PDR1:
558
+ case A_NPCM7XX_PWM_PDR2:
559
+ case A_NPCM7XX_PWM_PDR3:
560
+ value = s->pwm[npcm7xx_pdr_index(offset)].pdr;
561
+ break;
562
+
563
+ case A_NPCM7XX_PWM_PWDR0:
564
+ case A_NPCM7XX_PWM_PWDR1:
565
+ case A_NPCM7XX_PWM_PWDR2:
566
+ case A_NPCM7XX_PWM_PWDR3:
567
+ value = s->pwm[npcm7xx_pwdr_index(offset)].pwdr;
568
+ break;
569
+
570
+ case A_NPCM7XX_PWM_PPR:
571
+ value = s->ppr;
572
+ break;
573
+
574
+ case A_NPCM7XX_PWM_CSR:
575
+ value = s->csr;
576
+ break;
577
+
578
+ case A_NPCM7XX_PWM_PCR:
579
+ value = s->pcr;
580
+ break;
581
+
582
+ case A_NPCM7XX_PWM_PIER:
583
+ value = s->pier;
584
+ break;
585
+
586
+ case A_NPCM7XX_PWM_PIIR:
587
+ value = s->piir;
588
+ break;
589
+
590
+ default:
493
+ default:
591
+ qemu_log_mask(LOG_GUEST_ERROR,
494
+ qemu_log_mask(LOG_GUEST_ERROR,
592
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
495
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
593
+ __func__, offset);
496
+ }
594
+ break;
497
+}
595
+ }
498
+
596
+
499
+static uint64_t stm32l4x5_gpio_read(void *opaque, hwaddr addr,
597
+ trace_npcm7xx_pwm_read(DEVICE(s)->canonical_path, offset, value);
500
+ unsigned int size)
598
+ return value;
501
+{
599
+}
502
+ Stm32l4x5GpioState *s = opaque;
600
+
503
+
601
+static void npcm7xx_pwm_write(void *opaque, hwaddr offset,
504
+ trace_stm32l4x5_gpio_read(s->name, addr);
602
+ uint64_t v, unsigned size)
505
+
603
+{
506
+ switch (addr) {
604
+ NPCM7xxPWMState *s = opaque;
507
+ case GPIO_MODER:
605
+ NPCM7xxPWM *p;
508
+ return s->moder;
606
+ uint32_t value = v;
509
+ case GPIO_OTYPER:
607
+
510
+ return s->otyper;
608
+ trace_npcm7xx_pwm_write(DEVICE(s)->canonical_path, offset, value);
511
+ case GPIO_OSPEEDR:
609
+ switch (offset) {
512
+ return s->ospeedr;
610
+ case A_NPCM7XX_PWM_CNR0:
513
+ case GPIO_PUPDR:
611
+ case A_NPCM7XX_PWM_CNR1:
514
+ return s->pupdr;
612
+ case A_NPCM7XX_PWM_CNR2:
515
+ case GPIO_IDR:
613
+ case A_NPCM7XX_PWM_CNR3:
516
+ return s->idr;
614
+ p = &s->pwm[npcm7xx_cnr_index(offset)];
517
+ case GPIO_ODR:
615
+ p->cnr = value;
518
+ return s->odr;
616
+ npcm7xx_pwm_update_output(p);
519
+ case GPIO_BSRR:
617
+ break;
520
+ return 0;
618
+
521
+ case GPIO_LCKR:
619
+ case A_NPCM7XX_PWM_CMR0:
522
+ return s->lckr;
620
+ case A_NPCM7XX_PWM_CMR1:
523
+ case GPIO_AFRL:
621
+ case A_NPCM7XX_PWM_CMR2:
524
+ return s->afrl;
622
+ case A_NPCM7XX_PWM_CMR3:
525
+ case GPIO_AFRH:
623
+ p = &s->pwm[npcm7xx_cmr_index(offset)];
526
+ return s->afrh;
624
+ p->cmr = value;
527
+ case GPIO_BRR:
625
+ npcm7xx_pwm_update_output(p);
528
+ return 0;
626
+ break;
529
+ case GPIO_ASCR:
627
+
530
+ return s->ascr;
628
+ case A_NPCM7XX_PWM_PDR0:
629
+ case A_NPCM7XX_PWM_PDR1:
630
+ case A_NPCM7XX_PWM_PDR2:
631
+ case A_NPCM7XX_PWM_PDR3:
632
+ qemu_log_mask(LOG_GUEST_ERROR,
633
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
634
+ __func__, offset);
635
+ break;
636
+
637
+ case A_NPCM7XX_PWM_PWDR0:
638
+ case A_NPCM7XX_PWM_PWDR1:
639
+ case A_NPCM7XX_PWM_PWDR2:
640
+ case A_NPCM7XX_PWM_PWDR3:
641
+ qemu_log_mask(LOG_UNIMP,
642
+ "%s: register @ 0x%04" HWADDR_PRIx " is not implemented\n",
643
+ __func__, offset);
644
+ break;
645
+
646
+ case A_NPCM7XX_PWM_PPR:
647
+ npcm7xx_pwm_write_ppr(s, value);
648
+ break;
649
+
650
+ case A_NPCM7XX_PWM_CSR:
651
+ npcm7xx_pwm_write_csr(s, value);
652
+ break;
653
+
654
+ case A_NPCM7XX_PWM_PCR:
655
+ npcm7xx_pwm_write_pcr(s, value);
656
+ break;
657
+
658
+ case A_NPCM7XX_PWM_PIER:
659
+ qemu_log_mask(LOG_UNIMP,
660
+ "%s: register @ 0x%04" HWADDR_PRIx " is not implemented\n",
661
+ __func__, offset);
662
+ break;
663
+
664
+ case A_NPCM7XX_PWM_PIIR:
665
+ qemu_log_mask(LOG_UNIMP,
666
+ "%s: register @ 0x%04" HWADDR_PRIx " is not implemented\n",
667
+ __func__, offset);
668
+ break;
669
+
670
+ default:
531
+ default:
671
+ qemu_log_mask(LOG_GUEST_ERROR,
532
+ qemu_log_mask(LOG_GUEST_ERROR,
672
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
533
+ "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
673
+ __func__, offset);
534
+ return 0;
674
+ break;
535
+ }
675
+ }
536
+}
676
+}
537
+
677
+
538
+static const MemoryRegionOps stm32l4x5_gpio_ops = {
678
+static const struct MemoryRegionOps npcm7xx_pwm_ops = {
539
+ .read = stm32l4x5_gpio_read,
679
+ .read = npcm7xx_pwm_read,
540
+ .write = stm32l4x5_gpio_write,
680
+ .write = npcm7xx_pwm_write,
541
+ .endianness = DEVICE_NATIVE_ENDIAN,
681
+ .endianness = DEVICE_LITTLE_ENDIAN,
542
+ .impl = {
682
+ .valid = {
543
+ .min_access_size = 4,
683
+ .min_access_size = 4,
544
+ .max_access_size = 4,
684
+ .max_access_size = 4,
545
+ .unaligned = false,
685
+ .unaligned = false,
546
+ },
547
+ .valid = {
548
+ .min_access_size = 4,
549
+ .max_access_size = 4,
550
+ .unaligned = false,
686
+ },
551
+ },
687
+};
552
+};
688
+
553
+
689
+static void npcm7xx_pwm_enter_reset(Object *obj, ResetType type)
554
+static void stm32l4x5_gpio_init(Object *obj)
690
+{
555
+{
691
+ NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
556
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
692
+ int i;
557
+
693
+
558
+ memory_region_init_io(&s->mmio, obj, &stm32l4x5_gpio_ops, s,
694
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
559
+ TYPE_STM32L4X5_GPIO, 0x400);
695
+ NPCM7xxPWM *p = &s->pwm[i];
560
+
696
+
561
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
697
+ p->cnr = 0x00000000;
562
+
698
+ p->cmr = 0x00000000;
563
+ qdev_init_gpio_out(DEVICE(obj), s->pin, GPIO_NUM_PINS);
699
+ p->pdr = 0x00000000;
564
+ qdev_init_gpio_in(DEVICE(obj), stm32l4x5_gpio_set, GPIO_NUM_PINS);
700
+ p->pwdr = 0x00000000;
565
+
701
+ }
566
+ s->clk = qdev_init_clock_in(DEVICE(s), "clk", NULL, s, 0);
702
+
567
+
703
+ s->ppr = 0x00000000;
568
+ object_property_add(obj, "disconnected-pins", "uint16",
704
+ s->csr = 0x00000000;
569
+ disconnected_pins_get, disconnected_pins_set,
705
+ s->pcr = 0x00000000;
570
+ NULL, &s->disconnected_pins);
706
+ s->pier = 0x00000000;
571
+ object_property_add(obj, "clock-freq-hz", "uint32",
707
+ s->piir = 0x00000000;
572
+ clock_freq_get, NULL, NULL, NULL);
708
+}
573
+}
709
+
574
+
710
+static void npcm7xx_pwm_hold_reset(Object *obj)
575
+static void stm32l4x5_gpio_realize(DeviceState *dev, Error **errp)
711
+{
576
+{
712
+ NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
577
+ Stm32l4x5GpioState *s = STM32L4X5_GPIO(dev);
713
+ int i;
578
+ if (!clock_has_source(s->clk)) {
714
+
579
+ error_setg(errp, "GPIO: clk input must be connected");
715
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
580
+ return;
716
+ qemu_irq_lower(s->pwm[i].irq);
581
+ }
717
+ }
582
+}
718
+}
583
+
719
+
584
+static const VMStateDescription vmstate_stm32l4x5_gpio = {
720
+static void npcm7xx_pwm_init(Object *obj)
585
+ .name = TYPE_STM32L4X5_GPIO,
721
+{
586
+ .version_id = 1,
722
+ NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
587
+ .minimum_version_id = 1,
723
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
588
+ .fields = (VMStateField[]){
724
+ int i;
589
+ VMSTATE_UINT32(moder, Stm32l4x5GpioState),
725
+
590
+ VMSTATE_UINT32(otyper, Stm32l4x5GpioState),
726
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
591
+ VMSTATE_UINT32(ospeedr, Stm32l4x5GpioState),
727
+ NPCM7xxPWM *p = &s->pwm[i];
592
+ VMSTATE_UINT32(pupdr, Stm32l4x5GpioState),
728
+ p->module = s;
593
+ VMSTATE_UINT32(idr, Stm32l4x5GpioState),
729
+ p->index = i;
594
+ VMSTATE_UINT32(odr, Stm32l4x5GpioState),
730
+ sysbus_init_irq(sbd, &p->irq);
595
+ VMSTATE_UINT32(lckr, Stm32l4x5GpioState),
731
+ }
596
+ VMSTATE_UINT32(afrl, Stm32l4x5GpioState),
732
+
597
+ VMSTATE_UINT32(afrh, Stm32l4x5GpioState),
733
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_pwm_ops, s,
598
+ VMSTATE_UINT32(ascr, Stm32l4x5GpioState),
734
+ TYPE_NPCM7XX_PWM, 4 * KiB);
599
+ VMSTATE_UINT16(disconnected_pins, Stm32l4x5GpioState),
735
+ sysbus_init_mmio(sbd, &s->iomem);
600
+ VMSTATE_UINT16(pins_connected_high, Stm32l4x5GpioState),
736
+ s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL);
601
+ VMSTATE_END_OF_LIST()
737
+
602
+ }
738
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
603
+};
739
+ object_property_add_uint32_ptr(obj, "freq[*]",
604
+
740
+ &s->pwm[i].freq, OBJ_PROP_FLAG_READ);
605
+static Property stm32l4x5_gpio_properties[] = {
741
+ object_property_add_uint32_ptr(obj, "duty[*]",
606
+ DEFINE_PROP_STRING("name", Stm32l4x5GpioState, name),
742
+ &s->pwm[i].duty, OBJ_PROP_FLAG_READ);
607
+ DEFINE_PROP_UINT32("mode-reset", Stm32l4x5GpioState, moder_reset, 0),
743
+ }
608
+ DEFINE_PROP_UINT32("ospeed-reset", Stm32l4x5GpioState, ospeedr_reset, 0),
744
+}
609
+ DEFINE_PROP_UINT32("pupd-reset", Stm32l4x5GpioState, pupdr_reset, 0),
745
+
610
+ DEFINE_PROP_END_OF_LIST(),
746
+static const VMStateDescription vmstate_npcm7xx_pwm = {
611
+};
747
+ .name = "npcm7xx-pwm",
612
+
748
+ .version_id = 0,
613
+static void stm32l4x5_gpio_class_init(ObjectClass *klass, void *data)
749
+ .minimum_version_id = 0,
614
+{
750
+ .fields = (VMStateField[]) {
615
+ DeviceClass *dc = DEVICE_CLASS(klass);
751
+ VMSTATE_BOOL(running, NPCM7xxPWM),
616
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
752
+ VMSTATE_BOOL(inverted, NPCM7xxPWM),
617
+
753
+ VMSTATE_UINT8(index, NPCM7xxPWM),
618
+ device_class_set_props(dc, stm32l4x5_gpio_properties);
754
+ VMSTATE_UINT32(cnr, NPCM7xxPWM),
619
+ dc->vmsd = &vmstate_stm32l4x5_gpio;
755
+ VMSTATE_UINT32(cmr, NPCM7xxPWM),
620
+ dc->realize = stm32l4x5_gpio_realize;
756
+ VMSTATE_UINT32(pdr, NPCM7xxPWM),
621
+ rc->phases.hold = stm32l4x5_gpio_reset_hold;
757
+ VMSTATE_UINT32(pwdr, NPCM7xxPWM),
622
+}
758
+ VMSTATE_UINT32(freq, NPCM7xxPWM),
623
+
759
+ VMSTATE_UINT32(duty, NPCM7xxPWM),
624
+static const TypeInfo stm32l4x5_gpio_types[] = {
760
+ VMSTATE_END_OF_LIST(),
625
+ {
626
+ .name = TYPE_STM32L4X5_GPIO,
627
+ .parent = TYPE_SYS_BUS_DEVICE,
628
+ .instance_size = sizeof(Stm32l4x5GpioState),
629
+ .instance_init = stm32l4x5_gpio_init,
630
+ .class_init = stm32l4x5_gpio_class_init,
761
+ },
631
+ },
762
+};
632
+};
763
+
633
+
764
+static const VMStateDescription vmstate_npcm7xx_pwm_module = {
634
+DEFINE_TYPES(stm32l4x5_gpio_types)
765
+ .name = "npcm7xx-pwm-module",
635
diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
766
+ .version_id = 0,
767
+ .minimum_version_id = 0,
768
+ .fields = (VMStateField[]) {
769
+ VMSTATE_CLOCK(clock, NPCM7xxPWMState),
770
+ VMSTATE_STRUCT_ARRAY(pwm, NPCM7xxPWMState,
771
+ NPCM7XX_PWM_PER_MODULE, 0, vmstate_npcm7xx_pwm,
772
+ NPCM7xxPWM),
773
+ VMSTATE_UINT32(ppr, NPCM7xxPWMState),
774
+ VMSTATE_UINT32(csr, NPCM7xxPWMState),
775
+ VMSTATE_UINT32(pcr, NPCM7xxPWMState),
776
+ VMSTATE_UINT32(pier, NPCM7xxPWMState),
777
+ VMSTATE_UINT32(piir, NPCM7xxPWMState),
778
+ VMSTATE_END_OF_LIST(),
779
+ },
780
+};
781
+
782
+static void npcm7xx_pwm_class_init(ObjectClass *klass, void *data)
783
+{
784
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
785
+ DeviceClass *dc = DEVICE_CLASS(klass);
786
+
787
+ dc->desc = "NPCM7xx PWM Controller";
788
+ dc->vmsd = &vmstate_npcm7xx_pwm_module;
789
+ rc->phases.enter = npcm7xx_pwm_enter_reset;
790
+ rc->phases.hold = npcm7xx_pwm_hold_reset;
791
+}
792
+
793
+static const TypeInfo npcm7xx_pwm_info = {
794
+ .name = TYPE_NPCM7XX_PWM,
795
+ .parent = TYPE_SYS_BUS_DEVICE,
796
+ .instance_size = sizeof(NPCM7xxPWMState),
797
+ .class_init = npcm7xx_pwm_class_init,
798
+ .instance_init = npcm7xx_pwm_init,
799
+};
800
+
801
+static void npcm7xx_pwm_register_type(void)
802
+{
803
+ type_register_static(&npcm7xx_pwm_info);
804
+}
805
+type_init(npcm7xx_pwm_register_type);
806
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
807
index XXXXXXX..XXXXXXX 100644
636
index XXXXXXX..XXXXXXX 100644
808
--- a/hw/misc/meson.build
637
--- a/hw/gpio/Kconfig
809
+++ b/hw/misc/meson.build
638
+++ b/hw/gpio/Kconfig
810
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c'))
639
@@ -XXX,XX +XXX,XX @@ config GPIO_PWR
811
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
640
812
'npcm7xx_clk.c',
641
config SIFIVE_GPIO
813
'npcm7xx_gcr.c',
642
bool
814
+ 'npcm7xx_pwm.c',
643
+
815
'npcm7xx_rng.c',
644
+config STM32L4X5_GPIO
645
+ bool
646
diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
647
index XXXXXXX..XXXXXXX 100644
648
--- a/hw/gpio/meson.build
649
+++ b/hw/gpio/meson.build
650
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_RASPI', if_true: files(
651
'bcm2835_gpio.c',
652
'bcm2838_gpio.c'
816
))
653
))
817
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files(
654
+system_ss.add(when: 'CONFIG_STM32L4X5_SOC', if_true: files('stm32l4x5_gpio.c'))
818
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
655
system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_gpio.c'))
656
system_ss.add(when: 'CONFIG_SIFIVE_GPIO', if_true: files('sifive_gpio.c'))
657
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
819
index XXXXXXX..XXXXXXX 100644
658
index XXXXXXX..XXXXXXX 100644
820
--- a/hw/misc/trace-events
659
--- a/hw/gpio/trace-events
821
+++ b/hw/misc/trace-events
660
+++ b/hw/gpio/trace-events
822
@@ -XXX,XX +XXX,XX @@ npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " valu
661
@@ -XXX,XX +XXX,XX @@ sifive_gpio_update_output_irq(int64_t line, int64_t value) "line %" PRIi64 " val
823
npcm7xx_rng_read(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
662
# aspeed_gpio.c
824
npcm7xx_rng_write(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
663
aspeed_gpio_read(uint64_t offset, uint64_t value) "offset: 0x%" PRIx64 " value 0x%" PRIx64
825
664
aspeed_gpio_write(uint64_t offset, uint64_t value) "offset: 0x%" PRIx64 " value 0x%" PRIx64
826
+# npcm7xx_pwm.c
665
+
827
+npcm7xx_pwm_read(const char *id, uint64_t offset, uint32_t value) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
666
+# stm32l4x5_gpio.c
828
+npcm7xx_pwm_write(const char *id, uint64_t offset, uint32_t value) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
667
+stm32l4x5_gpio_read(char *gpio, uint64_t addr) "GPIO%s addr: 0x%" PRIx64 " "
829
+npcm7xx_pwm_update_freq(const char *id, uint8_t index, uint32_t old_value, uint32_t new_value) "%s pwm[%u] Update Freq: old_freq: %u, new_freq: %u"
668
+stm32l4x5_gpio_write(char *gpio, uint64_t addr, uint64_t data) "GPIO%s addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
830
+npcm7xx_pwm_update_duty(const char *id, uint8_t index, uint32_t old_value, uint32_t new_value) "%s pwm[%u] Update Duty: old_duty: %u, new_duty: %u"
669
+stm32l4x5_gpio_update_idr(char *gpio, uint32_t old_idr, uint32_t new_idr) "GPIO%s from: 0x%x to: 0x%x"
831
+
670
+stm32l4x5_gpio_pins(char *gpio, uint16_t disconnected, uint16_t high) "GPIO%s disconnected pins: 0x%x levels: 0x%x"
832
# stm32f4xx_syscfg.c
833
stm32f4xx_syscfg_set_irq(int gpio, int line, int level) "Interupt: GPIO: %d, Line: %d; Level: %d"
834
stm32f4xx_pulse_exti(int irq) "Pulse EXTI: %d"
835
--
671
--
836
2.20.1
672
2.34.1
837
673
838
674
diff view generated by jsdifflib
1
From: Roman Bolshakov <r.bolshakov@yadro.com>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
ui/cocoa.m:1188:44: warning: 'openFile:' is deprecated: first deprecated in macOS 11.0 - Use -[NSWorkspace openURL:] instead.
3
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
4
[-Wdeprecated-declarations]
4
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
5
if ([[NSWorkspace sharedWorkspace] openFile: full_file_path] == YES) {
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
^
6
Acked-by: Alistair Francis <alistair.francis@wdc.com>
7
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSWorkspace.h:350:1: note:
7
Message-id: 20240305210444.310665-3-ines.varhol@telecom-paris.fr
8
'openFile:' has been explicitly marked deprecated here
9
- (BOOL)openFile:(NSString *)fullPath API_DEPRECATED("Use -[NSWorkspace openURL:] instead.", macos(10.0, 11.0));
10
^
11
12
Signed-off-by: Roman Bolshakov <r.bolshakov@yadro.com>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20210102150718.47618-1-r.bolshakov@yadro.com
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
9
---
17
ui/cocoa.m | 5 ++++-
10
include/hw/arm/stm32l4x5_soc.h | 2 +
18
1 file changed, 4 insertions(+), 1 deletion(-)
11
include/hw/gpio/stm32l4x5_gpio.h | 1 +
19
12
include/hw/misc/stm32l4x5_syscfg.h | 3 +-
20
diff --git a/ui/cocoa.m b/ui/cocoa.m
13
hw/arm/stm32l4x5_soc.c | 71 +++++++++++++++++++++++-------
21
index XXXXXXX..XXXXXXX 100644
14
hw/misc/stm32l4x5_syscfg.c | 1 +
22
--- a/ui/cocoa.m
15
hw/arm/Kconfig | 3 +-
23
+++ b/ui/cocoa.m
16
6 files changed, 63 insertions(+), 18 deletions(-)
24
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
17
25
/* Where to look for local files */
18
diff --git a/include/hw/arm/stm32l4x5_soc.h b/include/hw/arm/stm32l4x5_soc.h
26
NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"docs/"};
19
index XXXXXXX..XXXXXXX 100644
27
NSString *full_file_path;
20
--- a/include/hw/arm/stm32l4x5_soc.h
28
+ NSURL *full_file_url;
21
+++ b/include/hw/arm/stm32l4x5_soc.h
29
22
@@ -XXX,XX +XXX,XX @@
30
/* iterate thru the possible paths until the file is found */
23
#include "hw/misc/stm32l4x5_syscfg.h"
31
int index;
24
#include "hw/misc/stm32l4x5_exti.h"
32
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
25
#include "hw/misc/stm32l4x5_rcc.h"
33
full_file_path = [full_file_path stringByDeletingLastPathComponent];
26
+#include "hw/gpio/stm32l4x5_gpio.h"
34
full_file_path = [NSString stringWithFormat: @"%@/%@%@", full_file_path,
27
#include "qom/object.h"
35
path_array[index], filename];
28
36
- if ([[NSWorkspace sharedWorkspace] openFile: full_file_path] == YES) {
29
#define TYPE_STM32L4X5_SOC "stm32l4x5-soc"
37
+ full_file_url = [NSURL fileURLWithPath: full_file_path
30
@@ -XXX,XX +XXX,XX @@ struct Stm32l4x5SocState {
38
+ isDirectory: false];
31
OrIRQState exti_or_gates[NUM_EXTI_OR_GATES];
39
+ if ([[NSWorkspace sharedWorkspace] openURL: full_file_url] == YES) {
32
Stm32l4x5SyscfgState syscfg;
40
return;
33
Stm32l4x5RccState rcc;
34
+ Stm32l4x5GpioState gpio[NUM_GPIOS];
35
36
MemoryRegion sram1;
37
MemoryRegion sram2;
38
diff --git a/include/hw/gpio/stm32l4x5_gpio.h b/include/hw/gpio/stm32l4x5_gpio.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/include/hw/gpio/stm32l4x5_gpio.h
41
+++ b/include/hw/gpio/stm32l4x5_gpio.h
42
@@ -XXX,XX +XXX,XX @@
43
#define TYPE_STM32L4X5_GPIO "stm32l4x5-gpio"
44
OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5GpioState, STM32L4X5_GPIO)
45
46
+#define NUM_GPIOS 8
47
#define GPIO_NUM_PINS 16
48
49
struct Stm32l4x5GpioState {
50
diff --git a/include/hw/misc/stm32l4x5_syscfg.h b/include/hw/misc/stm32l4x5_syscfg.h
51
index XXXXXXX..XXXXXXX 100644
52
--- a/include/hw/misc/stm32l4x5_syscfg.h
53
+++ b/include/hw/misc/stm32l4x5_syscfg.h
54
@@ -XXX,XX +XXX,XX @@
55
56
#include "hw/sysbus.h"
57
#include "qom/object.h"
58
+#include "hw/gpio/stm32l4x5_gpio.h"
59
60
#define TYPE_STM32L4X5_SYSCFG "stm32l4x5-syscfg"
61
OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5SyscfgState, STM32L4X5_SYSCFG)
62
63
-#define NUM_GPIOS 8
64
-#define GPIO_NUM_PINS 16
65
#define SYSCFG_NUM_EXTICR 4
66
67
struct Stm32l4x5SyscfgState {
68
diff --git a/hw/arm/stm32l4x5_soc.c b/hw/arm/stm32l4x5_soc.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/hw/arm/stm32l4x5_soc.c
71
+++ b/hw/arm/stm32l4x5_soc.c
72
@@ -XXX,XX +XXX,XX @@
73
#include "sysemu/sysemu.h"
74
#include "hw/or-irq.h"
75
#include "hw/arm/stm32l4x5_soc.h"
76
+#include "hw/gpio/stm32l4x5_gpio.h"
77
#include "hw/qdev-clock.h"
78
#include "hw/misc/unimp.h"
79
80
@@ -XXX,XX +XXX,XX @@ static const int exti_or_gate1_lines_in[EXTI_OR_GATE1_NUM_LINES_IN] = {
81
16, 35, 36, 37, 38,
82
};
83
84
+static const struct {
85
+ uint32_t addr;
86
+ uint32_t moder_reset;
87
+ uint32_t ospeedr_reset;
88
+ uint32_t pupdr_reset;
89
+} stm32l4x5_gpio_cfg[NUM_GPIOS] = {
90
+ { 0x48000000, 0xABFFFFFF, 0x0C000000, 0x64000000 },
91
+ { 0x48000400, 0xFFFFFEBF, 0x00000000, 0x00000100 },
92
+ { 0x48000800, 0xFFFFFFFF, 0x00000000, 0x00000000 },
93
+ { 0x48000C00, 0xFFFFFFFF, 0x00000000, 0x00000000 },
94
+ { 0x48001000, 0xFFFFFFFF, 0x00000000, 0x00000000 },
95
+ { 0x48001400, 0xFFFFFFFF, 0x00000000, 0x00000000 },
96
+ { 0x48001800, 0xFFFFFFFF, 0x00000000, 0x00000000 },
97
+ { 0x48001C00, 0x0000000F, 0x00000000, 0x00000000 },
98
+};
99
+
100
static void stm32l4x5_soc_initfn(Object *obj)
101
{
102
Stm32l4x5SocState *s = STM32L4X5_SOC(obj);
103
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_initfn(Object *obj)
104
}
105
object_initialize_child(obj, "syscfg", &s->syscfg, TYPE_STM32L4X5_SYSCFG);
106
object_initialize_child(obj, "rcc", &s->rcc, TYPE_STM32L4X5_RCC);
107
+
108
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
109
+ g_autofree char *name = g_strdup_printf("gpio%c", 'a' + i);
110
+ object_initialize_child(obj, name, &s->gpio[i], TYPE_STM32L4X5_GPIO);
111
+ }
112
}
113
114
static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
115
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
116
Stm32l4x5SocState *s = STM32L4X5_SOC(dev_soc);
117
const Stm32l4x5SocClass *sc = STM32L4X5_SOC_GET_CLASS(dev_soc);
118
MemoryRegion *system_memory = get_system_memory();
119
- DeviceState *armv7m;
120
+ DeviceState *armv7m, *dev;
121
SysBusDevice *busdev;
122
+ uint32_t pin_index;
123
124
if (!memory_region_init_rom(&s->flash, OBJECT(dev_soc), "flash",
125
sc->flash_size, errp)) {
126
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
127
return;
128
}
129
130
+ /* GPIOs */
131
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
132
+ g_autofree char *name = g_strdup_printf("%c", 'A' + i);
133
+ dev = DEVICE(&s->gpio[i]);
134
+ qdev_prop_set_string(dev, "name", name);
135
+ qdev_prop_set_uint32(dev, "mode-reset",
136
+ stm32l4x5_gpio_cfg[i].moder_reset);
137
+ qdev_prop_set_uint32(dev, "ospeed-reset",
138
+ stm32l4x5_gpio_cfg[i].ospeedr_reset);
139
+ qdev_prop_set_uint32(dev, "pupd-reset",
140
+ stm32l4x5_gpio_cfg[i].pupdr_reset);
141
+ busdev = SYS_BUS_DEVICE(&s->gpio[i]);
142
+ g_free(name);
143
+ name = g_strdup_printf("gpio%c-out", 'a' + i);
144
+ qdev_connect_clock_in(DEVICE(&s->gpio[i]), "clk",
145
+ qdev_get_clock_out(DEVICE(&(s->rcc)), name));
146
+ if (!sysbus_realize(busdev, errp)) {
147
+ return;
148
+ }
149
+ sysbus_mmio_map(busdev, 0, stm32l4x5_gpio_cfg[i].addr);
150
+ }
151
+
152
/* System configuration controller */
153
busdev = SYS_BUS_DEVICE(&s->syscfg);
154
if (!sysbus_realize(busdev, errp)) {
155
return;
156
}
157
sysbus_mmio_map(busdev, 0, SYSCFG_ADDR);
158
- /*
159
- * TODO: when the GPIO device is implemented, connect it
160
- * to SYCFG using `qdev_connect_gpio_out`, NUM_GPIOS and
161
- * GPIO_NUM_PINS.
162
- */
163
+
164
+ for (unsigned i = 0; i < NUM_GPIOS; i++) {
165
+ for (unsigned j = 0; j < GPIO_NUM_PINS; j++) {
166
+ pin_index = GPIO_NUM_PINS * i + j;
167
+ qdev_connect_gpio_out(DEVICE(&s->gpio[i]), j,
168
+ qdev_get_gpio_in(DEVICE(&s->syscfg),
169
+ pin_index));
170
+ }
171
+ }
172
173
/* EXTI device */
174
busdev = SYS_BUS_DEVICE(&s->exti);
175
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
41
}
176
}
42
}
177
}
178
179
- for (unsigned i = 0; i < 16; i++) {
180
+ for (unsigned i = 0; i < GPIO_NUM_PINS; i++) {
181
qdev_connect_gpio_out(DEVICE(&s->syscfg), i,
182
qdev_get_gpio_in(DEVICE(&s->exti), i));
183
}
184
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
185
/* RESERVED: 0x40024400, 0x7FDBC00 */
186
187
/* AHB2 BUS */
188
- create_unimplemented_device("GPIOA", 0x48000000, 0x400);
189
- create_unimplemented_device("GPIOB", 0x48000400, 0x400);
190
- create_unimplemented_device("GPIOC", 0x48000800, 0x400);
191
- create_unimplemented_device("GPIOD", 0x48000C00, 0x400);
192
- create_unimplemented_device("GPIOE", 0x48001000, 0x400);
193
- create_unimplemented_device("GPIOF", 0x48001400, 0x400);
194
- create_unimplemented_device("GPIOG", 0x48001800, 0x400);
195
- create_unimplemented_device("GPIOH", 0x48001C00, 0x400);
196
/* RESERVED: 0x48002000, 0x7FDBC00 */
197
create_unimplemented_device("OTG_FS", 0x50000000, 0x40000);
198
create_unimplemented_device("ADC", 0x50040000, 0x400);
199
diff --git a/hw/misc/stm32l4x5_syscfg.c b/hw/misc/stm32l4x5_syscfg.c
200
index XXXXXXX..XXXXXXX 100644
201
--- a/hw/misc/stm32l4x5_syscfg.c
202
+++ b/hw/misc/stm32l4x5_syscfg.c
203
@@ -XXX,XX +XXX,XX @@
204
#include "hw/irq.h"
205
#include "migration/vmstate.h"
206
#include "hw/misc/stm32l4x5_syscfg.h"
207
+#include "hw/gpio/stm32l4x5_gpio.h"
208
209
#define SYSCFG_MEMRMP 0x00
210
#define SYSCFG_CFGR1 0x04
211
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
212
index XXXXXXX..XXXXXXX 100644
213
--- a/hw/arm/Kconfig
214
+++ b/hw/arm/Kconfig
215
@@ -XXX,XX +XXX,XX @@ config STM32L4X5_SOC
216
bool
217
select ARM_V7M
218
select OR_IRQ
219
- select STM32L4X5_SYSCFG
220
select STM32L4X5_EXTI
221
+ select STM32L4X5_SYSCFG
222
select STM32L4X5_RCC
223
+ select STM32L4X5_GPIO
224
225
config XLNX_ZYNQMP_ARM
226
bool
43
--
227
--
44
2.20.1
228
2.34.1
45
229
46
230
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
From: Inès Varhol <ines.varhol@telecom-paris.fr>
2
2
3
We add a qtest for the PWM in the previous patch. It proves it works as
3
The testcase contains :
4
expected.
4
- `test_idr_reset_value()` :
5
Checks the reset values of MODER, OTYPER, PUPDR, ODR and IDR.
6
- `test_gpio_output_mode()` :
7
Checks that writing a bit in register ODR results in the corresponding
8
pin rising or lowering, if this pin is configured in output mode.
9
- `test_gpio_input_mode()` :
10
Checks that a input pin set high or low externally results
11
in the pin rising and lowering.
12
- `test_pull_up_pull_down()` :
13
Checks that a floating pin in pull-up/down mode is actually high/down.
14
- `test_push_pull()` :
15
Checks that a pin set externally is disconnected when configured in
16
push-pull output mode, and can't be set externally while in this mode.
17
- `test_open_drain()` :
18
Checks that a pin set externally high is disconnected when configured
19
in open-drain output mode, and can't be set high while in this mode.
20
- `test_bsrr_brr()` :
21
Checks that writing to BSRR and BRR has the desired result in ODR.
22
- `test_clock_enable()` :
23
Checks that GPIO clock is at the right frequency after enabling it.
5
24
6
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
25
Acked-by: Thomas Huth <thuth@redhat.com>
7
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
26
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
8
Signed-off-by: Hao Wu <wuhaotsh@google.com>
27
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
28
Message-id: 20240305210444.310665-4-ines.varhol@telecom-paris.fr
10
Message-id: 20210108190945.949196-6-wuhaotsh@google.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
30
---
13
tests/qtest/npcm7xx_pwm-test.c | 490 +++++++++++++++++++++++++++++++++
31
tests/qtest/stm32l4x5_gpio-test.c | 551 ++++++++++++++++++++++++++++++
14
tests/qtest/meson.build | 1 +
32
tests/qtest/meson.build | 3 +-
15
2 files changed, 491 insertions(+)
33
2 files changed, 553 insertions(+), 1 deletion(-)
16
create mode 100644 tests/qtest/npcm7xx_pwm-test.c
34
create mode 100644 tests/qtest/stm32l4x5_gpio-test.c
17
35
18
diff --git a/tests/qtest/npcm7xx_pwm-test.c b/tests/qtest/npcm7xx_pwm-test.c
36
diff --git a/tests/qtest/stm32l4x5_gpio-test.c b/tests/qtest/stm32l4x5_gpio-test.c
19
new file mode 100644
37
new file mode 100644
20
index XXXXXXX..XXXXXXX
38
index XXXXXXX..XXXXXXX
21
--- /dev/null
39
--- /dev/null
22
+++ b/tests/qtest/npcm7xx_pwm-test.c
40
+++ b/tests/qtest/stm32l4x5_gpio-test.c
23
@@ -XXX,XX +XXX,XX @@
41
@@ -XXX,XX +XXX,XX @@
24
+/*
42
+/*
25
+ * QTests for Nuvoton NPCM7xx PWM Modules.
43
+ * QTest testcase for STM32L4x5_GPIO
26
+ *
44
+ *
27
+ * Copyright 2020 Google LLC
45
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
46
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
28
+ *
47
+ *
29
+ * This program is free software; you can redistribute it and/or modify it
48
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
30
+ * under the terms of the GNU General Public License as published by the
49
+ * See the COPYING file in the top-level directory.
31
+ * Free Software Foundation; either version 2 of the License, or
32
+ * (at your option) any later version.
33
+ *
34
+ * This program is distributed in the hope that it will be useful, but WITHOUT
35
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
36
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
37
+ * for more details.
38
+ */
50
+ */
39
+
51
+
40
+#include "qemu/osdep.h"
52
+#include "qemu/osdep.h"
41
+#include "qemu/bitops.h"
53
+#include "libqtest-single.h"
42
+#include "libqos/libqtest.h"
54
+
43
+#include "qapi/qmp/qdict.h"
55
+#define GPIO_BASE_ADDR 0x48000000
44
+#include "qapi/qmp/qnum.h"
56
+#define GPIO_SIZE 0x400
45
+
57
+#define NUM_GPIOS 8
46
+#define REF_HZ 25000000
58
+#define NUM_GPIO_PINS 16
47
+
59
+
48
+/* Register field definitions. */
60
+#define GPIO_A 0x48000000
49
+#define CH_EN BIT(0)
61
+#define GPIO_B 0x48000400
50
+#define CH_INV BIT(2)
62
+#define GPIO_C 0x48000800
51
+#define CH_MOD BIT(3)
63
+#define GPIO_D 0x48000C00
52
+
64
+#define GPIO_E 0x48001000
53
+/* Registers shared between all PWMs in a module */
65
+#define GPIO_F 0x48001400
54
+#define PPR 0x00
66
+#define GPIO_G 0x48001800
55
+#define CSR 0x04
67
+#define GPIO_H 0x48001C00
56
+#define PCR 0x08
68
+
57
+#define PIER 0x3c
69
+#define MODER 0x00
58
+#define PIIR 0x40
70
+#define OTYPER 0x04
59
+
71
+#define PUPDR 0x0C
60
+/* CLK module related */
72
+#define IDR 0x10
61
+#define CLK_BA 0xf0801000
73
+#define ODR 0x14
62
+#define CLKSEL 0x04
74
+#define BSRR 0x18
63
+#define CLKDIV1 0x08
75
+#define BRR 0x28
64
+#define CLKDIV2 0x2c
76
+
65
+#define PLLCON0 0x0c
77
+#define MODER_INPUT 0
66
+#define PLLCON1 0x10
78
+#define MODER_OUTPUT 1
67
+#define PLL_INDV(rv) extract32((rv), 0, 6)
79
+
68
+#define PLL_FBDV(rv) extract32((rv), 16, 12)
80
+#define PUPDR_NONE 0
69
+#define PLL_OTDV1(rv) extract32((rv), 8, 3)
81
+#define PUPDR_PULLUP 1
70
+#define PLL_OTDV2(rv) extract32((rv), 13, 3)
82
+#define PUPDR_PULLDOWN 2
71
+#define APB3CKDIV(rv) extract32((rv), 28, 2)
83
+
72
+#define CLK2CKDIV(rv) extract32((rv), 0, 1)
84
+#define OTYPER_PUSH_PULL 0
73
+#define CLK4CKDIV(rv) extract32((rv), 26, 2)
85
+#define OTYPER_OPEN_DRAIN 1
74
+#define CPUCKSEL(rv) extract32((rv), 0, 2)
86
+
75
+
87
+const uint32_t moder_reset[NUM_GPIOS] = {
76
+#define MAX_DUTY 1000000
88
+ 0xABFFFFFF,
77
+
89
+ 0xFFFFFEBF,
78
+typedef struct PWMModule {
90
+ 0xFFFFFFFF,
79
+ int irq;
91
+ 0xFFFFFFFF,
80
+ uint64_t base_addr;
92
+ 0xFFFFFFFF,
81
+} PWMModule;
93
+ 0xFFFFFFFF,
82
+
94
+ 0xFFFFFFFF,
83
+typedef struct PWM {
95
+ 0x0000000F
84
+ uint32_t cnr_offset;
96
+};
85
+ uint32_t cmr_offset;
97
+
86
+ uint32_t pdr_offset;
98
+const uint32_t pupdr_reset[NUM_GPIOS] = {
87
+ uint32_t pwdr_offset;
99
+ 0x64000000,
88
+} PWM;
100
+ 0x00000100,
89
+
101
+ 0x00000000,
90
+typedef struct TestData {
102
+ 0x00000000,
91
+ const PWMModule *module;
103
+ 0x00000000,
92
+ const PWM *pwm;
104
+ 0x00000000,
93
+} TestData;
105
+ 0x00000000,
94
+
106
+ 0x00000000
95
+static const PWMModule pwm_module_list[] = {
107
+};
96
+ {
108
+
97
+ .irq = 93,
109
+const uint32_t idr_reset[NUM_GPIOS] = {
98
+ .base_addr = 0xf0103000
110
+ 0x0000A000,
99
+ },
111
+ 0x00000010,
100
+ {
112
+ 0x00000000,
101
+ .irq = 94,
113
+ 0x00000000,
102
+ .base_addr = 0xf0104000
114
+ 0x00000000,
115
+ 0x00000000,
116
+ 0x00000000,
117
+ 0x00000000
118
+};
119
+
120
+static uint32_t gpio_readl(unsigned int gpio, unsigned int offset)
121
+{
122
+ return readl(gpio + offset);
123
+}
124
+
125
+static void gpio_writel(unsigned int gpio, unsigned int offset, uint32_t value)
126
+{
127
+ writel(gpio + offset, value);
128
+}
129
+
130
+static void gpio_set_bit(unsigned int gpio, unsigned int reg,
131
+ unsigned int pin, uint32_t value)
132
+{
133
+ uint32_t mask = 0xFFFFFFFF & ~(0x1 << pin);
134
+ gpio_writel(gpio, reg, (gpio_readl(gpio, reg) & mask) | value << pin);
135
+}
136
+
137
+static void gpio_set_2bits(unsigned int gpio, unsigned int reg,
138
+ unsigned int pin, uint32_t value)
139
+{
140
+ uint32_t offset = 2 * pin;
141
+ uint32_t mask = 0xFFFFFFFF & ~(0x3 << offset);
142
+ gpio_writel(gpio, reg, (gpio_readl(gpio, reg) & mask) | value << offset);
143
+}
144
+
145
+static unsigned int get_gpio_id(uint32_t gpio_addr)
146
+{
147
+ return (gpio_addr - GPIO_BASE_ADDR) / GPIO_SIZE;
148
+}
149
+
150
+static void gpio_set_irq(unsigned int gpio, int num, int level)
151
+{
152
+ g_autofree char *name = g_strdup_printf("/machine/soc/gpio%c",
153
+ get_gpio_id(gpio) + 'a');
154
+ qtest_set_irq_in(global_qtest, name, NULL, num, level);
155
+}
156
+
157
+static void disconnect_all_pins(unsigned int gpio)
158
+{
159
+ g_autofree char *path = g_strdup_printf("/machine/soc/gpio%c",
160
+ get_gpio_id(gpio) + 'a');
161
+ QDict *r;
162
+
163
+ r = qtest_qmp(global_qtest, "{ 'execute': 'qom-set', 'arguments': "
164
+ "{ 'path': %s, 'property': 'disconnected-pins', 'value': %d } }",
165
+ path, 0xFFFF);
166
+ g_assert_false(qdict_haskey(r, "error"));
167
+ qobject_unref(r);
168
+}
169
+
170
+static uint32_t get_disconnected_pins(unsigned int gpio)
171
+{
172
+ g_autofree char *path = g_strdup_printf("/machine/soc/gpio%c",
173
+ get_gpio_id(gpio) + 'a');
174
+ uint32_t disconnected_pins = 0;
175
+ QDict *r;
176
+
177
+ r = qtest_qmp(global_qtest, "{ 'execute': 'qom-get', 'arguments':"
178
+ " { 'path': %s, 'property': 'disconnected-pins'} }", path);
179
+ g_assert_false(qdict_haskey(r, "error"));
180
+ disconnected_pins = qdict_get_int(r, "return");
181
+ qobject_unref(r);
182
+ return disconnected_pins;
183
+}
184
+
185
+static uint32_t reset(uint32_t gpio, unsigned int offset)
186
+{
187
+ switch (offset) {
188
+ case MODER:
189
+ return moder_reset[get_gpio_id(gpio)];
190
+ case PUPDR:
191
+ return pupdr_reset[get_gpio_id(gpio)];
192
+ case IDR:
193
+ return idr_reset[get_gpio_id(gpio)];
103
+ }
194
+ }
104
+};
195
+ return 0x0;
105
+
196
+}
106
+static const PWM pwm_list[] = {
197
+
107
+ {
198
+static void system_reset(void)
108
+ .cnr_offset = 0x0c,
199
+{
109
+ .cmr_offset = 0x10,
200
+ QDict *r;
110
+ .pdr_offset = 0x14,
201
+ r = qtest_qmp(global_qtest, "{'execute': 'system_reset'}");
111
+ .pwdr_offset = 0x44,
202
+ g_assert_false(qdict_haskey(r, "error"));
112
+ },
203
+ qobject_unref(r);
113
+ {
204
+}
114
+ .cnr_offset = 0x18,
205
+
115
+ .cmr_offset = 0x1c,
206
+static void test_idr_reset_value(void)
116
+ .pdr_offset = 0x20,
207
+{
117
+ .pwdr_offset = 0x48,
208
+ /*
118
+ },
209
+ * Checks that the values in MODER, OTYPER, PUPDR and ODR
119
+ {
210
+ * after reset are correct, and that the value in IDR is
120
+ .cnr_offset = 0x24,
211
+ * coherent.
121
+ .cmr_offset = 0x28,
212
+ * Since AF and analog modes aren't implemented, IDR reset
122
+ .pdr_offset = 0x2c,
213
+ * values aren't the same as with a real board.
123
+ .pwdr_offset = 0x4c,
214
+ *
124
+ },
215
+ * Register IDR contains the actual values of all GPIO pins.
125
+ {
216
+ * Its value depends on the pins' configuration
126
+ .cnr_offset = 0x30,
217
+ * (intput/output/analog : register MODER, push-pull/open-drain :
127
+ .cmr_offset = 0x34,
218
+ * register OTYPER, pull-up/pull-down/none : register PUPDR)
128
+ .pdr_offset = 0x38,
219
+ * and on the values stored in register ODR
129
+ .pwdr_offset = 0x50,
220
+ * (in case the pin is in output mode).
130
+ },
221
+ */
131
+};
222
+
132
+
223
+ gpio_writel(GPIO_A, MODER, 0xDEADBEEF);
133
+static const int ppr_base[] = { 0, 0, 8, 8 };
224
+ gpio_writel(GPIO_A, ODR, 0xDEADBEEF);
134
+static const int csr_base[] = { 0, 4, 8, 12 };
225
+ gpio_writel(GPIO_A, OTYPER, 0xDEADBEEF);
135
+static const int pcr_base[] = { 0, 8, 12, 16 };
226
+ gpio_writel(GPIO_A, PUPDR, 0xDEADBEEF);
136
+
227
+
137
+static const uint32_t ppr_list[] = {
228
+ gpio_writel(GPIO_B, MODER, 0xDEADBEEF);
138
+ 0,
229
+ gpio_writel(GPIO_B, ODR, 0xDEADBEEF);
139
+ 1,
230
+ gpio_writel(GPIO_B, OTYPER, 0xDEADBEEF);
140
+ 10,
231
+ gpio_writel(GPIO_B, PUPDR, 0xDEADBEEF);
141
+ 100,
232
+
142
+ 255, /* Max possible value. */
233
+ gpio_writel(GPIO_C, MODER, 0xDEADBEEF);
143
+};
234
+ gpio_writel(GPIO_C, ODR, 0xDEADBEEF);
144
+
235
+ gpio_writel(GPIO_C, OTYPER, 0xDEADBEEF);
145
+static const uint32_t csr_list[] = {
236
+ gpio_writel(GPIO_C, PUPDR, 0xDEADBEEF);
146
+ 0,
237
+
147
+ 1,
238
+ gpio_writel(GPIO_H, MODER, 0xDEADBEEF);
148
+ 2,
239
+ gpio_writel(GPIO_H, ODR, 0xDEADBEEF);
149
+ 3,
240
+ gpio_writel(GPIO_H, OTYPER, 0xDEADBEEF);
150
+ 4, /* Max possible value. */
241
+ gpio_writel(GPIO_H, PUPDR, 0xDEADBEEF);
151
+};
242
+
152
+
243
+ system_reset();
153
+static const uint32_t cnr_list[] = {
244
+
154
+ 0,
245
+ uint32_t moder = gpio_readl(GPIO_A, MODER);
155
+ 1,
246
+ uint32_t odr = gpio_readl(GPIO_A, ODR);
156
+ 50,
247
+ uint32_t otyper = gpio_readl(GPIO_A, OTYPER);
157
+ 100,
248
+ uint32_t pupdr = gpio_readl(GPIO_A, PUPDR);
158
+ 150,
249
+ uint32_t idr = gpio_readl(GPIO_A, IDR);
159
+ 200,
250
+ /* 15: AF, 14: AF, 13: AF, 12: Analog ... */
160
+ 1000,
251
+ /* here AF is the same as Analog and Input mode */
161
+ 10000,
252
+ g_assert_cmphex(moder, ==, reset(GPIO_A, MODER));
162
+ 65535, /* Max possible value. */
253
+ g_assert_cmphex(odr, ==, reset(GPIO_A, ODR));
163
+};
254
+ g_assert_cmphex(otyper, ==, reset(GPIO_A, OTYPER));
164
+
255
+ /* 15: pull-up, 14: pull-down, 13: pull-up, 12: neither ... */
165
+static const uint32_t cmr_list[] = {
256
+ g_assert_cmphex(pupdr, ==, reset(GPIO_A, PUPDR));
166
+ 0,
257
+ /* 15 : 1, 14: 0, 13: 1, 12 : reset value ... */
167
+ 1,
258
+ g_assert_cmphex(idr, ==, reset(GPIO_A, IDR));
168
+ 10,
259
+
169
+ 50,
260
+ moder = gpio_readl(GPIO_B, MODER);
170
+ 100,
261
+ odr = gpio_readl(GPIO_B, ODR);
171
+ 150,
262
+ otyper = gpio_readl(GPIO_B, OTYPER);
172
+ 200,
263
+ pupdr = gpio_readl(GPIO_B, PUPDR);
173
+ 1000,
264
+ idr = gpio_readl(GPIO_B, IDR);
174
+ 10000,
265
+ /* ... 5: Analog, 4: AF, 3: AF, 2: Analog ... */
175
+ 65535, /* Max possible value. */
266
+ /* here AF is the same as Analog and Input mode */
176
+};
267
+ g_assert_cmphex(moder, ==, reset(GPIO_B, MODER));
177
+
268
+ g_assert_cmphex(odr, ==, reset(GPIO_B, ODR));
178
+/* Returns the index of the PWM module. */
269
+ g_assert_cmphex(otyper, ==, reset(GPIO_B, OTYPER));
179
+static int pwm_module_index(const PWMModule *module)
270
+ /* ... 5: neither, 4: pull-up, 3: neither ... */
180
+{
271
+ g_assert_cmphex(pupdr, ==, reset(GPIO_B, PUPDR));
181
+ ptrdiff_t diff = module - pwm_module_list;
272
+ /* ... 5 : reset value, 4 : 1, 3 : reset value ... */
182
+
273
+ g_assert_cmphex(idr, ==, reset(GPIO_B, IDR));
183
+ g_assert_true(diff >= 0 && diff < ARRAY_SIZE(pwm_module_list));
274
+
184
+
275
+ moder = gpio_readl(GPIO_C, MODER);
185
+ return diff;
276
+ odr = gpio_readl(GPIO_C, ODR);
186
+}
277
+ otyper = gpio_readl(GPIO_C, OTYPER);
187
+
278
+ pupdr = gpio_readl(GPIO_C, PUPDR);
188
+/* Returns the index of the PWM entry. */
279
+ idr = gpio_readl(GPIO_C, IDR);
189
+static int pwm_index(const PWM *pwm)
280
+ /* Analog, same as Input mode*/
190
+{
281
+ g_assert_cmphex(moder, ==, reset(GPIO_C, MODER));
191
+ ptrdiff_t diff = pwm - pwm_list;
282
+ g_assert_cmphex(odr, ==, reset(GPIO_C, ODR));
192
+
283
+ g_assert_cmphex(otyper, ==, reset(GPIO_C, OTYPER));
193
+ g_assert_true(diff >= 0 && diff < ARRAY_SIZE(pwm_list));
284
+ /* no pull-up or pull-down */
194
+
285
+ g_assert_cmphex(pupdr, ==, reset(GPIO_C, PUPDR));
195
+ return diff;
286
+ /* reset value */
196
+}
287
+ g_assert_cmphex(idr, ==, reset(GPIO_C, IDR));
197
+
288
+
198
+static uint64_t pwm_qom_get(QTestState *qts, const char *path, const char *name)
289
+ moder = gpio_readl(GPIO_H, MODER);
199
+{
290
+ odr = gpio_readl(GPIO_H, ODR);
200
+ QDict *response;
291
+ otyper = gpio_readl(GPIO_H, OTYPER);
201
+
292
+ pupdr = gpio_readl(GPIO_H, PUPDR);
202
+ g_test_message("Getting properties %s from %s", name, path);
293
+ idr = gpio_readl(GPIO_H, IDR);
203
+ response = qtest_qmp(qts, "{ 'execute': 'qom-get',"
294
+ /* Analog, same as Input mode */
204
+ " 'arguments': { 'path': %s, 'property': %s}}",
295
+ g_assert_cmphex(moder, ==, reset(GPIO_H, MODER));
205
+ path, name);
296
+ g_assert_cmphex(odr, ==, reset(GPIO_H, ODR));
206
+ /* The qom set message returns successfully. */
297
+ g_assert_cmphex(otyper, ==, reset(GPIO_H, OTYPER));
207
+ g_assert_true(qdict_haskey(response, "return"));
298
+ /* no pull-up or pull-down */
208
+ return qnum_get_uint(qobject_to(QNum, qdict_get(response, "return")));
299
+ g_assert_cmphex(pupdr, ==, reset(GPIO_H, PUPDR));
209
+}
300
+ /* reset value */
210
+
301
+ g_assert_cmphex(idr, ==, reset(GPIO_H, IDR));
211
+static uint64_t pwm_get_freq(QTestState *qts, int module_index, int pwm_index)
302
+}
212
+{
303
+
213
+ char path[100];
304
+static void test_gpio_output_mode(const void *data)
214
+ char name[100];
305
+{
215
+
306
+ /*
216
+ sprintf(path, "/machine/soc/pwm[%d]", module_index);
307
+ * Checks that setting a bit in ODR sets the corresponding
217
+ sprintf(name, "freq[%d]", pwm_index);
308
+ * GPIO line high : it should set the right bit in IDR
218
+
309
+ * and send an irq to syscfg.
219
+ return pwm_qom_get(qts, path, name);
310
+ * Additionally, it checks that values written to ODR
220
+}
311
+ * when not in output mode are stored and not discarded.
221
+
312
+ */
222
+static uint64_t pwm_get_duty(QTestState *qts, int module_index, int pwm_index)
313
+ unsigned int pin = ((uint64_t)data) & 0xF;
223
+{
314
+ uint32_t gpio = ((uint64_t)data) >> 32;
224
+ char path[100];
315
+ unsigned int gpio_id = get_gpio_id(gpio);
225
+ char name[100];
316
+
226
+
317
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
227
+ sprintf(path, "/machine/soc/pwm[%d]", module_index);
318
+
228
+ sprintf(name, "duty[%d]", pwm_index);
319
+ /* Set a bit in ODR and check nothing happens */
229
+
320
+ gpio_set_bit(gpio, ODR, pin, 1);
230
+ return pwm_qom_get(qts, path, name);
321
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
231
+}
322
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
232
+
323
+
233
+static uint32_t get_pll(uint32_t con)
324
+ /* Configure the relevant line as output and check the pin is high */
234
+{
325
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
235
+ return REF_HZ * PLL_FBDV(con) / (PLL_INDV(con) * PLL_OTDV1(con)
326
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
236
+ * PLL_OTDV2(con));
327
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
237
+}
328
+
238
+
329
+ /* Reset the bit in ODR and check the pin is low */
239
+static uint64_t read_pclk(QTestState *qts)
330
+ gpio_set_bit(gpio, ODR, pin, 0);
240
+{
331
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
241
+ uint64_t freq = REF_HZ;
332
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
242
+ uint32_t clksel = qtest_readl(qts, CLK_BA + CLKSEL);
333
+
243
+ uint32_t pllcon;
334
+ /* Clean the test */
244
+ uint32_t clkdiv1 = qtest_readl(qts, CLK_BA + CLKDIV1);
335
+ gpio_writel(gpio, ODR, reset(gpio, ODR));
245
+ uint32_t clkdiv2 = qtest_readl(qts, CLK_BA + CLKDIV2);
336
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
246
+
337
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
247
+ switch (CPUCKSEL(clksel)) {
338
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
248
+ case 0:
339
+}
249
+ pllcon = qtest_readl(qts, CLK_BA + PLLCON0);
340
+
250
+ freq = get_pll(pllcon);
341
+static void test_gpio_input_mode(const void *data)
251
+ break;
342
+{
252
+ case 1:
343
+ /*
253
+ pllcon = qtest_readl(qts, CLK_BA + PLLCON1);
344
+ * Test that setting a line high/low externally sets the
254
+ freq = get_pll(pllcon);
345
+ * corresponding GPIO line high/low : it should set the
255
+ break;
346
+ * right bit in IDR and send an irq to syscfg.
256
+ case 2:
347
+ */
257
+ break;
348
+ unsigned int pin = ((uint64_t)data) & 0xF;
258
+ case 3:
349
+ uint32_t gpio = ((uint64_t)data) >> 32;
259
+ break;
350
+ unsigned int gpio_id = get_gpio_id(gpio);
260
+ default:
351
+
261
+ g_assert_not_reached();
352
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
262
+ }
353
+
263
+
354
+ /* Configure a line as input, raise it, and check that the pin is high */
264
+ freq >>= (CLK2CKDIV(clkdiv1) + CLK4CKDIV(clkdiv1) + APB3CKDIV(clkdiv2));
355
+ gpio_set_2bits(gpio, MODER, pin, MODER_INPUT);
265
+
356
+ gpio_set_irq(gpio, pin, 1);
266
+ return freq;
357
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
267
+}
358
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
268
+
359
+
269
+static uint32_t pwm_selector(uint32_t csr)
360
+ /* Lower the line and check that the pin is low */
270
+{
361
+ gpio_set_irq(gpio, pin, 0);
271
+ switch (csr) {
362
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
272
+ case 0:
363
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
273
+ return 2;
364
+
274
+ case 1:
365
+ /* Clean the test */
275
+ return 4;
366
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
276
+ case 2:
367
+ disconnect_all_pins(gpio);
277
+ return 8;
368
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
278
+ case 3:
369
+}
279
+ return 16;
370
+
280
+ case 4:
371
+static void test_pull_up_pull_down(const void *data)
281
+ return 1;
372
+{
282
+ default:
373
+ /*
283
+ g_assert_not_reached();
374
+ * Test that a floating pin with pull-up sets the pin
284
+ }
375
+ * high and vice-versa.
285
+}
376
+ */
286
+
377
+ unsigned int pin = ((uint64_t)data) & 0xF;
287
+static uint64_t pwm_compute_freq(QTestState *qts, uint32_t ppr, uint32_t csr,
378
+ uint32_t gpio = ((uint64_t)data) >> 32;
288
+ uint32_t cnr)
379
+ unsigned int gpio_id = get_gpio_id(gpio);
289
+{
380
+
290
+ return read_pclk(qts) / ((ppr + 1) * pwm_selector(csr) * (cnr + 1));
381
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
291
+}
382
+
292
+
383
+ /* Configure a line as input with pull-up, check the line is set high */
293
+static uint64_t pwm_compute_duty(uint32_t cnr, uint32_t cmr, bool inverted)
384
+ gpio_set_2bits(gpio, MODER, pin, MODER_INPUT);
294
+{
385
+ gpio_set_2bits(gpio, PUPDR, pin, PUPDR_PULLUP);
295
+ uint64_t duty;
386
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) | (1 << pin));
296
+
387
+ g_assert_true(get_irq(gpio_id * NUM_GPIO_PINS + pin));
297
+ if (cnr == 0) {
388
+
298
+ /* PWM is stopped. */
389
+ /* Configure the line with pull-down, check the line is low */
299
+ duty = 0;
390
+ gpio_set_2bits(gpio, PUPDR, pin, PUPDR_PULLDOWN);
300
+ } else if (cmr >= cnr) {
391
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
301
+ duty = MAX_DUTY;
392
+ g_assert_false(get_irq(gpio_id * NUM_GPIO_PINS + pin));
302
+ } else {
393
+
303
+ duty = MAX_DUTY * (cmr + 1) / (cnr + 1);
394
+ /* Clean the test */
304
+ }
395
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
305
+
396
+ gpio_writel(gpio, PUPDR, reset(gpio, PUPDR));
306
+ if (inverted) {
397
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
307
+ duty = MAX_DUTY - duty;
398
+}
308
+ }
399
+
309
+
400
+static void test_push_pull(const void *data)
310
+ return duty;
401
+{
311
+}
402
+ /*
312
+
403
+ * Test that configuring a line in push-pull output mode
313
+static uint32_t pwm_read(QTestState *qts, const TestData *td, unsigned offset)
404
+ * disconnects the pin, that the pin can't be set or reset
314
+{
405
+ * externally afterwards.
315
+ return qtest_readl(qts, td->module->base_addr + offset);
406
+ */
316
+}
407
+ unsigned int pin = ((uint64_t)data) & 0xF;
317
+
408
+ uint32_t gpio = ((uint64_t)data) >> 32;
318
+static void pwm_write(QTestState *qts, const TestData *td, unsigned offset,
409
+ uint32_t gpio2 = GPIO_BASE_ADDR + (GPIO_H - gpio);
319
+ uint32_t value)
410
+
320
+{
411
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
321
+ qtest_writel(qts, td->module->base_addr + offset, value);
412
+
322
+}
413
+ /* Setting a line high externally, configuring it in push-pull output */
323
+
414
+ /* And checking the pin was disconnected */
324
+static uint32_t pwm_read_ppr(QTestState *qts, const TestData *td)
415
+ gpio_set_irq(gpio, pin, 1);
325
+{
416
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
326
+ return extract32(pwm_read(qts, td, PPR), ppr_base[pwm_index(td->pwm)], 8);
417
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
327
+}
418
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
328
+
419
+
329
+static void pwm_write_ppr(QTestState *qts, const TestData *td, uint32_t value)
420
+ /* Setting a line low externally, configuring it in push-pull output */
330
+{
421
+ /* And checking the pin was disconnected */
331
+ pwm_write(qts, td, PPR, value << ppr_base[pwm_index(td->pwm)]);
422
+ gpio_set_irq(gpio2, pin, 0);
332
+}
423
+ gpio_set_bit(gpio2, ODR, pin, 1);
333
+
424
+ gpio_set_2bits(gpio2, MODER, pin, MODER_OUTPUT);
334
+static uint32_t pwm_read_csr(QTestState *qts, const TestData *td)
425
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF);
335
+{
426
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR) | (1 << pin));
336
+ return extract32(pwm_read(qts, td, CSR), csr_base[pwm_index(td->pwm)], 3);
427
+
337
+}
428
+ /* Trying to set a push-pull output pin, checking it doesn't work */
338
+
429
+ gpio_set_irq(gpio, pin, 1);
339
+static void pwm_write_csr(QTestState *qts, const TestData *td, uint32_t value)
430
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
340
+{
431
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
341
+ pwm_write(qts, td, CSR, value << csr_base[pwm_index(td->pwm)]);
432
+
342
+}
433
+ /* Trying to reset a push-pull output pin, checking it doesn't work */
343
+
434
+ gpio_set_irq(gpio2, pin, 0);
344
+static uint32_t pwm_read_pcr(QTestState *qts, const TestData *td)
435
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF);
345
+{
436
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR) | (1 << pin));
346
+ return extract32(pwm_read(qts, td, PCR), pcr_base[pwm_index(td->pwm)], 4);
437
+
347
+}
438
+ /* Clean the test */
348
+
439
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
349
+static void pwm_write_pcr(QTestState *qts, const TestData *td, uint32_t value)
440
+ gpio_writel(gpio2, ODR, reset(gpio2, ODR));
350
+{
441
+ gpio_writel(gpio2, MODER, reset(gpio2, MODER));
351
+ pwm_write(qts, td, PCR, value << pcr_base[pwm_index(td->pwm)]);
442
+}
352
+}
443
+
353
+
444
+static void test_open_drain(const void *data)
354
+static uint32_t pwm_read_cnr(QTestState *qts, const TestData *td)
445
+{
355
+{
446
+ /*
356
+ return pwm_read(qts, td, td->pwm->cnr_offset);
447
+ * Test that configuring a line in open-drain output mode
357
+}
448
+ * disconnects a pin set high externally and that the pin
358
+
449
+ * can't be set high externally while configured in open-drain.
359
+static void pwm_write_cnr(QTestState *qts, const TestData *td, uint32_t value)
450
+ *
360
+{
451
+ * However a pin set low externally shouldn't be disconnected,
361
+ pwm_write(qts, td, td->pwm->cnr_offset, value);
452
+ * and it can be set low externally when in open-drain mode.
362
+}
453
+ */
363
+
454
+ unsigned int pin = ((uint64_t)data) & 0xF;
364
+static uint32_t pwm_read_cmr(QTestState *qts, const TestData *td)
455
+ uint32_t gpio = ((uint64_t)data) >> 32;
365
+{
456
+ uint32_t gpio2 = GPIO_BASE_ADDR + (GPIO_H - gpio);
366
+ return pwm_read(qts, td, td->pwm->cmr_offset);
457
+
367
+}
458
+ qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
368
+
459
+
369
+static void pwm_write_cmr(QTestState *qts, const TestData *td, uint32_t value)
460
+ /* Setting a line high externally, configuring it in open-drain output */
370
+{
461
+ /* And checking the pin was disconnected */
371
+ pwm_write(qts, td, td->pwm->cmr_offset, value);
462
+ gpio_set_irq(gpio, pin, 1);
372
+}
463
+ gpio_set_bit(gpio, OTYPER, pin, OTYPER_OPEN_DRAIN);
373
+
464
+ gpio_set_2bits(gpio, MODER, pin, MODER_OUTPUT);
374
+/* Check pwm registers can be reset to default value */
465
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
375
+static void test_init(gconstpointer test_data)
466
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
376
+{
467
+
377
+ const TestData *td = test_data;
468
+ /* Setting a line low externally, configuring it in open-drain output */
378
+ QTestState *qts = qtest_init("-machine quanta-gsj");
469
+ /* And checking the pin wasn't disconnected */
379
+ int module = pwm_module_index(td->module);
470
+ gpio_set_irq(gpio2, pin, 0);
380
+ int pwm = pwm_index(td->pwm);
471
+ gpio_set_bit(gpio2, ODR, pin, 1);
381
+
472
+ gpio_set_bit(gpio2, OTYPER, pin, OTYPER_OPEN_DRAIN);
382
+ g_assert_cmpuint(pwm_get_freq(qts, module, pwm), ==, 0);
473
+ gpio_set_2bits(gpio2, MODER, pin, MODER_OUTPUT);
383
+ g_assert_cmpuint(pwm_get_duty(qts, module, pwm), ==, 0);
474
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF & ~(1 << pin));
384
+
475
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==,
385
+ qtest_quit(qts);
476
+ reset(gpio2, IDR) & ~(1 << pin));
386
+}
477
+
387
+
478
+ /* Trying to set a open-drain output pin, checking it doesn't work */
388
+/* One-shot mode should not change frequency and duty cycle. */
479
+ gpio_set_irq(gpio, pin, 1);
389
+static void test_oneshot(gconstpointer test_data)
480
+ g_assert_cmphex(get_disconnected_pins(gpio), ==, 0xFFFF);
390
+{
481
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR) & ~(1 << pin));
391
+ const TestData *td = test_data;
482
+
392
+ QTestState *qts = qtest_init("-machine quanta-gsj");
483
+ /* Trying to reset a open-drain output pin, checking it works */
393
+ int module = pwm_module_index(td->module);
484
+ gpio_set_bit(gpio, ODR, pin, 1);
394
+ int pwm = pwm_index(td->pwm);
485
+ gpio_set_irq(gpio, pin, 0);
395
+ uint32_t ppr, csr, pcr;
486
+ g_assert_cmphex(get_disconnected_pins(gpio2), ==, 0xFFFF & ~(1 << pin));
396
+ int i, j;
487
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==,
397
+
488
+ reset(gpio2, IDR) & ~(1 << pin));
398
+ pcr = CH_EN;
489
+
399
+ for (i = 0; i < ARRAY_SIZE(ppr_list); ++i) {
490
+ /* Clean the test */
400
+ ppr = ppr_list[i];
491
+ disconnect_all_pins(gpio2);
401
+ pwm_write_ppr(qts, td, ppr);
492
+ gpio_writel(gpio2, OTYPER, reset(gpio2, OTYPER));
402
+
493
+ gpio_writel(gpio2, ODR, reset(gpio2, ODR));
403
+ for (j = 0; j < ARRAY_SIZE(csr_list); ++j) {
494
+ gpio_writel(gpio2, MODER, reset(gpio2, MODER));
404
+ csr = csr_list[j];
495
+ g_assert_cmphex(gpio_readl(gpio2, IDR), ==, reset(gpio2, IDR));
405
+ pwm_write_csr(qts, td, csr);
496
+ disconnect_all_pins(gpio);
406
+ pwm_write_pcr(qts, td, pcr);
497
+ gpio_writel(gpio, OTYPER, reset(gpio, OTYPER));
407
+
498
+ gpio_writel(gpio, ODR, reset(gpio, ODR));
408
+ g_assert_cmpuint(pwm_read_ppr(qts, td), ==, ppr);
499
+ gpio_writel(gpio, MODER, reset(gpio, MODER));
409
+ g_assert_cmpuint(pwm_read_csr(qts, td), ==, csr);
500
+ g_assert_cmphex(gpio_readl(gpio, IDR), ==, reset(gpio, IDR));
410
+ g_assert_cmpuint(pwm_read_pcr(qts, td), ==, pcr);
501
+}
411
+ g_assert_cmpuint(pwm_get_freq(qts, module, pwm), ==, 0);
502
+
412
+ g_assert_cmpuint(pwm_get_duty(qts, module, pwm), ==, 0);
503
+static void test_bsrr_brr(const void *data)
413
+ }
504
+{
414
+ }
505
+ /*
415
+
506
+ * Test that writing a '1' in BSS and BSRR
416
+ qtest_quit(qts);
507
+ * has the desired effect on ODR.
417
+}
508
+ * In BSRR, BSx has priority over BRx.
418
+
509
+ */
419
+/* In toggle mode, the PWM generates correct outputs. */
510
+ unsigned int pin = ((uint64_t)data) & 0xF;
420
+static void test_toggle(gconstpointer test_data)
511
+ uint32_t gpio = ((uint64_t)data) >> 32;
421
+{
512
+
422
+ const TestData *td = test_data;
513
+ gpio_writel(gpio, BSRR, (1 << pin));
423
+ QTestState *qts = qtest_init("-machine quanta-gsj");
514
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
424
+ int module = pwm_module_index(td->module);
515
+
425
+ int pwm = pwm_index(td->pwm);
516
+ gpio_writel(gpio, BSRR, (1 << (pin + NUM_GPIO_PINS)));
426
+ uint32_t ppr, csr, pcr, cnr, cmr;
517
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
427
+ int i, j, k, l;
518
+
428
+ uint64_t expected_freq, expected_duty;
519
+ gpio_writel(gpio, BSRR, (1 << pin));
429
+
520
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
430
+ pcr = CH_EN | CH_MOD;
521
+
431
+ for (i = 0; i < ARRAY_SIZE(ppr_list); ++i) {
522
+ gpio_writel(gpio, BRR, (1 << pin));
432
+ ppr = ppr_list[i];
523
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
433
+ pwm_write_ppr(qts, td, ppr);
524
+
434
+
525
+ /* BSx should have priority over BRx */
435
+ for (j = 0; j < ARRAY_SIZE(csr_list); ++j) {
526
+ gpio_writel(gpio, BSRR, (1 << pin) | (1 << (pin + NUM_GPIO_PINS)));
436
+ csr = csr_list[j];
527
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR) | (1 << pin));
437
+ pwm_write_csr(qts, td, csr);
528
+
438
+
529
+ gpio_writel(gpio, BRR, (1 << pin));
439
+ for (k = 0; k < ARRAY_SIZE(cnr_list); ++k) {
530
+ g_assert_cmphex(gpio_readl(gpio, ODR), ==, reset(gpio, ODR));
440
+ cnr = cnr_list[k];
531
+
441
+ pwm_write_cnr(qts, td, cnr);
532
+ gpio_writel(gpio, ODR, reset(gpio, ODR));
442
+
533
+}
443
+ for (l = 0; l < ARRAY_SIZE(cmr_list); ++l) {
444
+ cmr = cmr_list[l];
445
+ pwm_write_cmr(qts, td, cmr);
446
+ expected_freq = pwm_compute_freq(qts, ppr, csr, cnr);
447
+ expected_duty = pwm_compute_duty(cnr, cmr, false);
448
+
449
+ pwm_write_pcr(qts, td, pcr);
450
+ g_assert_cmpuint(pwm_read_ppr(qts, td), ==, ppr);
451
+ g_assert_cmpuint(pwm_read_csr(qts, td), ==, csr);
452
+ g_assert_cmpuint(pwm_read_pcr(qts, td), ==, pcr);
453
+ g_assert_cmpuint(pwm_read_cnr(qts, td), ==, cnr);
454
+ g_assert_cmpuint(pwm_read_cmr(qts, td), ==, cmr);
455
+ g_assert_cmpuint(pwm_get_duty(qts, module, pwm),
456
+ ==, expected_duty);
457
+ if (expected_duty != 0 && expected_duty != 100) {
458
+ /* Duty cycle with 0 or 100 doesn't need frequency. */
459
+ g_assert_cmpuint(pwm_get_freq(qts, module, pwm),
460
+ ==, expected_freq);
461
+ }
462
+
463
+ /* Test inverted mode */
464
+ expected_duty = pwm_compute_duty(cnr, cmr, true);
465
+ pwm_write_pcr(qts, td, pcr | CH_INV);
466
+ g_assert_cmpuint(pwm_read_pcr(qts, td), ==, pcr | CH_INV);
467
+ g_assert_cmpuint(pwm_get_duty(qts, module, pwm),
468
+ ==, expected_duty);
469
+ if (expected_duty != 0 && expected_duty != 100) {
470
+ /* Duty cycle with 0 or 100 doesn't need frequency. */
471
+ g_assert_cmpuint(pwm_get_freq(qts, module, pwm),
472
+ ==, expected_freq);
473
+ }
474
+
475
+ }
476
+ }
477
+ }
478
+ }
479
+
480
+ qtest_quit(qts);
481
+}
482
+
483
+static void pwm_add_test(const char *name, const TestData* td,
484
+ GTestDataFunc fn)
485
+{
486
+ g_autofree char *full_name = g_strdup_printf(
487
+ "npcm7xx_pwm/module[%d]/pwm[%d]/%s", pwm_module_index(td->module),
488
+ pwm_index(td->pwm), name);
489
+ qtest_add_data_func(full_name, td, fn);
490
+}
491
+#define add_test(name, td) pwm_add_test(#name, td, test_##name)
492
+
534
+
493
+int main(int argc, char **argv)
535
+int main(int argc, char **argv)
494
+{
536
+{
495
+ TestData test_data_list[ARRAY_SIZE(pwm_module_list) * ARRAY_SIZE(pwm_list)];
537
+ int ret;
496
+
538
+
497
+ g_test_init(&argc, &argv, NULL);
539
+ g_test_init(&argc, &argv, NULL);
498
+
540
+ g_test_set_nonfatal_assertions();
499
+ for (int i = 0; i < ARRAY_SIZE(pwm_module_list); ++i) {
541
+ qtest_add_func("stm32l4x5/gpio/test_idr_reset_value",
500
+ for (int j = 0; j < ARRAY_SIZE(pwm_list); ++j) {
542
+ test_idr_reset_value);
501
+ TestData *td = &test_data_list[i * ARRAY_SIZE(pwm_list) + j];
543
+ /*
502
+
544
+ * The inputs for the tests (gpio and pin) can be changed,
503
+ td->module = &pwm_module_list[i];
545
+ * but the tests don't work for pins that are high at reset
504
+ td->pwm = &pwm_list[j];
546
+ * (GPIOA15, GPIO13 and GPIOB5).
505
+
547
+ * Specifically, rising the pin then checking `get_irq()`
506
+ add_test(init, td);
548
+ * is problematic since the pin was already high.
507
+ add_test(oneshot, td);
549
+ */
508
+ add_test(toggle, td);
550
+ qtest_add_data_func("stm32l4x5/gpio/test_gpioc5_output_mode",
509
+ }
551
+ (void *)((uint64_t)GPIO_C << 32 | 5),
510
+ }
552
+ test_gpio_output_mode);
511
+
553
+ qtest_add_data_func("stm32l4x5/gpio/test_gpioh3_output_mode",
512
+ return g_test_run();
554
+ (void *)((uint64_t)GPIO_H << 32 | 3),
555
+ test_gpio_output_mode);
556
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_input_mode1",
557
+ (void *)((uint64_t)GPIO_D << 32 | 6),
558
+ test_gpio_input_mode);
559
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_input_mode2",
560
+ (void *)((uint64_t)GPIO_C << 32 | 10),
561
+ test_gpio_input_mode);
562
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_pull_up_pull_down1",
563
+ (void *)((uint64_t)GPIO_B << 32 | 5),
564
+ test_pull_up_pull_down);
565
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_pull_up_pull_down2",
566
+ (void *)((uint64_t)GPIO_F << 32 | 1),
567
+ test_pull_up_pull_down);
568
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_push_pull1",
569
+ (void *)((uint64_t)GPIO_G << 32 | 6),
570
+ test_push_pull);
571
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_push_pull2",
572
+ (void *)((uint64_t)GPIO_H << 32 | 3),
573
+ test_push_pull);
574
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_open_drain1",
575
+ (void *)((uint64_t)GPIO_C << 32 | 4),
576
+ test_open_drain);
577
+ qtest_add_data_func("stm32l4x5/gpio/test_gpio_open_drain2",
578
+ (void *)((uint64_t)GPIO_E << 32 | 11),
579
+ test_open_drain);
580
+ qtest_add_data_func("stm32l4x5/gpio/test_bsrr_brr1",
581
+ (void *)((uint64_t)GPIO_A << 32 | 12),
582
+ test_bsrr_brr);
583
+ qtest_add_data_func("stm32l4x5/gpio/test_bsrr_brr2",
584
+ (void *)((uint64_t)GPIO_D << 32 | 0),
585
+ test_bsrr_brr);
586
+
587
+ qtest_start("-machine b-l475e-iot01a");
588
+ ret = g_test_run();
589
+ qtest_end();
590
+
591
+ return ret;
513
+}
592
+}
514
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
593
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
515
index XXXXXXX..XXXXXXX 100644
594
index XXXXXXX..XXXXXXX 100644
516
--- a/tests/qtest/meson.build
595
--- a/tests/qtest/meson.build
517
+++ b/tests/qtest/meson.build
596
+++ b/tests/qtest/meson.build
518
@@ -XXX,XX +XXX,XX @@ qtests_sparc64 = \
597
@@ -XXX,XX +XXX,XX @@ qtests_aspeed = \
519
qtests_npcm7xx = \
598
qtests_stm32l4x5 = \
520
['npcm7xx_adc-test',
599
['stm32l4x5_exti-test',
521
'npcm7xx_gpio-test',
600
'stm32l4x5_syscfg-test',
522
+ 'npcm7xx_pwm-test',
601
- 'stm32l4x5_rcc-test']
523
'npcm7xx_rng-test',
602
+ 'stm32l4x5_rcc-test',
524
'npcm7xx_timer-test',
603
+ 'stm32l4x5_gpio-test']
525
'npcm7xx_watchdog_timer-test']
604
605
qtests_arm = \
606
(config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \
526
--
607
--
527
2.20.1
608
2.34.1
528
609
529
610
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
The ADC is part of NPCM7XX Module. Its behavior is controled by the
3
While the 8-bit input elements are sequential in the input vector,
4
ADC_CON register. It converts one of the eight analog inputs into a
4
the 32-bit output elements are not sequential in the output matrix.
5
digital input and stores it in the ADC_DATA register when enabled.
5
Do not attempt to compute 2 32-bit outputs at the same time.
6
6
7
Users can alter input value by using qom-set QMP command.
7
Cc: qemu-stable@nongnu.org
8
8
Fixes: 23a5e3859f5 ("target/arm: Implement SME integer outer product")
9
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
9
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2083
10
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Signed-off-by: Hao Wu <wuhaotsh@google.com>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
Message-id: 20210108190945.949196-4-wuhaotsh@google.com
12
Message-id: 20240305163931.242795-1-richard.henderson@linaro.org
13
[PMM: Added missing hw/adc/trace.h file]
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
14
---
17
docs/system/arm/nuvoton.rst | 2 +-
15
target/arm/tcg/sme_helper.c | 77 ++++++++++++++++++-------------
18
meson.build | 1 +
16
tests/tcg/aarch64/sme-smopa-1.c | 47 +++++++++++++++++++
19
hw/adc/trace.h | 1 +
17
tests/tcg/aarch64/sme-smopa-2.c | 54 ++++++++++++++++++++++
20
include/hw/adc/npcm7xx_adc.h | 69 ++++++
18
tests/tcg/aarch64/Makefile.target | 2 +-
21
include/hw/arm/npcm7xx.h | 2 +
19
4 files changed, 147 insertions(+), 33 deletions(-)
22
hw/adc/npcm7xx_adc.c | 301 ++++++++++++++++++++++++++
20
create mode 100644 tests/tcg/aarch64/sme-smopa-1.c
23
hw/arm/npcm7xx.c | 24 ++-
21
create mode 100644 tests/tcg/aarch64/sme-smopa-2.c
24
tests/qtest/npcm7xx_adc-test.c | 377 +++++++++++++++++++++++++++++++++
22
25
hw/adc/meson.build | 1 +
23
diff --git a/target/arm/tcg/sme_helper.c b/target/arm/tcg/sme_helper.c
26
hw/adc/trace-events | 5 +
27
tests/qtest/meson.build | 3 +-
28
11 files changed, 783 insertions(+), 3 deletions(-)
29
create mode 100644 hw/adc/trace.h
30
create mode 100644 include/hw/adc/npcm7xx_adc.h
31
create mode 100644 hw/adc/npcm7xx_adc.c
32
create mode 100644 tests/qtest/npcm7xx_adc-test.c
33
create mode 100644 hw/adc/trace-events
34
35
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
36
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
37
--- a/docs/system/arm/nuvoton.rst
25
--- a/target/arm/tcg/sme_helper.c
38
+++ b/docs/system/arm/nuvoton.rst
26
+++ b/target/arm/tcg/sme_helper.c
39
@@ -XXX,XX +XXX,XX @@ Supported devices
27
@@ -XXX,XX +XXX,XX @@ void HELPER(sme_bfmopa)(void *vza, void *vzn, void *vzm, void *vpn,
40
* Random Number Generator (RNG)
28
}
41
* USB host (USBH)
29
}
42
* GPIO controller
30
43
+ * Analog to Digital Converter (ADC)
31
-typedef uint64_t IMOPFn(uint64_t, uint64_t, uint64_t, uint8_t, bool);
44
32
+typedef uint32_t IMOPFn32(uint32_t, uint32_t, uint32_t, uint8_t, bool);
45
Missing devices
33
+static inline void do_imopa_s(uint32_t *za, uint32_t *zn, uint32_t *zm,
46
---------------
34
+ uint8_t *pn, uint8_t *pm,
47
@@ -XXX,XX +XXX,XX @@ Missing devices
35
+ uint32_t desc, IMOPFn32 *fn)
48
* USB device (USBD)
36
+{
49
* SMBus controller (SMBF)
37
+ intptr_t row, col, oprsz = simd_oprsz(desc) / 4;
50
* Peripheral SPI controller (PSPI)
38
+ bool neg = simd_data(desc);
51
- * Analog to Digital Converter (ADC)
39
52
* SD/MMC host
40
-static inline void do_imopa(uint64_t *za, uint64_t *zn, uint64_t *zm,
53
* PECI interface
41
- uint8_t *pn, uint8_t *pm,
54
* Pulse Width Modulation (PWM)
42
- uint32_t desc, IMOPFn *fn)
55
diff --git a/meson.build b/meson.build
43
+ for (row = 0; row < oprsz; ++row) {
56
index XXXXXXX..XXXXXXX 100644
44
+ uint8_t pa = (pn[H1(row >> 1)] >> ((row & 1) * 4)) & 0xf;
57
--- a/meson.build
45
+ uint32_t *za_row = &za[tile_vslice_index(row)];
58
+++ b/meson.build
46
+ uint32_t n = zn[H4(row)];
59
@@ -XXX,XX +XXX,XX @@ if have_system
47
+
60
'chardev',
48
+ for (col = 0; col < oprsz; ++col) {
61
'hw/9pfs',
49
+ uint8_t pb = pm[H1(col >> 1)] >> ((col & 1) * 4);
62
'hw/acpi',
50
+ uint32_t *a = &za_row[H4(col)];
63
+ 'hw/adc',
51
+
64
'hw/alpha',
52
+ *a = fn(n, zm[H4(col)], *a, pa & pb, neg);
65
'hw/arm',
53
+ }
66
'hw/audio',
54
+ }
67
diff --git a/hw/adc/trace.h b/hw/adc/trace.h
55
+}
56
+
57
+typedef uint64_t IMOPFn64(uint64_t, uint64_t, uint64_t, uint8_t, bool);
58
+static inline void do_imopa_d(uint64_t *za, uint64_t *zn, uint64_t *zm,
59
+ uint8_t *pn, uint8_t *pm,
60
+ uint32_t desc, IMOPFn64 *fn)
61
{
62
intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
63
bool neg = simd_data(desc);
64
@@ -XXX,XX +XXX,XX @@ static inline void do_imopa(uint64_t *za, uint64_t *zn, uint64_t *zm,
65
}
66
67
#define DEF_IMOP_32(NAME, NTYPE, MTYPE) \
68
-static uint64_t NAME(uint64_t n, uint64_t m, uint64_t a, uint8_t p, bool neg) \
69
+static uint32_t NAME(uint32_t n, uint32_t m, uint32_t a, uint8_t p, bool neg) \
70
{ \
71
- uint32_t sum0 = 0, sum1 = 0; \
72
+ uint32_t sum = 0; \
73
/* Apply P to N as a mask, making the inactive elements 0. */ \
74
n &= expand_pred_b(p); \
75
- sum0 += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
76
- sum0 += (NTYPE)(n >> 8) * (MTYPE)(m >> 8); \
77
- sum0 += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
78
- sum0 += (NTYPE)(n >> 24) * (MTYPE)(m >> 24); \
79
- sum1 += (NTYPE)(n >> 32) * (MTYPE)(m >> 32); \
80
- sum1 += (NTYPE)(n >> 40) * (MTYPE)(m >> 40); \
81
- sum1 += (NTYPE)(n >> 48) * (MTYPE)(m >> 48); \
82
- sum1 += (NTYPE)(n >> 56) * (MTYPE)(m >> 56); \
83
- if (neg) { \
84
- sum0 = (uint32_t)a - sum0, sum1 = (uint32_t)(a >> 32) - sum1; \
85
- } else { \
86
- sum0 = (uint32_t)a + sum0, sum1 = (uint32_t)(a >> 32) + sum1; \
87
- } \
88
- return ((uint64_t)sum1 << 32) | sum0; \
89
+ sum += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); \
90
+ sum += (NTYPE)(n >> 8) * (MTYPE)(m >> 8); \
91
+ sum += (NTYPE)(n >> 16) * (MTYPE)(m >> 16); \
92
+ sum += (NTYPE)(n >> 24) * (MTYPE)(m >> 24); \
93
+ return neg ? a - sum : a + sum; \
94
}
95
96
#define DEF_IMOP_64(NAME, NTYPE, MTYPE) \
97
@@ -XXX,XX +XXX,XX @@ DEF_IMOP_64(umopa_d, uint16_t, uint16_t)
98
DEF_IMOP_64(sumopa_d, int16_t, uint16_t)
99
DEF_IMOP_64(usmopa_d, uint16_t, int16_t)
100
101
-#define DEF_IMOPH(NAME) \
102
- void HELPER(sme_##NAME)(void *vza, void *vzn, void *vzm, void *vpn, \
103
- void *vpm, uint32_t desc) \
104
- { do_imopa(vza, vzn, vzm, vpn, vpm, desc, NAME); }
105
+#define DEF_IMOPH(NAME, S) \
106
+ void HELPER(sme_##NAME##_##S)(void *vza, void *vzn, void *vzm, \
107
+ void *vpn, void *vpm, uint32_t desc) \
108
+ { do_imopa_##S(vza, vzn, vzm, vpn, vpm, desc, NAME##_##S); }
109
110
-DEF_IMOPH(smopa_s)
111
-DEF_IMOPH(umopa_s)
112
-DEF_IMOPH(sumopa_s)
113
-DEF_IMOPH(usmopa_s)
114
-DEF_IMOPH(smopa_d)
115
-DEF_IMOPH(umopa_d)
116
-DEF_IMOPH(sumopa_d)
117
-DEF_IMOPH(usmopa_d)
118
+DEF_IMOPH(smopa, s)
119
+DEF_IMOPH(umopa, s)
120
+DEF_IMOPH(sumopa, s)
121
+DEF_IMOPH(usmopa, s)
122
+
123
+DEF_IMOPH(smopa, d)
124
+DEF_IMOPH(umopa, d)
125
+DEF_IMOPH(sumopa, d)
126
+DEF_IMOPH(usmopa, d)
127
diff --git a/tests/tcg/aarch64/sme-smopa-1.c b/tests/tcg/aarch64/sme-smopa-1.c
68
new file mode 100644
128
new file mode 100644
69
index XXXXXXX..XXXXXXX
129
index XXXXXXX..XXXXXXX
70
--- /dev/null
130
--- /dev/null
71
+++ b/hw/adc/trace.h
131
+++ b/tests/tcg/aarch64/sme-smopa-1.c
72
@@ -0,0 +1 @@
132
@@ -XXX,XX +XXX,XX @@
73
+#include "trace/trace-hw_adc.h"
133
+#include <stdio.h>
74
diff --git a/include/hw/adc/npcm7xx_adc.h b/include/hw/adc/npcm7xx_adc.h
134
+#include <string.h>
135
+
136
+int main()
137
+{
138
+ static const int cmp[4][4] = {
139
+ { 110, 134, 158, 182 },
140
+ { 390, 478, 566, 654 },
141
+ { 670, 822, 974, 1126 },
142
+ { 950, 1166, 1382, 1598 }
143
+ };
144
+ int dst[4][4];
145
+ int *tmp = &dst[0][0];
146
+
147
+ asm volatile(
148
+ ".arch armv8-r+sme\n\t"
149
+ "smstart\n\t"
150
+ "index z0.b, #0, #1\n\t"
151
+ "movprfx z1, z0\n\t"
152
+ "add z1.b, z1.b, #16\n\t"
153
+ "ptrue p0.b\n\t"
154
+ "smopa za0.s, p0/m, p0/m, z0.b, z1.b\n\t"
155
+ "ptrue p0.s, vl4\n\t"
156
+ "mov w12, #0\n\t"
157
+ "st1w { za0h.s[w12, #0] }, p0, [%0]\n\t"
158
+ "add %0, %0, #16\n\t"
159
+ "st1w { za0h.s[w12, #1] }, p0, [%0]\n\t"
160
+ "add %0, %0, #16\n\t"
161
+ "st1w { za0h.s[w12, #2] }, p0, [%0]\n\t"
162
+ "add %0, %0, #16\n\t"
163
+ "st1w { za0h.s[w12, #3] }, p0, [%0]\n\t"
164
+ "smstop"
165
+ : "+r"(tmp) : : "memory");
166
+
167
+ if (memcmp(cmp, dst, sizeof(dst)) == 0) {
168
+ return 0;
169
+ }
170
+
171
+ /* See above for correct results. */
172
+ for (int i = 0; i < 4; ++i) {
173
+ for (int j = 0; j < 4; ++j) {
174
+ printf("%6d", dst[i][j]);
175
+ }
176
+ printf("\n");
177
+ }
178
+ return 1;
179
+}
180
diff --git a/tests/tcg/aarch64/sme-smopa-2.c b/tests/tcg/aarch64/sme-smopa-2.c
75
new file mode 100644
181
new file mode 100644
76
index XXXXXXX..XXXXXXX
182
index XXXXXXX..XXXXXXX
77
--- /dev/null
183
--- /dev/null
78
+++ b/include/hw/adc/npcm7xx_adc.h
184
+++ b/tests/tcg/aarch64/sme-smopa-2.c
79
@@ -XXX,XX +XXX,XX @@
185
@@ -XXX,XX +XXX,XX @@
80
+/*
186
+#include <stdio.h>
81
+ * Nuvoton NPCM7xx ADC Module
187
+#include <string.h>
82
+ *
188
+
83
+ * Copyright 2020 Google LLC
189
+int main()
84
+ *
190
+{
85
+ * This program is free software; you can redistribute it and/or modify it
191
+ static const long cmp[4][4] = {
86
+ * under the terms of the GNU General Public License as published by the
192
+ { 110, 134, 158, 182 },
87
+ * Free Software Foundation; either version 2 of the License, or
193
+ { 390, 478, 566, 654 },
88
+ * (at your option) any later version.
194
+ { 670, 822, 974, 1126 },
89
+ *
195
+ { 950, 1166, 1382, 1598 }
90
+ * This program is distributed in the hope that it will be useful, but WITHOUT
196
+ };
91
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
197
+ long dst[4][4];
92
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
198
+ long *tmp = &dst[0][0];
93
+ * for more details.
199
+ long svl;
94
+ */
200
+
95
+#ifndef NPCM7XX_ADC_H
201
+ /* Validate that we have a wide enough vector for 4 elements. */
96
+#define NPCM7XX_ADC_H
202
+ asm(".arch armv8-r+sme-i64\n\trdsvl %0, #1" : "=r"(svl));
97
+
203
+ if (svl < 32) {
98
+#include "hw/clock.h"
204
+ return 0;
99
+#include "hw/irq.h"
205
+ }
100
+#include "hw/sysbus.h"
206
+
101
+#include "qemu/timer.h"
207
+ asm volatile(
102
+
208
+ "smstart\n\t"
103
+#define NPCM7XX_ADC_NUM_INPUTS 8
209
+ "index z0.h, #0, #1\n\t"
104
+/**
210
+ "movprfx z1, z0\n\t"
105
+ * This value should not be changed unless write_adc_calibration function in
211
+ "add z1.h, z1.h, #16\n\t"
106
+ * hw/arm/npcm7xx.c is also changed.
212
+ "ptrue p0.b\n\t"
107
+ */
213
+ "smopa za0.d, p0/m, p0/m, z0.h, z1.h\n\t"
108
+#define NPCM7XX_ADC_NUM_CALIB 2
214
+ "ptrue p0.d, vl4\n\t"
109
+
215
+ "mov w12, #0\n\t"
110
+/**
216
+ "st1d { za0h.d[w12, #0] }, p0, [%0]\n\t"
111
+ * struct NPCM7xxADCState - Analog to Digital Converter Module device state.
217
+ "add %0, %0, #32\n\t"
112
+ * @parent: System bus device.
218
+ "st1d { za0h.d[w12, #1] }, p0, [%0]\n\t"
113
+ * @iomem: Memory region through which registers are accessed.
219
+ "mov w12, #2\n\t"
114
+ * @conv_timer: The timer counts down remaining cycles for the conversion.
220
+ "add %0, %0, #32\n\t"
115
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
221
+ "st1d { za0h.d[w12, #0] }, p0, [%0]\n\t"
116
+ * @con: The Control Register.
222
+ "add %0, %0, #32\n\t"
117
+ * @data: The Data Buffer.
223
+ "st1d { za0h.d[w12, #1] }, p0, [%0]\n\t"
118
+ * @clock: The ADC Clock.
224
+ "smstop"
119
+ * @adci: The input voltage in units of uV. 1uv = 1e-6V.
225
+ : "+r"(tmp) : : "memory");
120
+ * @vref: The external reference voltage.
226
+
121
+ * @iref: The internal reference voltage, initialized at launch time.
227
+ if (memcmp(cmp, dst, sizeof(dst)) == 0) {
122
+ * @rv: The calibrated output values of 0.5V and 1.5V for the ADC.
228
+ return 0;
123
+ */
229
+ }
124
+typedef struct {
230
+
125
+ SysBusDevice parent;
231
+ /* See above for correct results. */
126
+
232
+ for (int i = 0; i < 4; ++i) {
127
+ MemoryRegion iomem;
233
+ for (int j = 0; j < 4; ++j) {
128
+
234
+ printf("%6ld", dst[i][j]);
129
+ QEMUTimer conv_timer;
235
+ }
130
+
236
+ printf("\n");
131
+ qemu_irq irq;
237
+ }
132
+ uint32_t con;
238
+ return 1;
133
+ uint32_t data;
239
+}
134
+ Clock *clock;
240
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
135
+
136
+ /* Voltages are in unit of uV. 1V = 1000000uV. */
137
+ uint32_t adci[NPCM7XX_ADC_NUM_INPUTS];
138
+ uint32_t vref;
139
+ uint32_t iref;
140
+
141
+ uint16_t calibration_r_values[NPCM7XX_ADC_NUM_CALIB];
142
+} NPCM7xxADCState;
143
+
144
+#define TYPE_NPCM7XX_ADC "npcm7xx-adc"
145
+#define NPCM7XX_ADC(obj) \
146
+ OBJECT_CHECK(NPCM7xxADCState, (obj), TYPE_NPCM7XX_ADC)
147
+
148
+#endif /* NPCM7XX_ADC_H */
149
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
150
index XXXXXXX..XXXXXXX 100644
241
index XXXXXXX..XXXXXXX 100644
151
--- a/include/hw/arm/npcm7xx.h
242
--- a/tests/tcg/aarch64/Makefile.target
152
+++ b/include/hw/arm/npcm7xx.h
243
+++ b/tests/tcg/aarch64/Makefile.target
153
@@ -XXX,XX +XXX,XX @@
244
@@ -XXX,XX +XXX,XX @@ endif
154
#define NPCM7XX_H
245
155
246
# SME Tests
156
#include "hw/boards.h"
247
ifneq ($(CROSS_AS_HAS_ARMV9_SME),)
157
+#include "hw/adc/npcm7xx_adc.h"
248
-AARCH64_TESTS += sme-outprod1
158
#include "hw/cpu/a9mpcore.h"
249
+AARCH64_TESTS += sme-outprod1 sme-smopa-1 sme-smopa-2
159
#include "hw/gpio/npcm7xx_gpio.h"
250
endif
160
#include "hw/mem/npcm7xx_mc.h"
251
161
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
252
# System Registers Tests
162
NPCM7xxGCRState gcr;
163
NPCM7xxCLKState clk;
164
NPCM7xxTimerCtrlState tim[3];
165
+ NPCM7xxADCState adc;
166
NPCM7xxOTPState key_storage;
167
NPCM7xxOTPState fuse_array;
168
NPCM7xxMCState mc;
169
diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c
170
new file mode 100644
171
index XXXXXXX..XXXXXXX
172
--- /dev/null
173
+++ b/hw/adc/npcm7xx_adc.c
174
@@ -XXX,XX +XXX,XX @@
175
+/*
176
+ * Nuvoton NPCM7xx ADC Module
177
+ *
178
+ * Copyright 2020 Google LLC
179
+ *
180
+ * This program is free software; you can redistribute it and/or modify it
181
+ * under the terms of the GNU General Public License as published by the
182
+ * Free Software Foundation; either version 2 of the License, or
183
+ * (at your option) any later version.
184
+ *
185
+ * This program is distributed in the hope that it will be useful, but WITHOUT
186
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
187
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
188
+ * for more details.
189
+ */
190
+
191
+#include "qemu/osdep.h"
192
+#include "hw/adc/npcm7xx_adc.h"
193
+#include "hw/qdev-clock.h"
194
+#include "hw/qdev-properties.h"
195
+#include "hw/registerfields.h"
196
+#include "migration/vmstate.h"
197
+#include "qemu/log.h"
198
+#include "qemu/module.h"
199
+#include "qemu/timer.h"
200
+#include "qemu/units.h"
201
+#include "trace.h"
202
+
203
+REG32(NPCM7XX_ADC_CON, 0x0)
204
+REG32(NPCM7XX_ADC_DATA, 0x4)
205
+
206
+/* Register field definitions. */
207
+#define NPCM7XX_ADC_CON_MUX(rv) extract32(rv, 24, 4)
208
+#define NPCM7XX_ADC_CON_INT_EN BIT(21)
209
+#define NPCM7XX_ADC_CON_REFSEL BIT(19)
210
+#define NPCM7XX_ADC_CON_INT BIT(18)
211
+#define NPCM7XX_ADC_CON_EN BIT(17)
212
+#define NPCM7XX_ADC_CON_RST BIT(16)
213
+#define NPCM7XX_ADC_CON_CONV BIT(14)
214
+#define NPCM7XX_ADC_CON_DIV(rv) extract32(rv, 1, 8)
215
+
216
+#define NPCM7XX_ADC_MAX_RESULT 1023
217
+#define NPCM7XX_ADC_DEFAULT_IREF 2000000
218
+#define NPCM7XX_ADC_CONV_CYCLES 20
219
+#define NPCM7XX_ADC_RESET_CYCLES 10
220
+#define NPCM7XX_ADC_R0_INPUT 500000
221
+#define NPCM7XX_ADC_R1_INPUT 1500000
222
+
223
+static void npcm7xx_adc_reset(NPCM7xxADCState *s)
224
+{
225
+ timer_del(&s->conv_timer);
226
+ s->con = 0x000c0001;
227
+ s->data = 0x00000000;
228
+}
229
+
230
+static uint32_t npcm7xx_adc_convert(uint32_t input, uint32_t ref)
231
+{
232
+ uint32_t result;
233
+
234
+ result = input * (NPCM7XX_ADC_MAX_RESULT + 1) / ref;
235
+ if (result > NPCM7XX_ADC_MAX_RESULT) {
236
+ result = NPCM7XX_ADC_MAX_RESULT;
237
+ }
238
+
239
+ return result;
240
+}
241
+
242
+static uint32_t npcm7xx_adc_prescaler(NPCM7xxADCState *s)
243
+{
244
+ return 2 * (NPCM7XX_ADC_CON_DIV(s->con) + 1);
245
+}
246
+
247
+static void npcm7xx_adc_start_timer(Clock *clk, QEMUTimer *timer,
248
+ uint32_t cycles, uint32_t prescaler)
249
+{
250
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
251
+ int64_t ticks = cycles;
252
+ int64_t ns;
253
+
254
+ ticks *= prescaler;
255
+ ns = clock_ticks_to_ns(clk, ticks);
256
+ ns += now;
257
+ timer_mod(timer, ns);
258
+}
259
+
260
+static void npcm7xx_adc_start_convert(NPCM7xxADCState *s)
261
+{
262
+ uint32_t prescaler = npcm7xx_adc_prescaler(s);
263
+
264
+ npcm7xx_adc_start_timer(s->clock, &s->conv_timer, NPCM7XX_ADC_CONV_CYCLES,
265
+ prescaler);
266
+}
267
+
268
+static void npcm7xx_adc_convert_done(void *opaque)
269
+{
270
+ NPCM7xxADCState *s = opaque;
271
+ uint32_t input = NPCM7XX_ADC_CON_MUX(s->con);
272
+ uint32_t ref = (s->con & NPCM7XX_ADC_CON_REFSEL)
273
+ ? s->iref : s->vref;
274
+
275
+ if (input >= NPCM7XX_ADC_NUM_INPUTS) {
276
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid input: %u\n",
277
+ __func__, input);
278
+ return;
279
+ }
280
+ s->data = npcm7xx_adc_convert(s->adci[input], ref);
281
+ if (s->con & NPCM7XX_ADC_CON_INT_EN) {
282
+ s->con |= NPCM7XX_ADC_CON_INT;
283
+ qemu_irq_raise(s->irq);
284
+ }
285
+ s->con &= ~NPCM7XX_ADC_CON_CONV;
286
+}
287
+
288
+static void npcm7xx_adc_calibrate(NPCM7xxADCState *adc)
289
+{
290
+ adc->calibration_r_values[0] = npcm7xx_adc_convert(NPCM7XX_ADC_R0_INPUT,
291
+ adc->iref);
292
+ adc->calibration_r_values[1] = npcm7xx_adc_convert(NPCM7XX_ADC_R1_INPUT,
293
+ adc->iref);
294
+}
295
+
296
+static void npcm7xx_adc_write_con(NPCM7xxADCState *s, uint32_t new_con)
297
+{
298
+ uint32_t old_con = s->con;
299
+
300
+ /* Write ADC_INT to 1 to clear it */
301
+ if (new_con & NPCM7XX_ADC_CON_INT) {
302
+ new_con &= ~NPCM7XX_ADC_CON_INT;
303
+ qemu_irq_lower(s->irq);
304
+ } else if (old_con & NPCM7XX_ADC_CON_INT) {
305
+ new_con |= NPCM7XX_ADC_CON_INT;
306
+ }
307
+
308
+ s->con = new_con;
309
+
310
+ if (s->con & NPCM7XX_ADC_CON_RST) {
311
+ npcm7xx_adc_reset(s);
312
+ return;
313
+ }
314
+
315
+ if ((s->con & NPCM7XX_ADC_CON_EN)) {
316
+ if (s->con & NPCM7XX_ADC_CON_CONV) {
317
+ if (!(old_con & NPCM7XX_ADC_CON_CONV)) {
318
+ npcm7xx_adc_start_convert(s);
319
+ }
320
+ } else {
321
+ timer_del(&s->conv_timer);
322
+ }
323
+ }
324
+}
325
+
326
+static uint64_t npcm7xx_adc_read(void *opaque, hwaddr offset, unsigned size)
327
+{
328
+ uint64_t value = 0;
329
+ NPCM7xxADCState *s = opaque;
330
+
331
+ switch (offset) {
332
+ case A_NPCM7XX_ADC_CON:
333
+ value = s->con;
334
+ break;
335
+
336
+ case A_NPCM7XX_ADC_DATA:
337
+ value = s->data;
338
+ break;
339
+
340
+ default:
341
+ qemu_log_mask(LOG_GUEST_ERROR,
342
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
343
+ __func__, offset);
344
+ break;
345
+ }
346
+
347
+ trace_npcm7xx_adc_read(DEVICE(s)->canonical_path, offset, value);
348
+ return value;
349
+}
350
+
351
+static void npcm7xx_adc_write(void *opaque, hwaddr offset, uint64_t v,
352
+ unsigned size)
353
+{
354
+ NPCM7xxADCState *s = opaque;
355
+
356
+ trace_npcm7xx_adc_write(DEVICE(s)->canonical_path, offset, v);
357
+ switch (offset) {
358
+ case A_NPCM7XX_ADC_CON:
359
+ npcm7xx_adc_write_con(s, v);
360
+ break;
361
+
362
+ case A_NPCM7XX_ADC_DATA:
363
+ qemu_log_mask(LOG_GUEST_ERROR,
364
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
365
+ __func__, offset);
366
+ break;
367
+
368
+ default:
369
+ qemu_log_mask(LOG_GUEST_ERROR,
370
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
371
+ __func__, offset);
372
+ break;
373
+ }
374
+
375
+}
376
+
377
+static const struct MemoryRegionOps npcm7xx_adc_ops = {
378
+ .read = npcm7xx_adc_read,
379
+ .write = npcm7xx_adc_write,
380
+ .endianness = DEVICE_LITTLE_ENDIAN,
381
+ .valid = {
382
+ .min_access_size = 4,
383
+ .max_access_size = 4,
384
+ .unaligned = false,
385
+ },
386
+};
387
+
388
+static void npcm7xx_adc_enter_reset(Object *obj, ResetType type)
389
+{
390
+ NPCM7xxADCState *s = NPCM7XX_ADC(obj);
391
+
392
+ npcm7xx_adc_reset(s);
393
+}
394
+
395
+static void npcm7xx_adc_hold_reset(Object *obj)
396
+{
397
+ NPCM7xxADCState *s = NPCM7XX_ADC(obj);
398
+
399
+ qemu_irq_lower(s->irq);
400
+}
401
+
402
+static void npcm7xx_adc_init(Object *obj)
403
+{
404
+ NPCM7xxADCState *s = NPCM7XX_ADC(obj);
405
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
406
+ int i;
407
+
408
+ sysbus_init_irq(sbd, &s->irq);
409
+
410
+ timer_init_ns(&s->conv_timer, QEMU_CLOCK_VIRTUAL,
411
+ npcm7xx_adc_convert_done, s);
412
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_adc_ops, s,
413
+ TYPE_NPCM7XX_ADC, 4 * KiB);
414
+ sysbus_init_mmio(sbd, &s->iomem);
415
+ s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL);
416
+
417
+ for (i = 0; i < NPCM7XX_ADC_NUM_INPUTS; ++i) {
418
+ object_property_add_uint32_ptr(obj, "adci[*]",
419
+ &s->adci[i], OBJ_PROP_FLAG_WRITE);
420
+ }
421
+ object_property_add_uint32_ptr(obj, "vref",
422
+ &s->vref, OBJ_PROP_FLAG_WRITE);
423
+ npcm7xx_adc_calibrate(s);
424
+}
425
+
426
+static const VMStateDescription vmstate_npcm7xx_adc = {
427
+ .name = "npcm7xx-adc",
428
+ .version_id = 0,
429
+ .minimum_version_id = 0,
430
+ .fields = (VMStateField[]) {
431
+ VMSTATE_TIMER(conv_timer, NPCM7xxADCState),
432
+ VMSTATE_UINT32(con, NPCM7xxADCState),
433
+ VMSTATE_UINT32(data, NPCM7xxADCState),
434
+ VMSTATE_CLOCK(clock, NPCM7xxADCState),
435
+ VMSTATE_UINT32_ARRAY(adci, NPCM7xxADCState, NPCM7XX_ADC_NUM_INPUTS),
436
+ VMSTATE_UINT32(vref, NPCM7xxADCState),
437
+ VMSTATE_UINT32(iref, NPCM7xxADCState),
438
+ VMSTATE_UINT16_ARRAY(calibration_r_values, NPCM7xxADCState,
439
+ NPCM7XX_ADC_NUM_CALIB),
440
+ VMSTATE_END_OF_LIST(),
441
+ },
442
+};
443
+
444
+static Property npcm7xx_timer_properties[] = {
445
+ DEFINE_PROP_UINT32("iref", NPCM7xxADCState, iref, NPCM7XX_ADC_DEFAULT_IREF),
446
+ DEFINE_PROP_END_OF_LIST(),
447
+};
448
+
449
+static void npcm7xx_adc_class_init(ObjectClass *klass, void *data)
450
+{
451
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
452
+ DeviceClass *dc = DEVICE_CLASS(klass);
453
+
454
+ dc->desc = "NPCM7xx ADC Module";
455
+ dc->vmsd = &vmstate_npcm7xx_adc;
456
+ rc->phases.enter = npcm7xx_adc_enter_reset;
457
+ rc->phases.hold = npcm7xx_adc_hold_reset;
458
+
459
+ device_class_set_props(dc, npcm7xx_timer_properties);
460
+}
461
+
462
+static const TypeInfo npcm7xx_adc_info = {
463
+ .name = TYPE_NPCM7XX_ADC,
464
+ .parent = TYPE_SYS_BUS_DEVICE,
465
+ .instance_size = sizeof(NPCM7xxADCState),
466
+ .class_init = npcm7xx_adc_class_init,
467
+ .instance_init = npcm7xx_adc_init,
468
+};
469
+
470
+static void npcm7xx_adc_register_types(void)
471
+{
472
+ type_register_static(&npcm7xx_adc_info);
473
+}
474
+
475
+type_init(npcm7xx_adc_register_types);
476
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
477
index XXXXXXX..XXXXXXX 100644
478
--- a/hw/arm/npcm7xx.c
479
+++ b/hw/arm/npcm7xx.c
480
@@ -XXX,XX +XXX,XX @@
481
#define NPCM7XX_EHCI_BA (0xf0806000)
482
#define NPCM7XX_OHCI_BA (0xf0807000)
483
484
+/* ADC Module */
485
+#define NPCM7XX_ADC_BA (0xf000c000)
486
+
487
/* Internal AHB SRAM */
488
#define NPCM7XX_RAM3_BA (0xc0008000)
489
#define NPCM7XX_RAM3_SZ (4 * KiB)
490
@@ -XXX,XX +XXX,XX @@
491
#define NPCM7XX_ROM_BA (0xffff0000)
492
#define NPCM7XX_ROM_SZ (64 * KiB)
493
494
+
495
/* Clock configuration values to be fixed up when bypassing bootloader */
496
497
/* Run PLL1 at 1600 MHz */
498
@@ -XXX,XX +XXX,XX @@
499
* interrupts.
500
*/
501
enum NPCM7xxInterrupt {
502
+ NPCM7XX_ADC_IRQ = 0,
503
NPCM7XX_UART0_IRQ = 2,
504
NPCM7XX_UART1_IRQ,
505
NPCM7XX_UART2_IRQ,
506
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init_fuses(NPCM7xxState *s)
507
sizeof(value));
508
}
509
510
+static void npcm7xx_write_adc_calibration(NPCM7xxState *s)
511
+{
512
+ /* Both ADC and the fuse array must have realized. */
513
+ QEMU_BUILD_BUG_ON(sizeof(s->adc.calibration_r_values) != 4);
514
+ npcm7xx_otp_array_write(&s->fuse_array, s->adc.calibration_r_values,
515
+ NPCM7XX_FUSE_ADC_CALIB, sizeof(s->adc.calibration_r_values));
516
+}
517
+
518
static qemu_irq npcm7xx_irq(NPCM7xxState *s, int n)
519
{
520
return qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
521
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
522
TYPE_NPCM7XX_FUSE_ARRAY);
523
object_initialize_child(obj, "mc", &s->mc, TYPE_NPCM7XX_MC);
524
object_initialize_child(obj, "rng", &s->rng, TYPE_NPCM7XX_RNG);
525
+ object_initialize_child(obj, "adc", &s->adc, TYPE_NPCM7XX_ADC);
526
527
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
528
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
529
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
530
sysbus_realize(SYS_BUS_DEVICE(&s->mc), &error_abort);
531
sysbus_mmio_map(SYS_BUS_DEVICE(&s->mc), 0, NPCM7XX_MC_BA);
532
533
+ /* ADC Modules. Cannot fail. */
534
+ qdev_connect_clock_in(DEVICE(&s->adc), "clock", qdev_get_clock_out(
535
+ DEVICE(&s->clk), "adc-clock"));
536
+ sysbus_realize(SYS_BUS_DEVICE(&s->adc), &error_abort);
537
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->adc), 0, NPCM7XX_ADC_BA);
538
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->adc), 0,
539
+ npcm7xx_irq(s, NPCM7XX_ADC_IRQ));
540
+ npcm7xx_write_adc_calibration(s);
541
+
542
/* Timer Modules (TIM). Cannot fail. */
543
QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
544
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
545
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
546
create_unimplemented_device("npcm7xx.vdmx", 0xe0800000, 4 * KiB);
547
create_unimplemented_device("npcm7xx.pcierc", 0xe1000000, 64 * KiB);
548
create_unimplemented_device("npcm7xx.kcs", 0xf0007000, 4 * KiB);
549
- create_unimplemented_device("npcm7xx.adc", 0xf000c000, 4 * KiB);
550
create_unimplemented_device("npcm7xx.gfxi", 0xf000e000, 4 * KiB);
551
create_unimplemented_device("npcm7xx.gpio[0]", 0xf0010000, 4 * KiB);
552
create_unimplemented_device("npcm7xx.gpio[1]", 0xf0011000, 4 * KiB);
553
diff --git a/tests/qtest/npcm7xx_adc-test.c b/tests/qtest/npcm7xx_adc-test.c
554
new file mode 100644
555
index XXXXXXX..XXXXXXX
556
--- /dev/null
557
+++ b/tests/qtest/npcm7xx_adc-test.c
558
@@ -XXX,XX +XXX,XX @@
559
+/*
560
+ * QTests for Nuvoton NPCM7xx ADCModules.
561
+ *
562
+ * Copyright 2020 Google LLC
563
+ *
564
+ * This program is free software; you can redistribute it and/or modify it
565
+ * under the terms of the GNU General Public License as published by the
566
+ * Free Software Foundation; either version 2 of the License, or
567
+ * (at your option) any later version.
568
+ *
569
+ * This program is distributed in the hope that it will be useful, but WITHOUT
570
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
571
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
572
+ * for more details.
573
+ */
574
+
575
+#include "qemu/osdep.h"
576
+#include "qemu/bitops.h"
577
+#include "qemu/timer.h"
578
+#include "libqos/libqtest.h"
579
+#include "qapi/qmp/qdict.h"
580
+
581
+#define REF_HZ (25000000)
582
+
583
+#define CON_OFFSET 0x0
584
+#define DATA_OFFSET 0x4
585
+
586
+#define NUM_INPUTS 8
587
+#define DEFAULT_IREF 2000000
588
+#define CONV_CYCLES 20
589
+#define RESET_CYCLES 10
590
+#define R0_INPUT 500000
591
+#define R1_INPUT 1500000
592
+#define MAX_RESULT 1023
593
+
594
+#define DEFAULT_CLKDIV 5
595
+
596
+#define FUSE_ARRAY_BA 0xf018a000
597
+#define FCTL_OFFSET 0x14
598
+#define FST_OFFSET 0x0
599
+#define FADDR_OFFSET 0x4
600
+#define FDATA_OFFSET 0x8
601
+#define ADC_CALIB_ADDR 24
602
+#define FUSE_READ 0x2
603
+
604
+/* Register field definitions. */
605
+#define CON_MUX(rv) ((rv) << 24)
606
+#define CON_INT_EN BIT(21)
607
+#define CON_REFSEL BIT(19)
608
+#define CON_INT BIT(18)
609
+#define CON_EN BIT(17)
610
+#define CON_RST BIT(16)
611
+#define CON_CONV BIT(14)
612
+#define CON_DIV(rv) extract32(rv, 1, 8)
613
+
614
+#define FST_RDST BIT(1)
615
+#define FDATA_MASK 0xff
616
+
617
+#define MAX_ERROR 10000
618
+#define MIN_CALIB_INPUT 100000
619
+#define MAX_CALIB_INPUT 1800000
620
+
621
+static const uint32_t input_list[] = {
622
+ 100000,
623
+ 500000,
624
+ 1000000,
625
+ 1500000,
626
+ 1800000,
627
+ 2000000,
628
+};
629
+
630
+static const uint32_t vref_list[] = {
631
+ 2000000,
632
+ 2200000,
633
+ 2500000,
634
+};
635
+
636
+static const uint32_t iref_list[] = {
637
+ 1800000,
638
+ 1900000,
639
+ 2000000,
640
+ 2100000,
641
+ 2200000,
642
+};
643
+
644
+static const uint32_t div_list[] = {0, 1, 3, 7, 15};
645
+
646
+typedef struct ADC {
647
+ int irq;
648
+ uint64_t base_addr;
649
+} ADC;
650
+
651
+ADC adc = {
652
+ .irq = 0,
653
+ .base_addr = 0xf000c000
654
+};
655
+
656
+static uint32_t adc_read_con(QTestState *qts, const ADC *adc)
657
+{
658
+ return qtest_readl(qts, adc->base_addr + CON_OFFSET);
659
+}
660
+
661
+static void adc_write_con(QTestState *qts, const ADC *adc, uint32_t value)
662
+{
663
+ qtest_writel(qts, adc->base_addr + CON_OFFSET, value);
664
+}
665
+
666
+static uint32_t adc_read_data(QTestState *qts, const ADC *adc)
667
+{
668
+ return qtest_readl(qts, adc->base_addr + DATA_OFFSET);
669
+}
670
+
671
+static uint32_t adc_calibrate(uint32_t measured, uint32_t *rv)
672
+{
673
+ return R0_INPUT + (R1_INPUT - R0_INPUT) * (int32_t)(measured - rv[0])
674
+ / (int32_t)(rv[1] - rv[0]);
675
+}
676
+
677
+static void adc_qom_set(QTestState *qts, const ADC *adc,
678
+ const char *name, uint32_t value)
679
+{
680
+ QDict *response;
681
+ const char *path = "/machine/soc/adc";
682
+
683
+ g_test_message("Setting properties %s of %s with value %u",
684
+ name, path, value);
685
+ response = qtest_qmp(qts, "{ 'execute': 'qom-set',"
686
+ " 'arguments': { 'path': %s, 'property': %s, 'value': %u}}",
687
+ path, name, value);
688
+ /* The qom set message returns successfully. */
689
+ g_assert_true(qdict_haskey(response, "return"));
690
+}
691
+
692
+static void adc_write_input(QTestState *qts, const ADC *adc,
693
+ uint32_t index, uint32_t value)
694
+{
695
+ char name[100];
696
+
697
+ sprintf(name, "adci[%u]", index);
698
+ adc_qom_set(qts, adc, name, value);
699
+}
700
+
701
+static void adc_write_vref(QTestState *qts, const ADC *adc, uint32_t value)
702
+{
703
+ adc_qom_set(qts, adc, "vref", value);
704
+}
705
+
706
+static uint32_t adc_calculate_output(uint32_t input, uint32_t ref)
707
+{
708
+ uint32_t output;
709
+
710
+ g_assert_cmpuint(input, <=, ref);
711
+ output = (input * (MAX_RESULT + 1)) / ref;
712
+ if (output > MAX_RESULT) {
713
+ output = MAX_RESULT;
714
+ }
715
+
716
+ return output;
717
+}
718
+
719
+static uint32_t adc_prescaler(QTestState *qts, const ADC *adc)
720
+{
721
+ uint32_t div = extract32(adc_read_con(qts, adc), 1, 8);
722
+
723
+ return 2 * (div + 1);
724
+}
725
+
726
+static int64_t adc_calculate_steps(uint32_t cycles, uint32_t prescale,
727
+ uint32_t clkdiv)
728
+{
729
+ return (NANOSECONDS_PER_SECOND / (REF_HZ >> clkdiv)) * cycles * prescale;
730
+}
731
+
732
+static void adc_wait_conv_finished(QTestState *qts, const ADC *adc,
733
+ uint32_t clkdiv)
734
+{
735
+ uint32_t prescaler = adc_prescaler(qts, adc);
736
+
737
+ /*
738
+ * ADC should takes roughly 20 cycles to convert one sample. So we assert it
739
+ * should take 10~30 cycles here.
740
+ */
741
+ qtest_clock_step(qts, adc_calculate_steps(CONV_CYCLES / 2, prescaler,
742
+ clkdiv));
743
+ /* ADC is still converting. */
744
+ g_assert_true(adc_read_con(qts, adc) & CON_CONV);
745
+ qtest_clock_step(qts, adc_calculate_steps(CONV_CYCLES, prescaler, clkdiv));
746
+ /* ADC has finished conversion. */
747
+ g_assert_false(adc_read_con(qts, adc) & CON_CONV);
748
+}
749
+
750
+/* Check ADC can be reset to default value. */
751
+static void test_init(gconstpointer adc_p)
752
+{
753
+ const ADC *adc = adc_p;
754
+
755
+ QTestState *qts = qtest_init("-machine quanta-gsj");
756
+ adc_write_con(qts, adc, CON_REFSEL | CON_INT);
757
+ g_assert_cmphex(adc_read_con(qts, adc), ==, CON_REFSEL);
758
+ qtest_quit(qts);
759
+}
760
+
761
+/* Check ADC can convert from an internal reference. */
762
+static void test_convert_internal(gconstpointer adc_p)
763
+{
764
+ const ADC *adc = adc_p;
765
+ uint32_t index, input, output, expected_output;
766
+ QTestState *qts = qtest_init("-machine quanta-gsj");
767
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
768
+
769
+ for (index = 0; index < NUM_INPUTS; ++index) {
770
+ for (size_t i = 0; i < ARRAY_SIZE(input_list); ++i) {
771
+ input = input_list[i];
772
+ expected_output = adc_calculate_output(input, DEFAULT_IREF);
773
+
774
+ adc_write_input(qts, adc, index, input);
775
+ adc_write_con(qts, adc, CON_MUX(index) | CON_REFSEL | CON_INT |
776
+ CON_EN | CON_CONV);
777
+ adc_wait_conv_finished(qts, adc, DEFAULT_CLKDIV);
778
+ g_assert_cmphex(adc_read_con(qts, adc), ==, CON_MUX(index) |
779
+ CON_REFSEL | CON_EN);
780
+ g_assert_false(qtest_get_irq(qts, adc->irq));
781
+ output = adc_read_data(qts, adc);
782
+ g_assert_cmpuint(output, ==, expected_output);
783
+ }
784
+ }
785
+
786
+ qtest_quit(qts);
787
+}
788
+
789
+/* Check ADC can convert from an external reference. */
790
+static void test_convert_external(gconstpointer adc_p)
791
+{
792
+ const ADC *adc = adc_p;
793
+ uint32_t index, input, vref, output, expected_output;
794
+ QTestState *qts = qtest_init("-machine quanta-gsj");
795
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
796
+
797
+ for (index = 0; index < NUM_INPUTS; ++index) {
798
+ for (size_t i = 0; i < ARRAY_SIZE(input_list); ++i) {
799
+ for (size_t j = 0; j < ARRAY_SIZE(vref_list); ++j) {
800
+ input = input_list[i];
801
+ vref = vref_list[j];
802
+ expected_output = adc_calculate_output(input, vref);
803
+
804
+ adc_write_input(qts, adc, index, input);
805
+ adc_write_vref(qts, adc, vref);
806
+ adc_write_con(qts, adc, CON_MUX(index) | CON_INT | CON_EN |
807
+ CON_CONV);
808
+ adc_wait_conv_finished(qts, adc, DEFAULT_CLKDIV);
809
+ g_assert_cmphex(adc_read_con(qts, adc), ==,
810
+ CON_MUX(index) | CON_EN);
811
+ g_assert_false(qtest_get_irq(qts, adc->irq));
812
+ output = adc_read_data(qts, adc);
813
+ g_assert_cmpuint(output, ==, expected_output);
814
+ }
815
+ }
816
+ }
817
+
818
+ qtest_quit(qts);
819
+}
820
+
821
+/* Check ADC interrupt files if and only if CON_INT_EN is set. */
822
+static void test_interrupt(gconstpointer adc_p)
823
+{
824
+ const ADC *adc = adc_p;
825
+ uint32_t index, input, output, expected_output;
826
+ QTestState *qts = qtest_init("-machine quanta-gsj");
827
+
828
+ index = 1;
829
+ input = input_list[1];
830
+ expected_output = adc_calculate_output(input, DEFAULT_IREF);
831
+
832
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
833
+ adc_write_input(qts, adc, index, input);
834
+ g_assert_false(qtest_get_irq(qts, adc->irq));
835
+ adc_write_con(qts, adc, CON_MUX(index) | CON_INT_EN | CON_REFSEL | CON_INT
836
+ | CON_EN | CON_CONV);
837
+ adc_wait_conv_finished(qts, adc, DEFAULT_CLKDIV);
838
+ g_assert_cmphex(adc_read_con(qts, adc), ==, CON_MUX(index) | CON_INT_EN
839
+ | CON_REFSEL | CON_INT | CON_EN);
840
+ g_assert_true(qtest_get_irq(qts, adc->irq));
841
+ output = adc_read_data(qts, adc);
842
+ g_assert_cmpuint(output, ==, expected_output);
843
+
844
+ qtest_quit(qts);
845
+}
846
+
847
+/* Check ADC is reset after setting ADC_RST for 10 ADC cycles. */
848
+static void test_reset(gconstpointer adc_p)
849
+{
850
+ const ADC *adc = adc_p;
851
+ QTestState *qts = qtest_init("-machine quanta-gsj");
852
+
853
+ for (size_t i = 0; i < ARRAY_SIZE(div_list); ++i) {
854
+ uint32_t div = div_list[i];
855
+
856
+ adc_write_con(qts, adc, CON_INT | CON_EN | CON_RST | CON_DIV(div));
857
+ qtest_clock_step(qts, adc_calculate_steps(RESET_CYCLES,
858
+ adc_prescaler(qts, adc), DEFAULT_CLKDIV));
859
+ g_assert_false(adc_read_con(qts, adc) & CON_EN);
860
+ }
861
+ qtest_quit(qts);
862
+}
863
+
864
+/* Check ADC Calibration works as desired. */
865
+static void test_calibrate(gconstpointer adc_p)
866
+{
867
+ int i, j;
868
+ const ADC *adc = adc_p;
869
+
870
+ for (j = 0; j < ARRAY_SIZE(iref_list); ++j) {
871
+ uint32_t iref = iref_list[j];
872
+ uint32_t expected_rv[] = {
873
+ adc_calculate_output(R0_INPUT, iref),
874
+ adc_calculate_output(R1_INPUT, iref),
875
+ };
876
+ char buf[100];
877
+ QTestState *qts;
878
+
879
+ sprintf(buf, "-machine quanta-gsj -global npcm7xx-adc.iref=%u", iref);
880
+ qts = qtest_init(buf);
881
+
882
+ /* Check the converted value is correct using the calibration value. */
883
+ for (i = 0; i < ARRAY_SIZE(input_list); ++i) {
884
+ uint32_t input;
885
+ uint32_t output;
886
+ uint32_t expected_output;
887
+ uint32_t calibrated_voltage;
888
+ uint32_t index = 0;
889
+
890
+ input = input_list[i];
891
+ /* Calibration only works for input range 0.1V ~ 1.8V. */
892
+ if (input < MIN_CALIB_INPUT || input > MAX_CALIB_INPUT) {
893
+ continue;
894
+ }
895
+ expected_output = adc_calculate_output(input, iref);
896
+
897
+ adc_write_input(qts, adc, index, input);
898
+ adc_write_con(qts, adc, CON_MUX(index) | CON_REFSEL | CON_INT |
899
+ CON_EN | CON_CONV);
900
+ adc_wait_conv_finished(qts, adc, DEFAULT_CLKDIV);
901
+ g_assert_cmphex(adc_read_con(qts, adc), ==,
902
+ CON_REFSEL | CON_MUX(index) | CON_EN);
903
+ output = adc_read_data(qts, adc);
904
+ g_assert_cmpuint(output, ==, expected_output);
905
+
906
+ calibrated_voltage = adc_calibrate(output, expected_rv);
907
+ g_assert_cmpuint(calibrated_voltage, >, input - MAX_ERROR);
908
+ g_assert_cmpuint(calibrated_voltage, <, input + MAX_ERROR);
909
+ }
910
+
911
+ qtest_quit(qts);
912
+ }
913
+}
914
+
915
+static void adc_add_test(const char *name, const ADC* wd,
916
+ GTestDataFunc fn)
917
+{
918
+ g_autofree char *full_name = g_strdup_printf("npcm7xx_adc/%s", name);
919
+ qtest_add_data_func(full_name, wd, fn);
920
+}
921
+#define add_test(name, td) adc_add_test(#name, td, test_##name)
922
+
923
+int main(int argc, char **argv)
924
+{
925
+ g_test_init(&argc, &argv, NULL);
926
+
927
+ add_test(init, &adc);
928
+ add_test(convert_internal, &adc);
929
+ add_test(convert_external, &adc);
930
+ add_test(interrupt, &adc);
931
+ add_test(reset, &adc);
932
+ add_test(calibrate, &adc);
933
+
934
+ return g_test_run();
935
+}
936
diff --git a/hw/adc/meson.build b/hw/adc/meson.build
937
index XXXXXXX..XXXXXXX 100644
938
--- a/hw/adc/meson.build
939
+++ b/hw/adc/meson.build
940
@@ -1 +1,2 @@
941
softmmu_ss.add(when: 'CONFIG_STM32F2XX_ADC', if_true: files('stm32f2xx_adc.c'))
942
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_adc.c'))
943
diff --git a/hw/adc/trace-events b/hw/adc/trace-events
944
new file mode 100644
945
index XXXXXXX..XXXXXXX
946
--- /dev/null
947
+++ b/hw/adc/trace-events
948
@@ -XXX,XX +XXX,XX @@
949
+# See docs/devel/tracing.txt for syntax documentation.
950
+
951
+# npcm7xx_adc.c
952
+npcm7xx_adc_read(const char *id, uint64_t offset, uint32_t value) " %s offset: 0x%04" PRIx64 " value 0x%04" PRIx32
953
+npcm7xx_adc_write(const char *id, uint64_t offset, uint32_t value) "%s offset: 0x%04" PRIx64 " value 0x%04" PRIx32
954
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
955
index XXXXXXX..XXXXXXX 100644
956
--- a/tests/qtest/meson.build
957
+++ b/tests/qtest/meson.build
958
@@ -XXX,XX +XXX,XX @@ qtests_sparc64 = \
959
['prom-env-test', 'boot-serial-test']
960
961
qtests_npcm7xx = \
962
- ['npcm7xx_gpio-test',
963
+ ['npcm7xx_adc-test',
964
+ 'npcm7xx_gpio-test',
965
'npcm7xx_rng-test',
966
'npcm7xx_timer-test',
967
'npcm7xx_watchdog_timer-test']
968
--
253
--
969
2.20.1
254
2.34.1
970
255
971
256
diff view generated by jsdifflib
1
From: Leif Lindholm <leif@nuviainc.com>
1
The sun4v RTC device model added under commit a0e893039cf2ce0 in 2016
2
was unfortunately added with a license of GPL-v3-or-later, which is
3
not compatible with other QEMU code which has a GPL-v2-only license.
2
4
3
SBSS -> SSBS
5
Relicense the code in the .c and the .h file to GPL-v2-or-later,
6
to make it compatible with the rest of QEMU.
4
7
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
8
Cc: qemu-stable@nongnu.org
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Paolo Bonzini (for Red Hat) <pbonzini@redhat.com>
8
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
11
Signed-off-by: Artyom Tarasenko <atar4qemu@gmail.com>
9
Message-id: 20210108185154.8108-2-leif@nuviainc.com
12
Signed-off-by: Markus Armbruster <armbru@redhat.com>
13
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
14
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
15
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
16
Acked-by: Alex Bennée <alex.bennee@linaro.org>
17
Message-id: 20240223161300.938542-1-peter.maydell@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
19
---
12
target/arm/cpu.h | 2 +-
20
include/hw/rtc/sun4v-rtc.h | 2 +-
13
1 file changed, 1 insertion(+), 1 deletion(-)
21
hw/rtc/sun4v-rtc.c | 2 +-
22
2 files changed, 2 insertions(+), 2 deletions(-)
14
23
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
24
diff --git a/include/hw/rtc/sun4v-rtc.h b/include/hw/rtc/sun4v-rtc.h
16
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
26
--- a/include/hw/rtc/sun4v-rtc.h
18
+++ b/target/arm/cpu.h
27
+++ b/include/hw/rtc/sun4v-rtc.h
19
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64PFR0, RAS, 28, 4)
28
@@ -XXX,XX +XXX,XX @@
20
FIELD(ID_AA64PFR0, SVE, 32, 4)
29
*
21
30
* Copyright (c) 2016 Artyom Tarasenko
22
FIELD(ID_AA64PFR1, BT, 0, 4)
31
*
23
-FIELD(ID_AA64PFR1, SBSS, 4, 4)
32
- * This code is licensed under the GNU GPL v3 or (at your option) any later
24
+FIELD(ID_AA64PFR1, SSBS, 4, 4)
33
+ * This code is licensed under the GNU GPL v2 or (at your option) any later
25
FIELD(ID_AA64PFR1, MTE, 8, 4)
34
* version.
26
FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4)
35
*/
36
37
diff --git a/hw/rtc/sun4v-rtc.c b/hw/rtc/sun4v-rtc.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/rtc/sun4v-rtc.c
40
+++ b/hw/rtc/sun4v-rtc.c
41
@@ -XXX,XX +XXX,XX @@
42
*
43
* Copyright (c) 2016 Artyom Tarasenko
44
*
45
- * This code is licensed under the GNU GPL v3 or (at your option) any later
46
+ * This code is licensed under the GNU GPL v2 or (at your option) any later
47
* version.
48
*/
27
49
28
--
50
--
29
2.20.1
51
2.34.1
30
52
31
53
diff view generated by jsdifflib
Deleted patch
1
From: Leif Lindholm <leif@nuviainc.com>
2
1
3
The AArch64 view of CLIDR_EL1 extends the ICB field to include also bit
4
32, as well as adding a Ttype<n> field when FEAT_MTE is implemented.
5
Extend the clidr field to be able to hold this context.
6
7
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
11
Message-id: 20210108185154.8108-3-leif@nuviainc.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
target/arm/cpu.h | 2 +-
15
1 file changed, 1 insertion(+), 1 deletion(-)
16
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
21
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
22
uint32_t id_afr0;
23
uint64_t id_aa64afr0;
24
uint64_t id_aa64afr1;
25
- uint32_t clidr;
26
+ uint64_t clidr;
27
uint64_t mp_affinity; /* MP ID without feature bits */
28
/* The elements of this array are the CCSIDR values for each cache,
29
* in the order L1DCache, L1ICache, L2DCache, L2ICache, etc.
30
--
31
2.20.1
32
33
diff view generated by jsdifflib
Deleted patch
1
From: Leif Lindholm <leif@nuviainc.com>
2
1
3
When FEAT_MTE is implemented, the AArch64 view of CTR_EL0 adds the
4
TminLine field in bits [37:32].
5
Extend the ctr field to be able to hold this context.
6
7
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
8
Reviewed-by: Hao Wu <wuhaotsh@google.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
11
Message-id: 20210108185154.8108-4-leif@nuviainc.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
target/arm/cpu.h | 2 +-
15
1 file changed, 1 insertion(+), 1 deletion(-)
16
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
21
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
22
uint64_t midr;
23
uint32_t revidr;
24
uint32_t reset_fpsid;
25
- uint32_t ctr;
26
+ uint64_t ctr;
27
uint32_t reset_sctlr;
28
uint64_t pmceid0;
29
uint64_t pmceid1;
30
--
31
2.20.1
32
33
diff view generated by jsdifflib
Deleted patch
1
From: Leif Lindholm <leif@nuviainc.com>
2
1
3
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
4
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
5
Message-id: 20210108185154.8108-5-leif@nuviainc.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
target/arm/cpu.h | 31 +++++++++++++++++++++++++++++++
9
1 file changed, 31 insertions(+)
10
11
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/cpu.h
14
+++ b/target/arm/cpu.h
15
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_FPCCR, ASPEN, 31, 1)
16
/*
17
* System register ID fields.
18
*/
19
+FIELD(CLIDR_EL1, CTYPE1, 0, 3)
20
+FIELD(CLIDR_EL1, CTYPE2, 3, 3)
21
+FIELD(CLIDR_EL1, CTYPE3, 6, 3)
22
+FIELD(CLIDR_EL1, CTYPE4, 9, 3)
23
+FIELD(CLIDR_EL1, CTYPE5, 12, 3)
24
+FIELD(CLIDR_EL1, CTYPE6, 15, 3)
25
+FIELD(CLIDR_EL1, CTYPE7, 18, 3)
26
+FIELD(CLIDR_EL1, LOUIS, 21, 3)
27
+FIELD(CLIDR_EL1, LOC, 24, 3)
28
+FIELD(CLIDR_EL1, LOUU, 27, 3)
29
+FIELD(CLIDR_EL1, ICB, 30, 3)
30
+
31
+/* When FEAT_CCIDX is implemented */
32
+FIELD(CCSIDR_EL1, CCIDX_LINESIZE, 0, 3)
33
+FIELD(CCSIDR_EL1, CCIDX_ASSOCIATIVITY, 3, 21)
34
+FIELD(CCSIDR_EL1, CCIDX_NUMSETS, 32, 24)
35
+
36
+/* When FEAT_CCIDX is not implemented */
37
+FIELD(CCSIDR_EL1, LINESIZE, 0, 3)
38
+FIELD(CCSIDR_EL1, ASSOCIATIVITY, 3, 10)
39
+FIELD(CCSIDR_EL1, NUMSETS, 13, 15)
40
+
41
+FIELD(CTR_EL0, IMINLINE, 0, 4)
42
+FIELD(CTR_EL0, L1IP, 14, 2)
43
+FIELD(CTR_EL0, DMINLINE, 16, 4)
44
+FIELD(CTR_EL0, ERG, 20, 4)
45
+FIELD(CTR_EL0, CWG, 24, 4)
46
+FIELD(CTR_EL0, IDC, 28, 1)
47
+FIELD(CTR_EL0, DIC, 29, 1)
48
+FIELD(CTR_EL0, TMINLINE, 32, 6)
49
+
50
FIELD(MIDR_EL1, REVISION, 0, 4)
51
FIELD(MIDR_EL1, PARTNUM, 4, 12)
52
FIELD(MIDR_EL1, ARCHITECTURE, 16, 4)
53
--
54
2.20.1
55
56
diff view generated by jsdifflib
Deleted patch
1
From: Leif Lindholm <leif@nuviainc.com>
2
1
3
Add entries present in ARM DDI 0487F.c (August 2020).
4
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
8
Message-id: 20210108185154.8108-6-leif@nuviainc.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/cpu.h | 15 +++++++++++++++
12
1 file changed, 15 insertions(+)
13
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64ISAR1, GPI, 28, 4)
19
FIELD(ID_AA64ISAR1, FRINTTS, 32, 4)
20
FIELD(ID_AA64ISAR1, SB, 36, 4)
21
FIELD(ID_AA64ISAR1, SPECRES, 40, 4)
22
+FIELD(ID_AA64ISAR1, BF16, 44, 4)
23
+FIELD(ID_AA64ISAR1, DGH, 48, 4)
24
+FIELD(ID_AA64ISAR1, I8MM, 52, 4)
25
26
FIELD(ID_AA64PFR0, EL0, 0, 4)
27
FIELD(ID_AA64PFR0, EL1, 4, 4)
28
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64PFR0, ADVSIMD, 20, 4)
29
FIELD(ID_AA64PFR0, GIC, 24, 4)
30
FIELD(ID_AA64PFR0, RAS, 28, 4)
31
FIELD(ID_AA64PFR0, SVE, 32, 4)
32
+FIELD(ID_AA64PFR0, SEL2, 36, 4)
33
+FIELD(ID_AA64PFR0, MPAM, 40, 4)
34
+FIELD(ID_AA64PFR0, AMU, 44, 4)
35
+FIELD(ID_AA64PFR0, DIT, 48, 4)
36
+FIELD(ID_AA64PFR0, CSV2, 56, 4)
37
+FIELD(ID_AA64PFR0, CSV3, 60, 4)
38
39
FIELD(ID_AA64PFR1, BT, 0, 4)
40
FIELD(ID_AA64PFR1, SSBS, 4, 4)
41
FIELD(ID_AA64PFR1, MTE, 8, 4)
42
FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4)
43
+FIELD(ID_AA64PFR1, MPAM_FRAC, 16, 4)
44
45
FIELD(ID_AA64MMFR0, PARANGE, 0, 4)
46
FIELD(ID_AA64MMFR0, ASIDBITS, 4, 4)
47
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64MMFR0, TGRAN16_2, 32, 4)
48
FIELD(ID_AA64MMFR0, TGRAN64_2, 36, 4)
49
FIELD(ID_AA64MMFR0, TGRAN4_2, 40, 4)
50
FIELD(ID_AA64MMFR0, EXS, 44, 4)
51
+FIELD(ID_AA64MMFR0, FGT, 56, 4)
52
+FIELD(ID_AA64MMFR0, ECV, 60, 4)
53
54
FIELD(ID_AA64MMFR1, HAFDBS, 0, 4)
55
FIELD(ID_AA64MMFR1, VMIDBITS, 4, 4)
56
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64MMFR1, LO, 16, 4)
57
FIELD(ID_AA64MMFR1, PAN, 20, 4)
58
FIELD(ID_AA64MMFR1, SPECSEI, 24, 4)
59
FIELD(ID_AA64MMFR1, XNX, 28, 4)
60
+FIELD(ID_AA64MMFR1, TWED, 32, 4)
61
+FIELD(ID_AA64MMFR1, ETS, 36, 4)
62
63
FIELD(ID_AA64MMFR2, CNP, 0, 4)
64
FIELD(ID_AA64MMFR2, UAO, 4, 4)
65
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64DFR0, CTX_CMPS, 28, 4)
66
FIELD(ID_AA64DFR0, PMSVER, 32, 4)
67
FIELD(ID_AA64DFR0, DOUBLELOCK, 36, 4)
68
FIELD(ID_AA64DFR0, TRACEFILT, 40, 4)
69
+FIELD(ID_AA64DFR0, MTPMU, 48, 4)
70
71
FIELD(ID_DFR0, COPDBG, 0, 4)
72
FIELD(ID_DFR0, COPSDBG, 4, 4)
73
--
74
2.20.1
75
76
diff view generated by jsdifflib
Deleted patch
1
From: Roman Bolshakov <r.bolshakov@yadro.com>
2
1
3
QEMU documentation can't be opened if QEMU is run from build tree
4
because executables are placed in the top of build tree after conversion
5
to meson.
6
7
Signed-off-by: Roman Bolshakov <r.bolshakov@yadro.com>
8
Reported-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20210108213815.64678-1-r.bolshakov@yadro.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
ui/cocoa.m | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/ui/cocoa.m b/ui/cocoa.m
17
index XXXXXXX..XXXXXXX 100644
18
--- a/ui/cocoa.m
19
+++ b/ui/cocoa.m
20
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
21
- (void) openDocumentation: (NSString *) filename
22
{
23
/* Where to look for local files */
24
- NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"../docs/"};
25
+ NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"docs/"};
26
NSString *full_file_path;
27
28
/* iterate thru the possible paths until the file is found */
29
--
30
2.20.1
31
32
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
This patch makes NPCM7XX Timer to use a the timer clock generated by the
3
Move the code to a separate file so that we do not have to compile
4
CLK module instead of the magic number TIMER_REF_HZ.
4
it anymore if CONFIG_ARM_V7M is not set.
5
5
6
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
6
Signed-off-by: Thomas Huth <thuth@redhat.com>
7
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
7
Message-id: 20240308141051.536599-2-thuth@redhat.com
8
Signed-off-by: Hao Wu <wuhaotsh@google.com>
9
Message-id: 20210108190945.949196-3-wuhaotsh@google.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
10
---
13
include/hw/misc/npcm7xx_clk.h | 6 -----
11
target/arm/tcg/cpu-v7m.c | 290 +++++++++++++++++++++++++++++++++++++
14
include/hw/timer/npcm7xx_timer.h | 1 +
12
target/arm/tcg/cpu32.c | 261 ---------------------------------
15
hw/arm/npcm7xx.c | 5 ++++
13
target/arm/meson.build | 3 +
16
hw/timer/npcm7xx_timer.c | 39 +++++++++++++++-----------------
14
target/arm/tcg/meson.build | 3 +
17
4 files changed, 24 insertions(+), 27 deletions(-)
15
4 files changed, 296 insertions(+), 261 deletions(-)
16
create mode 100644 target/arm/tcg/cpu-v7m.c
18
17
19
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
18
diff --git a/target/arm/tcg/cpu-v7m.c b/target/arm/tcg/cpu-v7m.c
19
new file mode 100644
20
index XXXXXXX..XXXXXXX
21
--- /dev/null
22
+++ b/target/arm/tcg/cpu-v7m.c
23
@@ -XXX,XX +XXX,XX @@
24
+/*
25
+ * QEMU ARMv7-M TCG-only CPUs.
26
+ *
27
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
28
+ *
29
+ * This code is licensed under the GNU GPL v2 or later.
30
+ *
31
+ * SPDX-License-Identifier: GPL-2.0-or-later
32
+ */
33
+
34
+#include "qemu/osdep.h"
35
+#include "cpu.h"
36
+#include "hw/core/tcg-cpu-ops.h"
37
+#include "internals.h"
38
+
39
+#if !defined(CONFIG_USER_ONLY)
40
+
41
+#include "hw/intc/armv7m_nvic.h"
42
+
43
+static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
44
+{
45
+ CPUClass *cc = CPU_GET_CLASS(cs);
46
+ ARMCPU *cpu = ARM_CPU(cs);
47
+ CPUARMState *env = &cpu->env;
48
+ bool ret = false;
49
+
50
+ /*
51
+ * ARMv7-M interrupt masking works differently than -A or -R.
52
+ * There is no FIQ/IRQ distinction. Instead of I and F bits
53
+ * masking FIQ and IRQ interrupts, an exception is taken only
54
+ * if it is higher priority than the current execution priority
55
+ * (which depends on state like BASEPRI, FAULTMASK and the
56
+ * currently active exception).
57
+ */
58
+ if (interrupt_request & CPU_INTERRUPT_HARD
59
+ && (armv7m_nvic_can_take_pending_exception(env->nvic))) {
60
+ cs->exception_index = EXCP_IRQ;
61
+ cc->tcg_ops->do_interrupt(cs);
62
+ ret = true;
63
+ }
64
+ return ret;
65
+}
66
+
67
+#endif /* !CONFIG_USER_ONLY */
68
+
69
+static void cortex_m0_initfn(Object *obj)
70
+{
71
+ ARMCPU *cpu = ARM_CPU(obj);
72
+ set_feature(&cpu->env, ARM_FEATURE_V6);
73
+ set_feature(&cpu->env, ARM_FEATURE_M);
74
+
75
+ cpu->midr = 0x410cc200;
76
+
77
+ /*
78
+ * These ID register values are not guest visible, because
79
+ * we do not implement the Main Extension. They must be set
80
+ * to values corresponding to the Cortex-M0's implemented
81
+ * features, because QEMU generally controls its emulation
82
+ * by looking at ID register fields. We use the same values as
83
+ * for the M3.
84
+ */
85
+ cpu->isar.id_pfr0 = 0x00000030;
86
+ cpu->isar.id_pfr1 = 0x00000200;
87
+ cpu->isar.id_dfr0 = 0x00100000;
88
+ cpu->id_afr0 = 0x00000000;
89
+ cpu->isar.id_mmfr0 = 0x00000030;
90
+ cpu->isar.id_mmfr1 = 0x00000000;
91
+ cpu->isar.id_mmfr2 = 0x00000000;
92
+ cpu->isar.id_mmfr3 = 0x00000000;
93
+ cpu->isar.id_isar0 = 0x01141110;
94
+ cpu->isar.id_isar1 = 0x02111000;
95
+ cpu->isar.id_isar2 = 0x21112231;
96
+ cpu->isar.id_isar3 = 0x01111110;
97
+ cpu->isar.id_isar4 = 0x01310102;
98
+ cpu->isar.id_isar5 = 0x00000000;
99
+ cpu->isar.id_isar6 = 0x00000000;
100
+}
101
+
102
+static void cortex_m3_initfn(Object *obj)
103
+{
104
+ ARMCPU *cpu = ARM_CPU(obj);
105
+ set_feature(&cpu->env, ARM_FEATURE_V7);
106
+ set_feature(&cpu->env, ARM_FEATURE_M);
107
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
108
+ cpu->midr = 0x410fc231;
109
+ cpu->pmsav7_dregion = 8;
110
+ cpu->isar.id_pfr0 = 0x00000030;
111
+ cpu->isar.id_pfr1 = 0x00000200;
112
+ cpu->isar.id_dfr0 = 0x00100000;
113
+ cpu->id_afr0 = 0x00000000;
114
+ cpu->isar.id_mmfr0 = 0x00000030;
115
+ cpu->isar.id_mmfr1 = 0x00000000;
116
+ cpu->isar.id_mmfr2 = 0x00000000;
117
+ cpu->isar.id_mmfr3 = 0x00000000;
118
+ cpu->isar.id_isar0 = 0x01141110;
119
+ cpu->isar.id_isar1 = 0x02111000;
120
+ cpu->isar.id_isar2 = 0x21112231;
121
+ cpu->isar.id_isar3 = 0x01111110;
122
+ cpu->isar.id_isar4 = 0x01310102;
123
+ cpu->isar.id_isar5 = 0x00000000;
124
+ cpu->isar.id_isar6 = 0x00000000;
125
+}
126
+
127
+static void cortex_m4_initfn(Object *obj)
128
+{
129
+ ARMCPU *cpu = ARM_CPU(obj);
130
+
131
+ set_feature(&cpu->env, ARM_FEATURE_V7);
132
+ set_feature(&cpu->env, ARM_FEATURE_M);
133
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
134
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
135
+ cpu->midr = 0x410fc240; /* r0p0 */
136
+ cpu->pmsav7_dregion = 8;
137
+ cpu->isar.mvfr0 = 0x10110021;
138
+ cpu->isar.mvfr1 = 0x11000011;
139
+ cpu->isar.mvfr2 = 0x00000000;
140
+ cpu->isar.id_pfr0 = 0x00000030;
141
+ cpu->isar.id_pfr1 = 0x00000200;
142
+ cpu->isar.id_dfr0 = 0x00100000;
143
+ cpu->id_afr0 = 0x00000000;
144
+ cpu->isar.id_mmfr0 = 0x00000030;
145
+ cpu->isar.id_mmfr1 = 0x00000000;
146
+ cpu->isar.id_mmfr2 = 0x00000000;
147
+ cpu->isar.id_mmfr3 = 0x00000000;
148
+ cpu->isar.id_isar0 = 0x01141110;
149
+ cpu->isar.id_isar1 = 0x02111000;
150
+ cpu->isar.id_isar2 = 0x21112231;
151
+ cpu->isar.id_isar3 = 0x01111110;
152
+ cpu->isar.id_isar4 = 0x01310102;
153
+ cpu->isar.id_isar5 = 0x00000000;
154
+ cpu->isar.id_isar6 = 0x00000000;
155
+}
156
+
157
+static void cortex_m7_initfn(Object *obj)
158
+{
159
+ ARMCPU *cpu = ARM_CPU(obj);
160
+
161
+ set_feature(&cpu->env, ARM_FEATURE_V7);
162
+ set_feature(&cpu->env, ARM_FEATURE_M);
163
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
164
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
165
+ cpu->midr = 0x411fc272; /* r1p2 */
166
+ cpu->pmsav7_dregion = 8;
167
+ cpu->isar.mvfr0 = 0x10110221;
168
+ cpu->isar.mvfr1 = 0x12000011;
169
+ cpu->isar.mvfr2 = 0x00000040;
170
+ cpu->isar.id_pfr0 = 0x00000030;
171
+ cpu->isar.id_pfr1 = 0x00000200;
172
+ cpu->isar.id_dfr0 = 0x00100000;
173
+ cpu->id_afr0 = 0x00000000;
174
+ cpu->isar.id_mmfr0 = 0x00100030;
175
+ cpu->isar.id_mmfr1 = 0x00000000;
176
+ cpu->isar.id_mmfr2 = 0x01000000;
177
+ cpu->isar.id_mmfr3 = 0x00000000;
178
+ cpu->isar.id_isar0 = 0x01101110;
179
+ cpu->isar.id_isar1 = 0x02112000;
180
+ cpu->isar.id_isar2 = 0x20232231;
181
+ cpu->isar.id_isar3 = 0x01111131;
182
+ cpu->isar.id_isar4 = 0x01310132;
183
+ cpu->isar.id_isar5 = 0x00000000;
184
+ cpu->isar.id_isar6 = 0x00000000;
185
+}
186
+
187
+static void cortex_m33_initfn(Object *obj)
188
+{
189
+ ARMCPU *cpu = ARM_CPU(obj);
190
+
191
+ set_feature(&cpu->env, ARM_FEATURE_V8);
192
+ set_feature(&cpu->env, ARM_FEATURE_M);
193
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
194
+ set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
195
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
196
+ cpu->midr = 0x410fd213; /* r0p3 */
197
+ cpu->pmsav7_dregion = 16;
198
+ cpu->sau_sregion = 8;
199
+ cpu->isar.mvfr0 = 0x10110021;
200
+ cpu->isar.mvfr1 = 0x11000011;
201
+ cpu->isar.mvfr2 = 0x00000040;
202
+ cpu->isar.id_pfr0 = 0x00000030;
203
+ cpu->isar.id_pfr1 = 0x00000210;
204
+ cpu->isar.id_dfr0 = 0x00200000;
205
+ cpu->id_afr0 = 0x00000000;
206
+ cpu->isar.id_mmfr0 = 0x00101F40;
207
+ cpu->isar.id_mmfr1 = 0x00000000;
208
+ cpu->isar.id_mmfr2 = 0x01000000;
209
+ cpu->isar.id_mmfr3 = 0x00000000;
210
+ cpu->isar.id_isar0 = 0x01101110;
211
+ cpu->isar.id_isar1 = 0x02212000;
212
+ cpu->isar.id_isar2 = 0x20232232;
213
+ cpu->isar.id_isar3 = 0x01111131;
214
+ cpu->isar.id_isar4 = 0x01310132;
215
+ cpu->isar.id_isar5 = 0x00000000;
216
+ cpu->isar.id_isar6 = 0x00000000;
217
+ cpu->clidr = 0x00000000;
218
+ cpu->ctr = 0x8000c000;
219
+}
220
+
221
+static void cortex_m55_initfn(Object *obj)
222
+{
223
+ ARMCPU *cpu = ARM_CPU(obj);
224
+
225
+ set_feature(&cpu->env, ARM_FEATURE_V8);
226
+ set_feature(&cpu->env, ARM_FEATURE_V8_1M);
227
+ set_feature(&cpu->env, ARM_FEATURE_M);
228
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
229
+ set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
230
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
231
+ cpu->midr = 0x410fd221; /* r0p1 */
232
+ cpu->revidr = 0;
233
+ cpu->pmsav7_dregion = 16;
234
+ cpu->sau_sregion = 8;
235
+ /* These are the MVFR* values for the FPU + full MVE configuration */
236
+ cpu->isar.mvfr0 = 0x10110221;
237
+ cpu->isar.mvfr1 = 0x12100211;
238
+ cpu->isar.mvfr2 = 0x00000040;
239
+ cpu->isar.id_pfr0 = 0x20000030;
240
+ cpu->isar.id_pfr1 = 0x00000230;
241
+ cpu->isar.id_dfr0 = 0x10200000;
242
+ cpu->id_afr0 = 0x00000000;
243
+ cpu->isar.id_mmfr0 = 0x00111040;
244
+ cpu->isar.id_mmfr1 = 0x00000000;
245
+ cpu->isar.id_mmfr2 = 0x01000000;
246
+ cpu->isar.id_mmfr3 = 0x00000011;
247
+ cpu->isar.id_isar0 = 0x01103110;
248
+ cpu->isar.id_isar1 = 0x02212000;
249
+ cpu->isar.id_isar2 = 0x20232232;
250
+ cpu->isar.id_isar3 = 0x01111131;
251
+ cpu->isar.id_isar4 = 0x01310132;
252
+ cpu->isar.id_isar5 = 0x00000000;
253
+ cpu->isar.id_isar6 = 0x00000000;
254
+ cpu->clidr = 0x00000000; /* caches not implemented */
255
+ cpu->ctr = 0x8303c003;
256
+}
257
+
258
+static const TCGCPUOps arm_v7m_tcg_ops = {
259
+ .initialize = arm_translate_init,
260
+ .synchronize_from_tb = arm_cpu_synchronize_from_tb,
261
+ .debug_excp_handler = arm_debug_excp_handler,
262
+ .restore_state_to_opc = arm_restore_state_to_opc,
263
+
264
+#ifdef CONFIG_USER_ONLY
265
+ .record_sigsegv = arm_cpu_record_sigsegv,
266
+ .record_sigbus = arm_cpu_record_sigbus,
267
+#else
268
+ .tlb_fill = arm_cpu_tlb_fill,
269
+ .cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt,
270
+ .do_interrupt = arm_v7m_cpu_do_interrupt,
271
+ .do_transaction_failed = arm_cpu_do_transaction_failed,
272
+ .do_unaligned_access = arm_cpu_do_unaligned_access,
273
+ .adjust_watchpoint_address = arm_adjust_watchpoint_address,
274
+ .debug_check_watchpoint = arm_debug_check_watchpoint,
275
+ .debug_check_breakpoint = arm_debug_check_breakpoint,
276
+#endif /* !CONFIG_USER_ONLY */
277
+};
278
+
279
+static void arm_v7m_class_init(ObjectClass *oc, void *data)
280
+{
281
+ ARMCPUClass *acc = ARM_CPU_CLASS(oc);
282
+ CPUClass *cc = CPU_CLASS(oc);
283
+
284
+ acc->info = data;
285
+ cc->tcg_ops = &arm_v7m_tcg_ops;
286
+ cc->gdb_core_xml_file = "arm-m-profile.xml";
287
+}
288
+
289
+static const ARMCPUInfo arm_v7m_cpus[] = {
290
+ { .name = "cortex-m0", .initfn = cortex_m0_initfn,
291
+ .class_init = arm_v7m_class_init },
292
+ { .name = "cortex-m3", .initfn = cortex_m3_initfn,
293
+ .class_init = arm_v7m_class_init },
294
+ { .name = "cortex-m4", .initfn = cortex_m4_initfn,
295
+ .class_init = arm_v7m_class_init },
296
+ { .name = "cortex-m7", .initfn = cortex_m7_initfn,
297
+ .class_init = arm_v7m_class_init },
298
+ { .name = "cortex-m33", .initfn = cortex_m33_initfn,
299
+ .class_init = arm_v7m_class_init },
300
+ { .name = "cortex-m55", .initfn = cortex_m55_initfn,
301
+ .class_init = arm_v7m_class_init },
302
+};
303
+
304
+static void arm_v7m_cpu_register_types(void)
305
+{
306
+ size_t i;
307
+
308
+ for (i = 0; i < ARRAY_SIZE(arm_v7m_cpus); ++i) {
309
+ arm_cpu_register(&arm_v7m_cpus[i]);
310
+ }
311
+}
312
+
313
+type_init(arm_v7m_cpu_register_types)
314
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
20
index XXXXXXX..XXXXXXX 100644
315
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/misc/npcm7xx_clk.h
316
--- a/target/arm/tcg/cpu32.c
22
+++ b/include/hw/misc/npcm7xx_clk.h
317
+++ b/target/arm/tcg/cpu32.c
23
@@ -XXX,XX +XXX,XX @@
318
@@ -XXX,XX +XXX,XX @@
24
#include "hw/clock.h"
319
#include "hw/boards.h"
25
#include "hw/sysbus.h"
320
#endif
26
321
#include "cpregs.h"
27
-/*
322
-#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG)
28
- * The reference clock frequency for the timer modules, and the SECCNT and
323
-#include "hw/intc/armv7m_nvic.h"
29
- * CNTR25M registers in this module, is always 25 MHz.
324
-#endif
30
- */
325
31
-#define NPCM7XX_TIMER_REF_HZ (25000000)
326
32
-
327
/* Share AArch32 -cpu max features with AArch64. */
328
@@ -XXX,XX +XXX,XX @@ void aa32_max_features(ARMCPU *cpu)
329
/* CPU models. These are not needed for the AArch64 linux-user build. */
330
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
331
332
-#if !defined(CONFIG_USER_ONLY)
333
-static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
334
-{
335
- CPUClass *cc = CPU_GET_CLASS(cs);
336
- ARMCPU *cpu = ARM_CPU(cs);
337
- CPUARMState *env = &cpu->env;
338
- bool ret = false;
339
-
340
- /*
341
- * ARMv7-M interrupt masking works differently than -A or -R.
342
- * There is no FIQ/IRQ distinction. Instead of I and F bits
343
- * masking FIQ and IRQ interrupts, an exception is taken only
344
- * if it is higher priority than the current execution priority
345
- * (which depends on state like BASEPRI, FAULTMASK and the
346
- * currently active exception).
347
- */
348
- if (interrupt_request & CPU_INTERRUPT_HARD
349
- && (armv7m_nvic_can_take_pending_exception(env->nvic))) {
350
- cs->exception_index = EXCP_IRQ;
351
- cc->tcg_ops->do_interrupt(cs);
352
- ret = true;
353
- }
354
- return ret;
355
-}
356
-#endif /* !CONFIG_USER_ONLY */
357
-
358
static void arm926_initfn(Object *obj)
359
{
360
ARMCPU *cpu = ARM_CPU(obj);
361
@@ -XXX,XX +XXX,XX @@ static void cortex_a15_initfn(Object *obj)
362
define_arm_cp_regs(cpu, cortexa15_cp_reginfo);
363
}
364
365
-static void cortex_m0_initfn(Object *obj)
366
-{
367
- ARMCPU *cpu = ARM_CPU(obj);
368
- set_feature(&cpu->env, ARM_FEATURE_V6);
369
- set_feature(&cpu->env, ARM_FEATURE_M);
370
-
371
- cpu->midr = 0x410cc200;
372
-
373
- /*
374
- * These ID register values are not guest visible, because
375
- * we do not implement the Main Extension. They must be set
376
- * to values corresponding to the Cortex-M0's implemented
377
- * features, because QEMU generally controls its emulation
378
- * by looking at ID register fields. We use the same values as
379
- * for the M3.
380
- */
381
- cpu->isar.id_pfr0 = 0x00000030;
382
- cpu->isar.id_pfr1 = 0x00000200;
383
- cpu->isar.id_dfr0 = 0x00100000;
384
- cpu->id_afr0 = 0x00000000;
385
- cpu->isar.id_mmfr0 = 0x00000030;
386
- cpu->isar.id_mmfr1 = 0x00000000;
387
- cpu->isar.id_mmfr2 = 0x00000000;
388
- cpu->isar.id_mmfr3 = 0x00000000;
389
- cpu->isar.id_isar0 = 0x01141110;
390
- cpu->isar.id_isar1 = 0x02111000;
391
- cpu->isar.id_isar2 = 0x21112231;
392
- cpu->isar.id_isar3 = 0x01111110;
393
- cpu->isar.id_isar4 = 0x01310102;
394
- cpu->isar.id_isar5 = 0x00000000;
395
- cpu->isar.id_isar6 = 0x00000000;
396
-}
397
-
398
-static void cortex_m3_initfn(Object *obj)
399
-{
400
- ARMCPU *cpu = ARM_CPU(obj);
401
- set_feature(&cpu->env, ARM_FEATURE_V7);
402
- set_feature(&cpu->env, ARM_FEATURE_M);
403
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
404
- cpu->midr = 0x410fc231;
405
- cpu->pmsav7_dregion = 8;
406
- cpu->isar.id_pfr0 = 0x00000030;
407
- cpu->isar.id_pfr1 = 0x00000200;
408
- cpu->isar.id_dfr0 = 0x00100000;
409
- cpu->id_afr0 = 0x00000000;
410
- cpu->isar.id_mmfr0 = 0x00000030;
411
- cpu->isar.id_mmfr1 = 0x00000000;
412
- cpu->isar.id_mmfr2 = 0x00000000;
413
- cpu->isar.id_mmfr3 = 0x00000000;
414
- cpu->isar.id_isar0 = 0x01141110;
415
- cpu->isar.id_isar1 = 0x02111000;
416
- cpu->isar.id_isar2 = 0x21112231;
417
- cpu->isar.id_isar3 = 0x01111110;
418
- cpu->isar.id_isar4 = 0x01310102;
419
- cpu->isar.id_isar5 = 0x00000000;
420
- cpu->isar.id_isar6 = 0x00000000;
421
-}
422
-
423
-static void cortex_m4_initfn(Object *obj)
424
-{
425
- ARMCPU *cpu = ARM_CPU(obj);
426
-
427
- set_feature(&cpu->env, ARM_FEATURE_V7);
428
- set_feature(&cpu->env, ARM_FEATURE_M);
429
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
430
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
431
- cpu->midr = 0x410fc240; /* r0p0 */
432
- cpu->pmsav7_dregion = 8;
433
- cpu->isar.mvfr0 = 0x10110021;
434
- cpu->isar.mvfr1 = 0x11000011;
435
- cpu->isar.mvfr2 = 0x00000000;
436
- cpu->isar.id_pfr0 = 0x00000030;
437
- cpu->isar.id_pfr1 = 0x00000200;
438
- cpu->isar.id_dfr0 = 0x00100000;
439
- cpu->id_afr0 = 0x00000000;
440
- cpu->isar.id_mmfr0 = 0x00000030;
441
- cpu->isar.id_mmfr1 = 0x00000000;
442
- cpu->isar.id_mmfr2 = 0x00000000;
443
- cpu->isar.id_mmfr3 = 0x00000000;
444
- cpu->isar.id_isar0 = 0x01141110;
445
- cpu->isar.id_isar1 = 0x02111000;
446
- cpu->isar.id_isar2 = 0x21112231;
447
- cpu->isar.id_isar3 = 0x01111110;
448
- cpu->isar.id_isar4 = 0x01310102;
449
- cpu->isar.id_isar5 = 0x00000000;
450
- cpu->isar.id_isar6 = 0x00000000;
451
-}
452
-
453
-static void cortex_m7_initfn(Object *obj)
454
-{
455
- ARMCPU *cpu = ARM_CPU(obj);
456
-
457
- set_feature(&cpu->env, ARM_FEATURE_V7);
458
- set_feature(&cpu->env, ARM_FEATURE_M);
459
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
460
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
461
- cpu->midr = 0x411fc272; /* r1p2 */
462
- cpu->pmsav7_dregion = 8;
463
- cpu->isar.mvfr0 = 0x10110221;
464
- cpu->isar.mvfr1 = 0x12000011;
465
- cpu->isar.mvfr2 = 0x00000040;
466
- cpu->isar.id_pfr0 = 0x00000030;
467
- cpu->isar.id_pfr1 = 0x00000200;
468
- cpu->isar.id_dfr0 = 0x00100000;
469
- cpu->id_afr0 = 0x00000000;
470
- cpu->isar.id_mmfr0 = 0x00100030;
471
- cpu->isar.id_mmfr1 = 0x00000000;
472
- cpu->isar.id_mmfr2 = 0x01000000;
473
- cpu->isar.id_mmfr3 = 0x00000000;
474
- cpu->isar.id_isar0 = 0x01101110;
475
- cpu->isar.id_isar1 = 0x02112000;
476
- cpu->isar.id_isar2 = 0x20232231;
477
- cpu->isar.id_isar3 = 0x01111131;
478
- cpu->isar.id_isar4 = 0x01310132;
479
- cpu->isar.id_isar5 = 0x00000000;
480
- cpu->isar.id_isar6 = 0x00000000;
481
-}
482
-
483
-static void cortex_m33_initfn(Object *obj)
484
-{
485
- ARMCPU *cpu = ARM_CPU(obj);
486
-
487
- set_feature(&cpu->env, ARM_FEATURE_V8);
488
- set_feature(&cpu->env, ARM_FEATURE_M);
489
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
490
- set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
491
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
492
- cpu->midr = 0x410fd213; /* r0p3 */
493
- cpu->pmsav7_dregion = 16;
494
- cpu->sau_sregion = 8;
495
- cpu->isar.mvfr0 = 0x10110021;
496
- cpu->isar.mvfr1 = 0x11000011;
497
- cpu->isar.mvfr2 = 0x00000040;
498
- cpu->isar.id_pfr0 = 0x00000030;
499
- cpu->isar.id_pfr1 = 0x00000210;
500
- cpu->isar.id_dfr0 = 0x00200000;
501
- cpu->id_afr0 = 0x00000000;
502
- cpu->isar.id_mmfr0 = 0x00101F40;
503
- cpu->isar.id_mmfr1 = 0x00000000;
504
- cpu->isar.id_mmfr2 = 0x01000000;
505
- cpu->isar.id_mmfr3 = 0x00000000;
506
- cpu->isar.id_isar0 = 0x01101110;
507
- cpu->isar.id_isar1 = 0x02212000;
508
- cpu->isar.id_isar2 = 0x20232232;
509
- cpu->isar.id_isar3 = 0x01111131;
510
- cpu->isar.id_isar4 = 0x01310132;
511
- cpu->isar.id_isar5 = 0x00000000;
512
- cpu->isar.id_isar6 = 0x00000000;
513
- cpu->clidr = 0x00000000;
514
- cpu->ctr = 0x8000c000;
515
-}
516
-
517
-static void cortex_m55_initfn(Object *obj)
518
-{
519
- ARMCPU *cpu = ARM_CPU(obj);
520
-
521
- set_feature(&cpu->env, ARM_FEATURE_V8);
522
- set_feature(&cpu->env, ARM_FEATURE_V8_1M);
523
- set_feature(&cpu->env, ARM_FEATURE_M);
524
- set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
525
- set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
526
- set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
527
- cpu->midr = 0x410fd221; /* r0p1 */
528
- cpu->revidr = 0;
529
- cpu->pmsav7_dregion = 16;
530
- cpu->sau_sregion = 8;
531
- /* These are the MVFR* values for the FPU + full MVE configuration */
532
- cpu->isar.mvfr0 = 0x10110221;
533
- cpu->isar.mvfr1 = 0x12100211;
534
- cpu->isar.mvfr2 = 0x00000040;
535
- cpu->isar.id_pfr0 = 0x20000030;
536
- cpu->isar.id_pfr1 = 0x00000230;
537
- cpu->isar.id_dfr0 = 0x10200000;
538
- cpu->id_afr0 = 0x00000000;
539
- cpu->isar.id_mmfr0 = 0x00111040;
540
- cpu->isar.id_mmfr1 = 0x00000000;
541
- cpu->isar.id_mmfr2 = 0x01000000;
542
- cpu->isar.id_mmfr3 = 0x00000011;
543
- cpu->isar.id_isar0 = 0x01103110;
544
- cpu->isar.id_isar1 = 0x02212000;
545
- cpu->isar.id_isar2 = 0x20232232;
546
- cpu->isar.id_isar3 = 0x01111131;
547
- cpu->isar.id_isar4 = 0x01310132;
548
- cpu->isar.id_isar5 = 0x00000000;
549
- cpu->isar.id_isar6 = 0x00000000;
550
- cpu->clidr = 0x00000000; /* caches not implemented */
551
- cpu->ctr = 0x8303c003;
552
-}
553
-
554
static const ARMCPRegInfo cortexr5_cp_reginfo[] = {
555
/* Dummy the TCM region regs for the moment */
556
{ .name = "ATCM", .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 0,
557
@@ -XXX,XX +XXX,XX @@ static void pxa270c5_initfn(Object *obj)
558
cpu->reset_sctlr = 0x00000078;
559
}
560
561
-static const TCGCPUOps arm_v7m_tcg_ops = {
562
- .initialize = arm_translate_init,
563
- .synchronize_from_tb = arm_cpu_synchronize_from_tb,
564
- .debug_excp_handler = arm_debug_excp_handler,
565
- .restore_state_to_opc = arm_restore_state_to_opc,
566
-
567
-#ifdef CONFIG_USER_ONLY
568
- .record_sigsegv = arm_cpu_record_sigsegv,
569
- .record_sigbus = arm_cpu_record_sigbus,
570
-#else
571
- .tlb_fill = arm_cpu_tlb_fill,
572
- .cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt,
573
- .do_interrupt = arm_v7m_cpu_do_interrupt,
574
- .do_transaction_failed = arm_cpu_do_transaction_failed,
575
- .do_unaligned_access = arm_cpu_do_unaligned_access,
576
- .adjust_watchpoint_address = arm_adjust_watchpoint_address,
577
- .debug_check_watchpoint = arm_debug_check_watchpoint,
578
- .debug_check_breakpoint = arm_debug_check_breakpoint,
579
-#endif /* !CONFIG_USER_ONLY */
580
-};
581
-
582
-static void arm_v7m_class_init(ObjectClass *oc, void *data)
583
-{
584
- ARMCPUClass *acc = ARM_CPU_CLASS(oc);
585
- CPUClass *cc = CPU_CLASS(oc);
586
-
587
- acc->info = data;
588
- cc->tcg_ops = &arm_v7m_tcg_ops;
589
- cc->gdb_core_xml_file = "arm-m-profile.xml";
590
-}
591
-
592
#ifndef TARGET_AARCH64
33
/*
593
/*
34
* Number of registers in our device state structure. Don't change this without
594
* -cpu max: a CPU with as many features enabled as our emulation supports.
35
* incrementing the version_id in the vmstate.
595
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_tcg_cpus[] = {
36
diff --git a/include/hw/timer/npcm7xx_timer.h b/include/hw/timer/npcm7xx_timer.h
596
{ .name = "cortex-a8", .initfn = cortex_a8_initfn },
597
{ .name = "cortex-a9", .initfn = cortex_a9_initfn },
598
{ .name = "cortex-a15", .initfn = cortex_a15_initfn },
599
- { .name = "cortex-m0", .initfn = cortex_m0_initfn,
600
- .class_init = arm_v7m_class_init },
601
- { .name = "cortex-m3", .initfn = cortex_m3_initfn,
602
- .class_init = arm_v7m_class_init },
603
- { .name = "cortex-m4", .initfn = cortex_m4_initfn,
604
- .class_init = arm_v7m_class_init },
605
- { .name = "cortex-m7", .initfn = cortex_m7_initfn,
606
- .class_init = arm_v7m_class_init },
607
- { .name = "cortex-m33", .initfn = cortex_m33_initfn,
608
- .class_init = arm_v7m_class_init },
609
- { .name = "cortex-m55", .initfn = cortex_m55_initfn,
610
- .class_init = arm_v7m_class_init },
611
{ .name = "cortex-r5", .initfn = cortex_r5_initfn },
612
{ .name = "cortex-r5f", .initfn = cortex_r5f_initfn },
613
{ .name = "cortex-r52", .initfn = cortex_r52_initfn },
614
diff --git a/target/arm/meson.build b/target/arm/meson.build
37
index XXXXXXX..XXXXXXX 100644
615
index XXXXXXX..XXXXXXX 100644
38
--- a/include/hw/timer/npcm7xx_timer.h
616
--- a/target/arm/meson.build
39
+++ b/include/hw/timer/npcm7xx_timer.h
617
+++ b/target/arm/meson.build
40
@@ -XXX,XX +XXX,XX @@ struct NPCM7xxTimerCtrlState {
618
@@ -XXX,XX +XXX,XX @@ arm_system_ss.add(files(
41
619
'ptw.c',
42
uint32_t tisr;
620
))
43
621
44
+ Clock *clock;
622
+arm_user_ss = ss.source_set()
45
NPCM7xxTimer timer[NPCM7XX_TIMERS_PER_CTRL];
623
+
46
NPCM7xxWatchdogTimer watchdog_timer;
624
subdir('hvf')
47
};
625
48
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
626
if 'CONFIG_TCG' in config_all_accel
627
@@ -XXX,XX +XXX,XX @@ endif
628
629
target_arch += {'arm': arm_ss}
630
target_system_arch += {'arm': arm_system_ss}
631
+target_user_arch += {'arm': arm_user_ss}
632
diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build
49
index XXXXXXX..XXXXXXX 100644
633
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/arm/npcm7xx.c
634
--- a/target/arm/tcg/meson.build
51
+++ b/hw/arm/npcm7xx.c
635
+++ b/target/arm/tcg/meson.build
52
@@ -XXX,XX +XXX,XX @@
636
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
53
#include "hw/char/serial.h"
637
arm_system_ss.add(files(
54
#include "hw/loader.h"
638
'psci.c',
55
#include "hw/misc/unimp.h"
639
))
56
+#include "hw/qdev-clock.h"
640
+
57
#include "hw/qdev-properties.h"
641
+arm_system_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('cpu-v7m.c'))
58
#include "qapi/error.h"
642
+arm_user_ss.add(when: 'TARGET_AARCH64', if_false: files('cpu-v7m.c'))
59
#include "qemu/units.h"
60
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
61
int first_irq;
62
int j;
63
64
+ /* Connect the timer clock. */
65
+ qdev_connect_clock_in(DEVICE(&s->tim[i]), "clock", qdev_get_clock_out(
66
+ DEVICE(&s->clk), "timer-clock"));
67
+
68
sysbus_realize(sbd, &error_abort);
69
sysbus_mmio_map(sbd, 0, npcm7xx_tim_addr[i]);
70
71
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/hw/timer/npcm7xx_timer.c
74
+++ b/hw/timer/npcm7xx_timer.c
75
@@ -XXX,XX +XXX,XX @@
76
#include "qemu/osdep.h"
77
78
#include "hw/irq.h"
79
+#include "hw/qdev-clock.h"
80
#include "hw/qdev-properties.h"
81
-#include "hw/misc/npcm7xx_clk.h"
82
#include "hw/timer/npcm7xx_timer.h"
83
#include "migration/vmstate.h"
84
#include "qemu/bitops.h"
85
@@ -XXX,XX +XXX,XX @@ static uint32_t npcm7xx_tcsr_prescaler(uint32_t tcsr)
86
/* Convert a timer cycle count to a time interval in nanoseconds. */
87
static int64_t npcm7xx_timer_count_to_ns(NPCM7xxTimer *t, uint32_t count)
88
{
89
- int64_t ns = count;
90
+ int64_t ticks = count;
91
92
- ns *= NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ;
93
- ns *= npcm7xx_tcsr_prescaler(t->tcsr);
94
+ ticks *= npcm7xx_tcsr_prescaler(t->tcsr);
95
96
- return ns;
97
+ return clock_ticks_to_ns(t->ctrl->clock, ticks);
98
}
99
100
/* Convert a time interval in nanoseconds to a timer cycle count. */
101
static uint32_t npcm7xx_timer_ns_to_count(NPCM7xxTimer *t, int64_t ns)
102
{
103
- int64_t count;
104
-
105
- count = ns / (NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ);
106
- count /= npcm7xx_tcsr_prescaler(t->tcsr);
107
-
108
- return count;
109
+ return ns / clock_ticks_to_ns(t->ctrl->clock,
110
+ npcm7xx_tcsr_prescaler(t->tcsr));
111
}
112
113
static uint32_t npcm7xx_watchdog_timer_prescaler(const NPCM7xxWatchdogTimer *t)
114
@@ -XXX,XX +XXX,XX @@ static uint32_t npcm7xx_watchdog_timer_prescaler(const NPCM7xxWatchdogTimer *t)
115
static void npcm7xx_watchdog_timer_reset_cycles(NPCM7xxWatchdogTimer *t,
116
int64_t cycles)
117
{
118
- uint32_t prescaler = npcm7xx_watchdog_timer_prescaler(t);
119
- int64_t ns = (NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ) * cycles;
120
+ int64_t ticks = cycles * npcm7xx_watchdog_timer_prescaler(t);
121
+ int64_t ns = clock_ticks_to_ns(t->ctrl->clock, ticks);
122
123
/*
124
* The reset function always clears the current timer. The caller of the
125
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_watchdog_timer_reset_cycles(NPCM7xxWatchdogTimer *t,
126
*/
127
npcm7xx_timer_clear(&t->base_timer);
128
129
- ns *= prescaler;
130
t->base_timer.remaining_ns = ns;
131
}
132
133
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_hold_reset(Object *obj)
134
qemu_irq_lower(s->watchdog_timer.irq);
135
}
136
137
-static void npcm7xx_timer_realize(DeviceState *dev, Error **errp)
138
+static void npcm7xx_timer_init(Object *obj)
139
{
140
- NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(dev);
141
- SysBusDevice *sbd = &s->parent;
142
+ NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(obj);
143
+ DeviceState *dev = DEVICE(obj);
144
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
145
int i;
146
NPCM7xxWatchdogTimer *w;
147
148
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_realize(DeviceState *dev, Error **errp)
149
npcm7xx_watchdog_timer_expired, w);
150
sysbus_init_irq(sbd, &w->irq);
151
152
- memory_region_init_io(&s->iomem, OBJECT(s), &npcm7xx_timer_ops, s,
153
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_timer_ops, s,
154
TYPE_NPCM7XX_TIMER, 4 * KiB);
155
sysbus_init_mmio(sbd, &s->iomem);
156
qdev_init_gpio_out_named(dev, &w->reset_signal,
157
NPCM7XX_WATCHDOG_RESET_GPIO_OUT, 1);
158
+ s->clock = qdev_init_clock_in(dev, "clock", NULL, NULL);
159
}
160
161
static const VMStateDescription vmstate_npcm7xx_base_timer = {
162
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_npcm7xx_watchdog_timer = {
163
164
static const VMStateDescription vmstate_npcm7xx_timer_ctrl = {
165
.name = "npcm7xx-timer-ctrl",
166
- .version_id = 1,
167
- .minimum_version_id = 1,
168
+ .version_id = 2,
169
+ .minimum_version_id = 2,
170
.fields = (VMStateField[]) {
171
VMSTATE_UINT32(tisr, NPCM7xxTimerCtrlState),
172
+ VMSTATE_CLOCK(clock, NPCM7xxTimerCtrlState),
173
VMSTATE_STRUCT_ARRAY(timer, NPCM7xxTimerCtrlState,
174
NPCM7XX_TIMERS_PER_CTRL, 0, vmstate_npcm7xx_timer,
175
NPCM7xxTimer),
176
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_class_init(ObjectClass *klass, void *data)
177
QEMU_BUILD_BUG_ON(NPCM7XX_TIMER_REGS_END > NPCM7XX_TIMER_NR_REGS);
178
179
dc->desc = "NPCM7xx Timer Controller";
180
- dc->realize = npcm7xx_timer_realize;
181
dc->vmsd = &vmstate_npcm7xx_timer_ctrl;
182
rc->phases.enter = npcm7xx_timer_enter_reset;
183
rc->phases.hold = npcm7xx_timer_hold_reset;
184
@@ -XXX,XX +XXX,XX @@ static const TypeInfo npcm7xx_timer_info = {
185
.parent = TYPE_SYS_BUS_DEVICE,
186
.instance_size = sizeof(NPCM7xxTimerCtrlState),
187
.class_init = npcm7xx_timer_class_init,
188
+ .instance_init = npcm7xx_timer_init,
189
};
190
191
static void npcm7xx_timer_register_type(void)
192
--
643
--
193
2.20.1
644
2.34.1
194
195
diff view generated by jsdifflib
Deleted patch
1
From: Hao Wu <wuhaotsh@google.com>
2
1
3
A device shouldn't access its parent object which is QOM internal.
4
Instead it should use type cast for this purporse. This patch fixes this
5
issue for all NPCM7XX Devices.
6
7
Signed-off-by: Hao Wu <wuhaotsh@google.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20210108190945.949196-7-wuhaotsh@google.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
hw/arm/npcm7xx_boards.c | 2 +-
13
hw/mem/npcm7xx_mc.c | 2 +-
14
hw/misc/npcm7xx_clk.c | 2 +-
15
hw/misc/npcm7xx_gcr.c | 2 +-
16
hw/misc/npcm7xx_rng.c | 2 +-
17
hw/nvram/npcm7xx_otp.c | 2 +-
18
hw/ssi/npcm7xx_fiu.c | 2 +-
19
7 files changed, 7 insertions(+), 7 deletions(-)
20
21
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/npcm7xx_boards.c
24
+++ b/hw/arm/npcm7xx_boards.c
25
@@ -XXX,XX +XXX,XX @@ static NPCM7xxState *npcm7xx_create_soc(MachineState *machine,
26
uint32_t hw_straps)
27
{
28
NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_GET_CLASS(machine);
29
- MachineClass *mc = &nmc->parent;
30
+ MachineClass *mc = MACHINE_CLASS(nmc);
31
Object *obj;
32
33
if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
34
diff --git a/hw/mem/npcm7xx_mc.c b/hw/mem/npcm7xx_mc.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/mem/npcm7xx_mc.c
37
+++ b/hw/mem/npcm7xx_mc.c
38
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_mc_realize(DeviceState *dev, Error **errp)
39
40
memory_region_init_io(&s->mmio, OBJECT(s), &npcm7xx_mc_ops, s, "regs",
41
NPCM7XX_MC_REGS_SIZE);
42
- sysbus_init_mmio(&s->parent, &s->mmio);
43
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio);
44
}
45
46
static void npcm7xx_mc_class_init(ObjectClass *klass, void *data)
47
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/misc/npcm7xx_clk.c
50
+++ b/hw/misc/npcm7xx_clk.c
51
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_init(Object *obj)
52
53
memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s,
54
TYPE_NPCM7XX_CLK, 4 * KiB);
55
- sysbus_init_mmio(&s->parent, &s->iomem);
56
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
57
}
58
59
static int npcm7xx_clk_post_load(void *opaque, int version_id)
60
diff --git a/hw/misc/npcm7xx_gcr.c b/hw/misc/npcm7xx_gcr.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/hw/misc/npcm7xx_gcr.c
63
+++ b/hw/misc/npcm7xx_gcr.c
64
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_gcr_init(Object *obj)
65
66
memory_region_init_io(&s->iomem, obj, &npcm7xx_gcr_ops, s,
67
TYPE_NPCM7XX_GCR, 4 * KiB);
68
- sysbus_init_mmio(&s->parent, &s->iomem);
69
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
70
}
71
72
static const VMStateDescription vmstate_npcm7xx_gcr = {
73
diff --git a/hw/misc/npcm7xx_rng.c b/hw/misc/npcm7xx_rng.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/misc/npcm7xx_rng.c
76
+++ b/hw/misc/npcm7xx_rng.c
77
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_rng_init(Object *obj)
78
79
memory_region_init_io(&s->iomem, obj, &npcm7xx_rng_ops, s, "regs",
80
NPCM7XX_RNG_REGS_SIZE);
81
- sysbus_init_mmio(&s->parent, &s->iomem);
82
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
83
}
84
85
static const VMStateDescription vmstate_npcm7xx_rng = {
86
diff --git a/hw/nvram/npcm7xx_otp.c b/hw/nvram/npcm7xx_otp.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/hw/nvram/npcm7xx_otp.c
89
+++ b/hw/nvram/npcm7xx_otp.c
90
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_otp_realize(DeviceState *dev, Error **errp)
91
{
92
NPCM7xxOTPClass *oc = NPCM7XX_OTP_GET_CLASS(dev);
93
NPCM7xxOTPState *s = NPCM7XX_OTP(dev);
94
- SysBusDevice *sbd = &s->parent;
95
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
96
97
memset(s->array, 0, sizeof(s->array));
98
99
diff --git a/hw/ssi/npcm7xx_fiu.c b/hw/ssi/npcm7xx_fiu.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/hw/ssi/npcm7xx_fiu.c
102
+++ b/hw/ssi/npcm7xx_fiu.c
103
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_fiu_hold_reset(Object *obj)
104
static void npcm7xx_fiu_realize(DeviceState *dev, Error **errp)
105
{
106
NPCM7xxFIUState *s = NPCM7XX_FIU(dev);
107
- SysBusDevice *sbd = &s->parent;
108
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
109
int i;
110
111
if (s->cs_count <= 0) {
112
--
113
2.20.1
114
115
diff view generated by jsdifflib