1
Arm queue; not huge but I figured I might as well send it out since
1
Here's another arm pullreq; nothing too exciting in here I think.
2
I've been doing code review today and there's no queue of unprocessed
3
pullreqs...
4
2
5
thanks
3
thanks
6
-- PMM
4
-- PMM
7
5
8
The following changes since commit b3f846c59d8405bb87c551187721fc92ff2f1b92:
6
The following changes since commit 5fee33d97a7f2e95716417bd164f2f5264acd976:
9
7
10
Merge remote-tracking branch 'remotes/huth-gitlab/tags/pull-request-2021-01-11v2' into staging (2021-01-11 15:15:35 +0000)
8
Merge tag 'samuel-thibault' of https://people.debian.org/~sthibault/qemu into staging (2024-04-29 14:34:25 -0700)
11
9
12
are available in the Git repository at:
10
are available in the Git repository at:
13
11
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210112
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20240430
15
13
16
for you to fetch changes up to 19d131395ccaf503db21dadd8257e6dc9fc1d7de:
14
for you to fetch changes up to a0c325c4b05cf7815739d6a84e567b95c8c5be7e:
17
15
18
ui/cocoa: Fix openFile: deprecation on Big Sur (2021-01-12 11:38:37 +0000)
16
tests/qtest : Add testcase for DM163 (2024-04-30 16:05:08 +0100)
19
17
20
----------------------------------------------------------------
18
----------------------------------------------------------------
21
target-arm queue:
19
target-arm queue:
22
* arm: Support emulation of ARMv8.4-TTST extension
20
* hw/core/clock: allow clock_propagate on child clocks
23
* arm: Update cpu.h ID register field definitions
21
* hvf: arm: Remove unused PL1_WRITE_MASK define
24
* arm: Fix breakage of XScale instruction emulation
22
* target/arm: Restrict translation disabled alignment check to VMSA
25
* hw/net/lan9118: Fix RX Status FIFO PEEK value
23
* docs/system/arm/emulation.rst: Add missing implemented features
26
* npcm7xx: Add ADC and PWM emulation
24
* target/arm: Enable FEAT_CSV2_3, FEAT_ETS2, FEAT_Spec_FPACC for 'max'
27
* ui/cocoa: Make "open docs" help menu entry work again when binary
25
* tests/avocado: update sunxi kernel from armbian to 6.6.16
28
is run from the build tree
26
* target/arm: Make new CPUs default to 1GHz generic timer
29
* ui/cocoa: Fix openFile: deprecation on Big Sur
27
* hw/dmax/xlnx_dpdma: fix handling of address_extension descriptor fields
30
* docs: Add qemu-storage-daemon(1) manpage to meson.build
28
* hw/char/stm32l4x5_usart: Fix memory corruption by adding correct class_size
31
* docs: Build and install all the docs in a single manual
29
* hw/arm/npcm7xx: Store derivative OTP fuse key in little endian
30
* hw/arm: Add DM163 display to B-L475E-IOT01A board
32
31
33
----------------------------------------------------------------
32
----------------------------------------------------------------
34
Hao Wu (6):
33
Alexandra Diupina (1):
35
hw/misc: Add clock converter in NPCM7XX CLK module
34
hw/dmax/xlnx_dpdma: fix handling of address_extension descriptor fields
36
hw/timer: Refactor NPCM7XX Timer to use CLK clock
37
hw/adc: Add an ADC module for NPCM7XX
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
35
42
Leif Lindholm (6):
36
Inès Varhol (5):
43
target/arm: fix typo in cpu.h ID_AA64PFR1 field name
37
hw/display : Add device DM163
44
target/arm: make ARMCPU.clidr 64-bit
38
hw/arm : Pass STM32L4x5 SYSCFG gpios to STM32L4x5 SoC
45
target/arm: make ARMCPU.ctr 64-bit
39
hw/arm : Create Bl475eMachineState
46
target/arm: add descriptions of CLIDR_EL1, CCSIDR_EL1, CTR_EL0 to cpu.h
40
hw/arm : Connect DM163 to B-L475E-IOT01A
47
target/arm: add aarch64 ID register fields to cpu.h
41
tests/qtest : Add testcase for DM163
48
target/arm: add aarch32 ID register fields to cpu.h
49
42
50
Peter Maydell (5):
43
Peter Maydell (10):
51
docs: Add qemu-storage-daemon(1) manpage to meson.build
44
docs/system/arm/emulation.rst: Add missing implemented features
52
docs: Build and install all the docs in a single manual
45
target/arm: Enable FEAT_CSV2_3 for -cpu max
53
target/arm: Don't decode insns in the XScale/iWMMXt space as cp insns
46
target/arm: Enable FEAT_ETS2 for -cpu max
54
hw/net/lan9118: Fix RX Status FIFO PEEK value
47
target/arm: Implement ID_AA64MMFR3_EL1
55
hw/net/lan9118: Add symbolic constants for register offsets
48
target/arm: Enable FEAT_Spec_FPACC for -cpu max
49
tests/avocado: update sunxi kernel from armbian to 6.6.16
50
target/arm: Refactor default generic timer frequency handling
51
hw/arm/sbsa-ref: Force CPU generic timer to 62.5MHz
52
hw/watchdog/sbsa_gwdt: Make watchdog timer frequency a QOM property
53
target/arm: Default to 1GHz cntfrq for 'max' and new CPUs
56
54
57
Roman Bolshakov (2):
55
Philippe Mathieu-Daudé (1):
58
ui/cocoa: Update path to docs in build tree
56
hw/arm/npcm7xx: Store derivative OTP fuse key in little endian
59
ui/cocoa: Fix openFile: deprecation on Big Sur
60
57
61
Rémi Denis-Courmont (2):
58
Raphael Poggi (1):
62
target/arm: ARMv8.4-TTST extension
59
hw/core/clock: allow clock_propagate on child clocks
63
target/arm: enable Small Translation tables in max CPU
64
60
65
docs/conf.py | 46 ++-
61
Richard Henderson (1):
66
docs/devel/conf.py | 15 -
62
target/arm: Restrict translation disabled alignment check to VMSA
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
63
64
Thomas Huth (1):
65
hw/char/stm32l4x5_usart: Fix memory corruption by adding correct class_size
66
67
Zenghui Yu (1):
68
hvf: arm: Remove PL1_WRITE_MASK
69
70
docs/system/arm/b-l475e-iot01a.rst | 3 +-
71
docs/system/arm/emulation.rst | 42 ++++-
72
include/hw/display/dm163.h | 59 ++++++
73
include/hw/watchdog/sbsa_gwdt.h | 3 +-
74
target/arm/cpu.h | 28 +++
75
target/arm/internals.h | 15 +-
76
hw/arm/b-l475e-iot01a.c | 105 +++++++++--
77
hw/arm/npcm7xx.c | 3 +-
78
hw/arm/sbsa-ref.c | 16 ++
79
hw/arm/stm32l4x5_soc.c | 6 +-
80
hw/char/stm32l4x5_usart.c | 1 +
81
hw/core/clock.c | 1 -
82
hw/core/machine.c | 4 +-
83
hw/display/dm163.c | 349 ++++++++++++++++++++++++++++++++++++
84
hw/dma/xlnx_dpdma.c | 20 +--
85
hw/watchdog/sbsa_gwdt.c | 15 +-
86
target/arm/cpu.c | 42 +++--
87
target/arm/cpu64.c | 2 +
88
target/arm/helper.c | 22 +--
89
target/arm/hvf/hvf.c | 3 +-
90
target/arm/kvm.c | 2 +
91
target/arm/tcg/cpu32.c | 6 +-
92
target/arm/tcg/cpu64.c | 28 ++-
93
target/arm/tcg/hflags.c | 12 +-
94
tests/qtest/dm163-test.c | 194 ++++++++++++++++++++
95
tests/qtest/stm32l4x5_gpio-test.c | 13 +-
96
tests/qtest/stm32l4x5_syscfg-test.c | 17 +-
97
hw/arm/Kconfig | 1 +
98
hw/display/Kconfig | 3 +
99
hw/display/meson.build | 1 +
100
hw/display/trace-events | 14 ++
101
tests/avocado/boot_linux_console.py | 70 ++++----
102
tests/avocado/replay_kernel.py | 8 +-
103
tests/qtest/meson.build | 2 +
104
34 files changed, 987 insertions(+), 123 deletions(-)
105
create mode 100644 include/hw/display/dm163.h
106
create mode 100644 hw/display/dm163.c
107
create mode 100644 tests/qtest/dm163-test.c
108
diff view generated by jsdifflib
1
From: Leif Lindholm <leif@nuviainc.com>
1
From: Raphael Poggi <raphael.poggi@lynxleap.co.uk>
2
2
3
Add entries present in ARM DDI 0487F.c (August 2020).
3
clock_propagate() has an assert that clk->source is NULL, i.e. that
4
you are calling it on a clock which has no source clock. This made
5
sense in the original design where the only way for a clock's
6
frequency to change if it had a source clock was when that source
7
clock changed. However, we subsequently added multiplier/divider
8
support, but didn't look at what that meant for propagation.
4
9
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
10
If a clock-management device changes the multiplier or divider value
11
on a clock, it needs to propagate that change down to child clocks,
12
even if the clock has a source clock set. So the assertion is now
13
incorrect.
14
15
Remove the assertion.
16
17
Signed-off-by: Raphael Poggi <raphael.poggi@lynxleap.co.uk>
18
Message-id: 20240419162951.23558-1-raphael.poggi@lynxleap.co.uk
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
20
[PMM: Rewrote the commit message]
8
Message-id: 20210108185154.8108-7-leif@nuviainc.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
22
---
11
target/arm/cpu.h | 28 ++++++++++++++++++++++++++++
23
hw/core/clock.c | 1 -
12
1 file changed, 28 insertions(+)
24
1 file changed, 1 deletion(-)
13
25
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
26
diff --git a/hw/core/clock.c b/hw/core/clock.c
15
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
28
--- a/hw/core/clock.c
17
+++ b/target/arm/cpu.h
29
+++ b/hw/core/clock.c
18
@@ -XXX,XX +XXX,XX @@ FIELD(ID_ISAR6, DP, 4, 4)
30
@@ -XXX,XX +XXX,XX @@ static void clock_propagate_period(Clock *clk, bool call_callbacks)
19
FIELD(ID_ISAR6, FHM, 8, 4)
31
20
FIELD(ID_ISAR6, SB, 12, 4)
32
void clock_propagate(Clock *clk)
21
FIELD(ID_ISAR6, SPECRES, 16, 4)
33
{
22
+FIELD(ID_ISAR6, BF16, 20, 4)
34
- assert(clk->source == NULL);
23
+FIELD(ID_ISAR6, I8MM, 24, 4)
35
trace_clock_propagate(CLOCK_PATH(clk));
24
36
clock_propagate_period(clk, true);
25
FIELD(ID_MMFR0, VMSA, 0, 4)
37
}
26
FIELD(ID_MMFR0, PMSA, 4, 4)
27
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR0, AUXREG, 20, 4)
28
FIELD(ID_MMFR0, FCSE, 24, 4)
29
FIELD(ID_MMFR0, INNERSHR, 28, 4)
30
31
+FIELD(ID_MMFR1, L1HVDVA, 0, 4)
32
+FIELD(ID_MMFR1, L1UNIVA, 4, 4)
33
+FIELD(ID_MMFR1, L1HVDSW, 8, 4)
34
+FIELD(ID_MMFR1, L1UNISW, 12, 4)
35
+FIELD(ID_MMFR1, L1HVD, 16, 4)
36
+FIELD(ID_MMFR1, L1UNI, 20, 4)
37
+FIELD(ID_MMFR1, L1TSTCLN, 24, 4)
38
+FIELD(ID_MMFR1, BPRED, 28, 4)
39
+
40
+FIELD(ID_MMFR2, L1HVDFG, 0, 4)
41
+FIELD(ID_MMFR2, L1HVDBG, 4, 4)
42
+FIELD(ID_MMFR2, L1HVDRNG, 8, 4)
43
+FIELD(ID_MMFR2, HVDTLB, 12, 4)
44
+FIELD(ID_MMFR2, UNITLB, 16, 4)
45
+FIELD(ID_MMFR2, MEMBARR, 20, 4)
46
+FIELD(ID_MMFR2, WFISTALL, 24, 4)
47
+FIELD(ID_MMFR2, HWACCFLG, 28, 4)
48
+
49
FIELD(ID_MMFR3, CMAINTVA, 0, 4)
50
FIELD(ID_MMFR3, CMAINTSW, 4, 4)
51
FIELD(ID_MMFR3, BPMAINT, 8, 4)
52
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR4, LSM, 20, 4)
53
FIELD(ID_MMFR4, CCIDX, 24, 4)
54
FIELD(ID_MMFR4, EVT, 28, 4)
55
56
+FIELD(ID_MMFR5, ETS, 0, 4)
57
+
58
FIELD(ID_PFR0, STATE0, 0, 4)
59
FIELD(ID_PFR0, STATE1, 4, 4)
60
FIELD(ID_PFR0, STATE2, 8, 4)
61
@@ -XXX,XX +XXX,XX @@ FIELD(ID_PFR1, SEC_FRAC, 20, 4)
62
FIELD(ID_PFR1, VIRT_FRAC, 24, 4)
63
FIELD(ID_PFR1, GIC, 28, 4)
64
65
+FIELD(ID_PFR2, CSV3, 0, 4)
66
+FIELD(ID_PFR2, SSBS, 4, 4)
67
+FIELD(ID_PFR2, RAS_FRAC, 8, 4)
68
+
69
FIELD(ID_AA64ISAR0, AES, 4, 4)
70
FIELD(ID_AA64ISAR0, SHA1, 8, 4)
71
FIELD(ID_AA64ISAR0, SHA2, 12, 4)
72
@@ -XXX,XX +XXX,XX @@ FIELD(ID_DFR0, MPROFDBG, 20, 4)
73
FIELD(ID_DFR0, PERFMON, 24, 4)
74
FIELD(ID_DFR0, TRACEFILT, 28, 4)
75
76
+FIELD(ID_DFR1, MTPMU, 0, 4)
77
+
78
FIELD(DBGDIDR, SE_IMP, 12, 1)
79
FIELD(DBGDIDR, NSUHD_IMP, 14, 1)
80
FIELD(DBGDIDR, VERSION, 16, 4)
81
--
38
--
82
2.20.1
39
2.34.1
83
84
diff view generated by jsdifflib
1
From: Roman Bolshakov <r.bolshakov@yadro.com>
1
From: Zenghui Yu <zenghui.yu@linux.dev>
2
2
3
QEMU documentation can't be opened if QEMU is run from build tree
3
As it had never been used since the first commit a1477da3ddeb ("hvf: Add
4
because executables are placed in the top of build tree after conversion
4
Apple Silicon support").
5
to meson.
6
5
7
Signed-off-by: Roman Bolshakov <r.bolshakov@yadro.com>
6
Signed-off-by: Zenghui Yu <zenghui.yu@linux.dev>
8
Reported-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20240422092715.71973-1-zenghui.yu@linux.dev
9
Message-id: 20210108213815.64678-1-r.bolshakov@yadro.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
ui/cocoa.m | 2 +-
11
target/arm/hvf/hvf.c | 1 -
14
1 file changed, 1 insertion(+), 1 deletion(-)
12
1 file changed, 1 deletion(-)
15
13
16
diff --git a/ui/cocoa.m b/ui/cocoa.m
14
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
17
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
18
--- a/ui/cocoa.m
16
--- a/target/arm/hvf/hvf.c
19
+++ b/ui/cocoa.m
17
+++ b/target/arm/hvf/hvf.c
20
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
18
@@ -XXX,XX +XXX,XX @@ void hvf_arm_init_debug(void)
21
- (void) openDocumentation: (NSString *) filename
19
22
{
20
#define HVF_SYSREG(crn, crm, op0, op1, op2) \
23
/* Where to look for local files */
21
ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP, crn, crm, op0, op1, op2)
24
- NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"../docs/"};
22
-#define PL1_WRITE_MASK 0x4
25
+ NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"docs/"};
23
26
NSString *full_file_path;
24
#define SYSREG_OP0_SHIFT 20
27
25
#define SYSREG_OP0_MASK 0x3
28
/* iterate thru the possible paths until the file is found */
29
--
26
--
30
2.20.1
27
2.34.1
31
32
diff view generated by jsdifflib
1
In commit cd8be50e58f63413c0 we converted the A32 coprocessor
1
From: Richard Henderson <richard.henderson@linaro.org>
2
insns to decodetree. This accidentally broke XScale/iWMMXt insns,
3
because it moved the handling of "cp insns which are handled
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
2
8
Update valid_cp() so that it knows that on XScale cp 0 and 1
3
For cpus using PMSA, when the MPU is disabled, the default memory
9
are not standard coprocessor instructions; this will cause
4
type is Normal, Non-cachable. This means that it should not
10
the decodetree trans_ functions to ignore them, so that
5
have alignment restrictions enforced.
11
execution will correctly get through to the legacy decode again.
12
6
13
Cc: qemu-stable@nongnu.org
7
Cc: qemu-stable@nongnu.org
14
Reported-by: Guenter Roeck <linux@roeck-us.net>
8
Fixes: 59754f85ed3 ("target/arm: Do memory type alignment check when translation disabled")
9
Reported-by: Clément Chigot <chigot@adacore.com>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
Tested-by: Clément Chigot <chigot@adacore.com>
13
Message-id: 20240422170722.117409-1-richard.henderson@linaro.org
14
[PMM: trivial comment, commit message tweaks]
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Tested-by: Guenter Roeck <linux@roeck-us.net>
18
Message-id: 20210108195157.32067-1-peter.maydell@linaro.org
19
---
16
---
20
target/arm/translate.c | 7 +++++++
17
target/arm/tcg/hflags.c | 12 ++++++++++--
21
1 file changed, 7 insertions(+)
18
1 file changed, 10 insertions(+), 2 deletions(-)
22
19
23
diff --git a/target/arm/translate.c b/target/arm/translate.c
20
diff --git a/target/arm/tcg/hflags.c b/target/arm/tcg/hflags.c
24
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/translate.c
22
--- a/target/arm/tcg/hflags.c
26
+++ b/target/arm/translate.c
23
+++ b/target/arm/tcg/hflags.c
27
@@ -XXX,XX +XXX,XX @@ static bool valid_cp(DisasContext *s, int cp)
24
@@ -XXX,XX +XXX,XX @@ static bool aprofile_require_alignment(CPUARMState *env, int el, uint64_t sctlr)
28
* only cp14 and cp15 are valid, and other values aren't considered
25
}
29
* to be in the coprocessor-instruction space at all. v8M still
26
30
* permits coprocessors 0..7.
27
/*
31
+ * For XScale, we must not decode the XScale cp0, cp1 space as
28
- * If translation is disabled, then the default memory type is
32
+ * a standard coprocessor insn, because we want to fall through to
29
- * Device(-nGnRnE) instead of Normal, which requires that alignment
33
+ * the legacy disas_xscale_insn() decoder after decodetree is done.
30
+ * With PMSA, when the MPU is disabled, all memory types in the
34
*/
31
+ * default map are Normal, so don't need aligment enforcing.
35
+ if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cp == 0 || cp == 1)) {
32
+ */
33
+ if (arm_feature(env, ARM_FEATURE_PMSA)) {
36
+ return false;
34
+ return false;
37
+ }
35
+ }
38
+
36
+
39
if (arm_dc_feature(s, ARM_FEATURE_V8) &&
37
+ /*
40
!arm_dc_feature(s, ARM_FEATURE_M)) {
38
+ * With VMSA, if translation is disabled, then the default memory type
41
return cp >= 14;
39
+ * is Device(-nGnRnE) instead of Normal, which requires that alignment
40
* be enforced. Since this affects all ram, it is most efficient
41
* to handle this during translation.
42
*/
42
--
43
--
43
2.20.1
44
2.34.1
44
45
45
46
diff view generated by jsdifflib
1
In commit 1982e1602d15 we added a new qemu-storage-daemon(1) manpage.
1
As of version DDI0487K.a of the Arm ARM, some architectural features
2
At the moment new manpages have to be listed both in the conf.py for
2
which previously didn't have official names have been named. Add
3
Sphinx and also in docs/meson.build for Meson. We forgot the second
3
these to the list of features which QEMU's TCG emulation supports.
4
of those -- correct the omission.
4
Mostly these are features which we thought of as part of baseline 8.0
5
support. For SVE and SVE2, the names have been brought into line
6
with the FEAT_* naming convention of other extensions, and some
7
sub-components split into separate FEAT_ items. In a few cases (eg
8
FEAT_CCIDX, FEAT_DPB2) the omission from our list was just an oversight.
5
9
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Message-id: 20240418152004.2106516-2-peter.maydell@linaro.org
9
Message-id: 20210108161416.21129-2-peter.maydell@linaro.org
10
---
13
---
11
docs/meson.build | 1 +
14
docs/system/arm/emulation.rst | 38 +++++++++++++++++++++++++++++++++--
12
1 file changed, 1 insertion(+)
15
1 file changed, 36 insertions(+), 2 deletions(-)
13
16
14
diff --git a/docs/meson.build b/docs/meson.build
17
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/docs/meson.build
19
--- a/docs/system/arm/emulation.rst
17
+++ b/docs/meson.build
20
+++ b/docs/system/arm/emulation.rst
18
@@ -XXX,XX +XXX,XX @@ if build_docs
21
@@ -XXX,XX +XXX,XX @@ Armv8 versions of the A-profile architecture. It also has support for
19
'qemu-img.1': (have_tools ? 'man1' : ''),
22
the following architecture extensions:
20
'qemu-nbd.8': (have_tools ? 'man8' : ''),
23
21
'qemu-pr-helper.8': (have_tools ? 'man8' : ''),
24
- FEAT_AA32BF16 (AArch32 BFloat16 instructions)
22
+ 'qemu-storage-daemon.1': (have_tools ? 'man1' : ''),
25
+- FEAT_AA32EL0 (Support for AArch32 at EL0)
23
'qemu-trace-stap.1': (config_host.has_key('CONFIG_TRACE_SYSTEMTAP') ? 'man1' : ''),
26
+- FEAT_AA32EL1 (Support for AArch32 at EL1)
24
'virtfs-proxy-helper.1': (have_virtfs_proxy_helper ? 'man1' : ''),
27
+- FEAT_AA32EL2 (Support for AArch32 at EL2)
25
'virtiofsd.1': (have_virtiofsd ? 'man1' : ''),
28
+- FEAT_AA32EL3 (Support for AArch32 at EL3)
29
- FEAT_AA32HPD (AArch32 hierarchical permission disables)
30
- FEAT_AA32I8MM (AArch32 Int8 matrix multiplication instructions)
31
+- FEAT_AA64EL0 (Support for AArch64 at EL0)
32
+- FEAT_AA64EL1 (Support for AArch64 at EL1)
33
+- FEAT_AA64EL2 (Support for AArch64 at EL2)
34
+- FEAT_AA64EL3 (Support for AArch64 at EL3)
35
+- FEAT_AdvSIMD (Advanced SIMD Extension)
36
- FEAT_AES (AESD and AESE instructions)
37
+- FEAT_Armv9_Crypto (Armv9 Cryptographic Extension)
38
+- FEAT_ASID16 (16 bit ASID)
39
- FEAT_BBM at level 2 (Translation table break-before-make levels)
40
- FEAT_BF16 (AArch64 BFloat16 instructions)
41
- FEAT_BTI (Branch Target Identification)
42
+- FEAT_CCIDX (Extended cache index)
43
- FEAT_CRC32 (CRC32 instructions)
44
+- FEAT_Crypto (Cryptographic Extension)
45
- FEAT_CSV2 (Cache speculation variant 2)
46
- FEAT_CSV2_1p1 (Cache speculation variant 2, version 1.1)
47
- FEAT_CSV2_1p2 (Cache speculation variant 2, version 1.2)
48
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
49
- FEAT_DGH (Data gathering hint)
50
- FEAT_DIT (Data Independent Timing instructions)
51
- FEAT_DPB (DC CVAP instruction)
52
+- FEAT_DPB2 (DC CVADP instruction)
53
+- FEAT_Debugv8p1 (Debug with VHE)
54
- FEAT_Debugv8p2 (Debug changes for v8.2)
55
- FEAT_Debugv8p4 (Debug changes for v8.4)
56
- FEAT_DotProd (Advanced SIMD dot product instructions)
57
- FEAT_DoubleFault (Double Fault Extension)
58
- FEAT_E0PD (Preventing EL0 access to halves of address maps)
59
- FEAT_ECV (Enhanced Counter Virtualization)
60
+- FEAT_EL0 (Support for execution at EL0)
61
+- FEAT_EL1 (Support for execution at EL1)
62
+- FEAT_EL2 (Support for execution at EL2)
63
+- FEAT_EL3 (Support for execution at EL3)
64
- FEAT_EPAC (Enhanced pointer authentication)
65
- FEAT_ETS (Enhanced Translation Synchronization)
66
- FEAT_EVT (Enhanced Virtualization Traps)
67
+- FEAT_F32MM (Single-precision Matrix Multiplication)
68
+- FEAT_F64MM (Double-precision Matrix Multiplication)
69
- FEAT_FCMA (Floating-point complex number instructions)
70
- FEAT_FGT (Fine-Grained Traps)
71
- FEAT_FHM (Floating-point half-precision multiplication instructions)
72
+- FEAT_FP (Floating Point extensions)
73
- FEAT_FP16 (Half-precision floating-point data processing)
74
- FEAT_FPAC (Faulting on AUT* instructions)
75
- FEAT_FPACCOMBINE (Faulting on combined pointer authentication instructions)
76
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
77
- FEAT_LSE (Large System Extensions)
78
- FEAT_LSE2 (Large System Extensions v2)
79
- FEAT_LVA (Large Virtual Address space)
80
+- FEAT_MixedEnd (Mixed-endian support)
81
+- FEAT_MixdEndEL0 (Mixed-endian support at EL0)
82
- FEAT_MOPS (Standardization of memory operations)
83
- FEAT_MTE (Memory Tagging Extension)
84
- FEAT_MTE2 (Memory Tagging Extension)
85
- FEAT_MTE3 (MTE Asymmetric Fault Handling)
86
+- FEAT_MTE_ASYM_FAULT (Memory tagging asymmetric faults)
87
- FEAT_NMI (Non-maskable Interrupt)
88
- FEAT_NV (Nested Virtualization)
89
- FEAT_NV2 (Enhanced nested virtualization support)
90
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
91
- FEAT_PAuth (Pointer authentication)
92
- FEAT_PAuth2 (Enhancements to pointer authentication)
93
- FEAT_PMULL (PMULL, PMULL2 instructions)
94
+- FEAT_PMUv3 (PMU extension version 3)
95
- FEAT_PMUv3p1 (PMU Extensions v3.1)
96
- FEAT_PMUv3p4 (PMU Extensions v3.4)
97
- FEAT_PMUv3p5 (PMU Extensions v3.5)
98
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
99
- FEAT_SME_FA64 (Full A64 instruction set in Streaming SVE mode)
100
- FEAT_SME_F64F64 (Double-precision floating-point outer product instructions)
101
- FEAT_SME_I16I64 (16-bit to 64-bit integer widening outer product instructions)
102
+- FEAT_SVE (Scalable Vector Extension)
103
+- FEAT_SVE_AES (Scalable Vector AES instructions)
104
+- FEAT_SVE_BitPerm (Scalable Vector Bit Permutes instructions)
105
+- FEAT_SVE_PMULL128 (Scalable Vector PMULL instructions)
106
+- FEAT_SVE_SHA3 (Scalable Vector SHA3 instructions)
107
+- FEAT_SVE_SM4 (Scalable Vector SM4 instructions)
108
+- FEAT_SVE2 (Scalable Vector Extension version 2)
109
- FEAT_SPECRES (Speculation restriction instructions)
110
- FEAT_SSBS (Speculative Store Bypass Safe)
111
+- FEAT_TGran16K (Support for 16KB memory translation granule size at stage 1)
112
+- FEAT_TGran4K (Support for 4KB memory translation granule size at stage 1)
113
+- FEAT_TGran64K (Support for 64KB memory translation granule size at stage 1)
114
- FEAT_TIDCP1 (EL0 use of IMPLEMENTATION DEFINED functionality)
115
- FEAT_TLBIOS (TLB invalidate instructions in Outer Shareable domain)
116
- FEAT_TLBIRANGE (TLB invalidate range instructions)
117
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
118
- FEAT_VHE (Virtualization Host Extensions)
119
- FEAT_VMID16 (16-bit VMID)
120
- FEAT_XNX (Translation table stage 2 Unprivileged Execute-never)
121
-- SVE (The Scalable Vector Extension)
122
-- SVE2 (The Scalable Vector Extension v2)
123
124
For information on the specifics of these extensions, please refer
125
to the `Armv8-A Arm Architecture Reference Manual
26
--
126
--
27
2.20.1
127
2.34.1
28
29
diff view generated by jsdifflib
1
From: Leif Lindholm <leif@nuviainc.com>
1
FEAT_CSV2_3 adds a mechanism to identify if hardware cannot disclose
2
information about whether branch targets and branch history trained
3
in one hardware described context can control speculative execution
4
in a different hardware context.
2
5
3
SBSS -> SSBS
6
There is no branch prediction in TCG, so we don't need to do anything
7
to be compliant with this. Upadte the '-cpu max' ID registers to
8
advertise the feature.
4
9
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
9
Message-id: 20210108185154.8108-2-leif@nuviainc.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
13
Message-id: 20240418152004.2106516-3-peter.maydell@linaro.org
11
---
14
---
12
target/arm/cpu.h | 2 +-
15
docs/system/arm/emulation.rst | 1 +
13
1 file changed, 1 insertion(+), 1 deletion(-)
16
target/arm/tcg/cpu64.c | 4 ++--
17
2 files changed, 3 insertions(+), 2 deletions(-)
14
18
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
19
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
16
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/cpu.h
21
--- a/docs/system/arm/emulation.rst
18
+++ b/target/arm/cpu.h
22
+++ b/docs/system/arm/emulation.rst
19
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64PFR0, RAS, 28, 4)
23
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
20
FIELD(ID_AA64PFR0, SVE, 32, 4)
24
- FEAT_CSV2_1p1 (Cache speculation variant 2, version 1.1)
21
25
- FEAT_CSV2_1p2 (Cache speculation variant 2, version 1.2)
22
FIELD(ID_AA64PFR1, BT, 0, 4)
26
- FEAT_CSV2_2 (Cache speculation variant 2, version 2)
23
-FIELD(ID_AA64PFR1, SBSS, 4, 4)
27
+- FEAT_CSV2_3 (Cache speculation variant 2, version 3)
24
+FIELD(ID_AA64PFR1, SSBS, 4, 4)
28
- FEAT_CSV3 (Cache speculation variant 3)
25
FIELD(ID_AA64PFR1, MTE, 8, 4)
29
- FEAT_DGH (Data gathering hint)
26
FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4)
30
- FEAT_DIT (Data Independent Timing instructions)
31
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/tcg/cpu64.c
34
+++ b/target/arm/tcg/cpu64.c
35
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
36
t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1);
37
t = FIELD_DP64(t, ID_AA64PFR0, SEL2, 1); /* FEAT_SEL2 */
38
t = FIELD_DP64(t, ID_AA64PFR0, DIT, 1); /* FEAT_DIT */
39
- t = FIELD_DP64(t, ID_AA64PFR0, CSV2, 2); /* FEAT_CSV2_2 */
40
+ t = FIELD_DP64(t, ID_AA64PFR0, CSV2, 3); /* FEAT_CSV2_3 */
41
t = FIELD_DP64(t, ID_AA64PFR0, CSV3, 1); /* FEAT_CSV3 */
42
cpu->isar.id_aa64pfr0 = t;
43
44
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
45
t = FIELD_DP64(t, ID_AA64PFR1, MTE, 3); /* FEAT_MTE3 */
46
t = FIELD_DP64(t, ID_AA64PFR1, RAS_FRAC, 0); /* FEAT_RASv1p1 + FEAT_DoubleFault */
47
t = FIELD_DP64(t, ID_AA64PFR1, SME, 1); /* FEAT_SME */
48
- t = FIELD_DP64(t, ID_AA64PFR1, CSV2_FRAC, 0); /* FEAT_CSV2_2 */
49
+ t = FIELD_DP64(t, ID_AA64PFR1, CSV2_FRAC, 0); /* FEAT_CSV2_3 */
50
t = FIELD_DP64(t, ID_AA64PFR1, NMI, 1); /* FEAT_NMI */
51
cpu->isar.id_aa64pfr1 = t;
27
52
28
--
53
--
29
2.20.1
54
2.34.1
30
55
31
56
diff view generated by jsdifflib
1
The lan9118 code mostly uses symbolic constants for register offsets;
1
FEAT_ETS2 is a tighter set of guarantees about memory ordering
2
the exceptions are those which the datasheet doesn't give an official
2
involving translation table walks than the old FEAT_ETS; FEAT_ETS has
3
symbolic name to.
3
been retired from the Arm ARM and the old ID_AA64MMFR1.ETS == 1
4
now gives no greater guarantees than ETS == 0.
4
5
5
Add some names for the registers which don't already have them, based
6
FEAT_ETS2 requires:
6
on the longer names they are given in the memory map.
7
* the virtual address of a load or store that appears in program
8
order after a DSB cannot be translated until after the DSB
9
completes (section B2.10.9)
10
* TLB maintenance operations that only affect translations without
11
execute permission are guaranteed complete after a DSB
12
(R_BLDZX)
13
* if a memory access RW2 is ordered-before memory access RW2,
14
then RW1 is also ordered-before any translation table walk
15
generated by RW2 that generates a Translation, Address size
16
or Access flag fault (R_NNFPF, I_CLGHP)
17
18
As with FEAT_ETS, QEMU is already compliant, because we do not
19
reorder translation table walk memory accesses relative to other
20
memory accesses, and we always guarantee to have finished TLB
21
maintenance as soon as the TLB op is done.
22
23
Update the documentation to list FEAT_ETS2 instead of the
24
no-longer-existent FEAT_ETS, and update the 'max' CPU ID registers.
7
25
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
27
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210108180401.2263-3-peter.maydell@linaro.org
28
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
29
Message-id: 20240418152004.2106516-4-peter.maydell@linaro.org
11
---
30
---
12
hw/net/lan9118.c | 24 ++++++++++++++++++------
31
docs/system/arm/emulation.rst | 2 +-
13
1 file changed, 18 insertions(+), 6 deletions(-)
32
target/arm/tcg/cpu32.c | 2 +-
33
target/arm/tcg/cpu64.c | 2 +-
34
3 files changed, 3 insertions(+), 3 deletions(-)
14
35
15
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
36
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
16
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/net/lan9118.c
38
--- a/docs/system/arm/emulation.rst
18
+++ b/hw/net/lan9118.c
39
+++ b/docs/system/arm/emulation.rst
19
@@ -XXX,XX +XXX,XX @@ do { hw_error("lan9118: error: " fmt , ## __VA_ARGS__);} while (0)
40
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
20
do { fprintf(stderr, "lan9118: error: " fmt , ## __VA_ARGS__);} while (0)
41
- FEAT_EL2 (Support for execution at EL2)
21
#endif
42
- FEAT_EL3 (Support for execution at EL3)
22
43
- FEAT_EPAC (Enhanced pointer authentication)
23
+/* The tx and rx fifo ports are a range of aliased 32-bit registers */
44
-- FEAT_ETS (Enhanced Translation Synchronization)
24
+#define RX_DATA_FIFO_PORT_FIRST 0x00
45
+- FEAT_ETS2 (Enhanced Translation Synchronization)
25
+#define RX_DATA_FIFO_PORT_LAST 0x1f
46
- FEAT_EVT (Enhanced Virtualization Traps)
26
+#define TX_DATA_FIFO_PORT_FIRST 0x20
47
- FEAT_F32MM (Single-precision Matrix Multiplication)
27
+#define TX_DATA_FIFO_PORT_LAST 0x3f
48
- FEAT_F64MM (Double-precision Matrix Multiplication)
28
+
49
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
29
+#define RX_STATUS_FIFO_PORT 0x40
50
index XXXXXXX..XXXXXXX 100644
30
+#define RX_STATUS_FIFO_PEEK 0x44
51
--- a/target/arm/tcg/cpu32.c
31
+#define TX_STATUS_FIFO_PORT 0x48
52
+++ b/target/arm/tcg/cpu32.c
32
+#define TX_STATUS_FIFO_PEEK 0x4c
53
@@ -XXX,XX +XXX,XX @@ void aa32_max_features(ARMCPU *cpu)
33
+
54
cpu->isar.id_mmfr4 = t;
34
#define CSR_ID_REV 0x50
55
35
#define CSR_IRQ_CFG 0x54
56
t = cpu->isar.id_mmfr5;
36
#define CSR_INT_STS 0x58
57
- t = FIELD_DP32(t, ID_MMFR5, ETS, 1); /* FEAT_ETS */
37
@@ -XXX,XX +XXX,XX @@ static void lan9118_writel(void *opaque, hwaddr offset,
58
+ t = FIELD_DP32(t, ID_MMFR5, ETS, 2); /* FEAT_ETS2 */
38
offset &= 0xff;
59
cpu->isar.id_mmfr5 = t;
39
60
40
//DPRINTF("Write reg 0x%02x = 0x%08x\n", (int)offset, val);
61
t = cpu->isar.id_pfr0;
41
- if (offset >= 0x20 && offset < 0x40) {
62
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
42
+ if (offset >= TX_DATA_FIFO_PORT_FIRST &&
63
index XXXXXXX..XXXXXXX 100644
43
+ offset <= TX_DATA_FIFO_PORT_LAST) {
64
--- a/target/arm/tcg/cpu64.c
44
/* TX FIFO */
65
+++ b/target/arm/tcg/cpu64.c
45
tx_fifo_push(s, val);
66
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
46
return;
67
t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1); /* FEAT_LOR */
47
@@ -XXX,XX +XXX,XX @@ static uint64_t lan9118_readl(void *opaque, hwaddr offset,
68
t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 3); /* FEAT_PAN3 */
48
lan9118_state *s = (lan9118_state *)opaque;
69
t = FIELD_DP64(t, ID_AA64MMFR1, XNX, 1); /* FEAT_XNX */
49
70
- t = FIELD_DP64(t, ID_AA64MMFR1, ETS, 1); /* FEAT_ETS */
50
//DPRINTF("Read reg 0x%02x\n", (int)offset);
71
+ t = FIELD_DP64(t, ID_AA64MMFR1, ETS, 2); /* FEAT_ETS2 */
51
- if (offset < 0x20) {
72
t = FIELD_DP64(t, ID_AA64MMFR1, HCX, 1); /* FEAT_HCX */
52
+ if (offset <= RX_DATA_FIFO_PORT_LAST) {
73
t = FIELD_DP64(t, ID_AA64MMFR1, TIDCP1, 1); /* FEAT_TIDCP1 */
53
/* RX FIFO */
74
cpu->isar.id_aa64mmfr1 = t;
54
return rx_fifo_pop(s);
55
}
56
switch (offset) {
57
- case 0x40:
58
+ case RX_STATUS_FIFO_PORT:
59
return rx_status_fifo_pop(s);
60
- case 0x44:
61
+ case RX_STATUS_FIFO_PEEK:
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
--
75
--
72
2.20.1
76
2.34.1
73
77
74
78
diff view generated by jsdifflib
1
From: Leif Lindholm <leif@nuviainc.com>
1
Newer versions of the Arm ARM (e.g. rev K.a) now define fields for
2
ID_AA64MMFR3_EL1. Implement this register, so that we can set the
3
fields if we need to. There's no behaviour change here since we
4
don't currently set the register value to non-zero.
2
5
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>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Message-id: 20240418152004.2106516-5-peter.maydell@linaro.org
7
---
10
---
8
target/arm/cpu.h | 31 +++++++++++++++++++++++++++++++
11
target/arm/cpu.h | 17 +++++++++++++++++
9
1 file changed, 31 insertions(+)
12
target/arm/helper.c | 6 ++++--
13
target/arm/hvf/hvf.c | 2 ++
14
target/arm/kvm.c | 2 ++
15
4 files changed, 25 insertions(+), 2 deletions(-)
10
16
11
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
12
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/cpu.h
19
--- a/target/arm/cpu.h
14
+++ b/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
15
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_FPCCR, ASPEN, 31, 1)
21
@@ -XXX,XX +XXX,XX @@ struct ArchCPU {
16
/*
22
uint64_t id_aa64mmfr0;
17
* System register ID fields.
23
uint64_t id_aa64mmfr1;
18
*/
24
uint64_t id_aa64mmfr2;
19
+FIELD(CLIDR_EL1, CTYPE1, 0, 3)
25
+ uint64_t id_aa64mmfr3;
20
+FIELD(CLIDR_EL1, CTYPE2, 3, 3)
26
uint64_t id_aa64dfr0;
21
+FIELD(CLIDR_EL1, CTYPE3, 6, 3)
27
uint64_t id_aa64dfr1;
22
+FIELD(CLIDR_EL1, CTYPE4, 9, 3)
28
uint64_t id_aa64zfr0;
23
+FIELD(CLIDR_EL1, CTYPE5, 12, 3)
29
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64MMFR2, BBM, 52, 4)
24
+FIELD(CLIDR_EL1, CTYPE6, 15, 3)
30
FIELD(ID_AA64MMFR2, EVT, 56, 4)
25
+FIELD(CLIDR_EL1, CTYPE7, 18, 3)
31
FIELD(ID_AA64MMFR2, E0PD, 60, 4)
26
+FIELD(CLIDR_EL1, LOUIS, 21, 3)
32
27
+FIELD(CLIDR_EL1, LOC, 24, 3)
33
+FIELD(ID_AA64MMFR3, TCRX, 0, 4)
28
+FIELD(CLIDR_EL1, LOUU, 27, 3)
34
+FIELD(ID_AA64MMFR3, SCTLRX, 4, 4)
29
+FIELD(CLIDR_EL1, ICB, 30, 3)
35
+FIELD(ID_AA64MMFR3, S1PIE, 8, 4)
36
+FIELD(ID_AA64MMFR3, S2PIE, 12, 4)
37
+FIELD(ID_AA64MMFR3, S1POE, 16, 4)
38
+FIELD(ID_AA64MMFR3, S2POE, 20, 4)
39
+FIELD(ID_AA64MMFR3, AIE, 24, 4)
40
+FIELD(ID_AA64MMFR3, MEC, 28, 4)
41
+FIELD(ID_AA64MMFR3, D128, 32, 4)
42
+FIELD(ID_AA64MMFR3, D128_2, 36, 4)
43
+FIELD(ID_AA64MMFR3, SNERR, 40, 4)
44
+FIELD(ID_AA64MMFR3, ANERR, 44, 4)
45
+FIELD(ID_AA64MMFR3, SDERR, 52, 4)
46
+FIELD(ID_AA64MMFR3, ADERR, 56, 4)
47
+FIELD(ID_AA64MMFR3, SPEC_FPACC, 60, 4)
30
+
48
+
31
+/* When FEAT_CCIDX is implemented */
49
FIELD(ID_AA64DFR0, DEBUGVER, 0, 4)
32
+FIELD(CCSIDR_EL1, CCIDX_LINESIZE, 0, 3)
50
FIELD(ID_AA64DFR0, TRACEVER, 4, 4)
33
+FIELD(CCSIDR_EL1, CCIDX_ASSOCIATIVITY, 3, 21)
51
FIELD(ID_AA64DFR0, PMUVER, 8, 4)
34
+FIELD(CCSIDR_EL1, CCIDX_NUMSETS, 32, 24)
52
diff --git a/target/arm/helper.c b/target/arm/helper.c
35
+
53
index XXXXXXX..XXXXXXX 100644
36
+/* When FEAT_CCIDX is not implemented */
54
--- a/target/arm/helper.c
37
+FIELD(CCSIDR_EL1, LINESIZE, 0, 3)
55
+++ b/target/arm/helper.c
38
+FIELD(CCSIDR_EL1, ASSOCIATIVITY, 3, 10)
56
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
39
+FIELD(CCSIDR_EL1, NUMSETS, 13, 15)
57
.access = PL1_R, .type = ARM_CP_CONST,
40
+
58
.accessfn = access_aa64_tid3,
41
+FIELD(CTR_EL0, IMINLINE, 0, 4)
59
.resetvalue = cpu->isar.id_aa64mmfr2 },
42
+FIELD(CTR_EL0, L1IP, 14, 2)
60
- { .name = "ID_AA64MMFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
43
+FIELD(CTR_EL0, DMINLINE, 16, 4)
61
+ { .name = "ID_AA64MMFR3_EL1", .state = ARM_CP_STATE_AA64,
44
+FIELD(CTR_EL0, ERG, 20, 4)
62
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 3,
45
+FIELD(CTR_EL0, CWG, 24, 4)
63
.access = PL1_R, .type = ARM_CP_CONST,
46
+FIELD(CTR_EL0, IDC, 28, 1)
64
.accessfn = access_aa64_tid3,
47
+FIELD(CTR_EL0, DIC, 29, 1)
65
- .resetvalue = 0 },
48
+FIELD(CTR_EL0, TMINLINE, 32, 6)
66
+ .resetvalue = cpu->isar.id_aa64mmfr3 },
49
+
67
{ .name = "ID_AA64MMFR4_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
50
FIELD(MIDR_EL1, REVISION, 0, 4)
68
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 4,
51
FIELD(MIDR_EL1, PARTNUM, 4, 12)
69
.access = PL1_R, .type = ARM_CP_CONST,
52
FIELD(MIDR_EL1, ARCHITECTURE, 16, 4)
70
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
71
.exported_bits = R_ID_AA64MMFR1_AFP_MASK },
72
{ .name = "ID_AA64MMFR2_EL1",
73
.exported_bits = R_ID_AA64MMFR2_AT_MASK },
74
+ { .name = "ID_AA64MMFR3_EL1",
75
+ .exported_bits = 0 },
76
{ .name = "ID_AA64MMFR*_EL1_RESERVED",
77
.is_glob = true },
78
{ .name = "ID_AA64DFR0_EL1",
79
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/target/arm/hvf/hvf.c
82
+++ b/target/arm/hvf/hvf.c
83
@@ -XXX,XX +XXX,XX @@ static struct hvf_sreg_match hvf_sreg_match[] = {
84
#endif
85
{ HV_SYS_REG_ID_AA64MMFR1_EL1, HVF_SYSREG(0, 7, 3, 0, 1) },
86
{ HV_SYS_REG_ID_AA64MMFR2_EL1, HVF_SYSREG(0, 7, 3, 0, 2) },
87
+ /* Add ID_AA64MMFR3_EL1 here when HVF supports it */
88
89
{ HV_SYS_REG_MDSCR_EL1, HVF_SYSREG(0, 2, 2, 0, 2) },
90
{ HV_SYS_REG_SCTLR_EL1, HVF_SYSREG(1, 0, 3, 0, 0) },
91
@@ -XXX,XX +XXX,XX @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
92
{ HV_SYS_REG_ID_AA64MMFR0_EL1, &host_isar.id_aa64mmfr0 },
93
{ HV_SYS_REG_ID_AA64MMFR1_EL1, &host_isar.id_aa64mmfr1 },
94
{ HV_SYS_REG_ID_AA64MMFR2_EL1, &host_isar.id_aa64mmfr2 },
95
+ /* Add ID_AA64MMFR3_EL1 here when HVF supports it */
96
};
97
hv_vcpu_t fd;
98
hv_return_t r = HV_SUCCESS;
99
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/target/arm/kvm.c
102
+++ b/target/arm/kvm.c
103
@@ -XXX,XX +XXX,XX @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
104
ARM64_SYS_REG(3, 0, 0, 7, 1));
105
err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr2,
106
ARM64_SYS_REG(3, 0, 0, 7, 2));
107
+ err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr3,
108
+ ARM64_SYS_REG(3, 0, 0, 7, 3));
109
110
/*
111
* Note that if AArch32 support is not present in the host,
53
--
112
--
54
2.20.1
113
2.34.1
55
114
56
115
diff view generated by jsdifflib
1
When we first converted our documentation to Sphinx, we split it into
1
FEAT_Spec_FPACC is a feature describing speculative behaviour in the
2
multiple manuals (system, interop, tools, etc), which are all built
2
event of a PAC authontication failure when FEAT_FPACCOMBINE is
3
separately. The primary driver for this was wanting to be able to
3
implemented. FEAT_Spec_FPACC means that the speculative use of
4
avoid shipping the 'devel' manual to end-users. However, this is
4
pointers processed by a PAC Authentication is not materially
5
working against the grain of the way Sphinx wants to be used and
5
different in terms of the impact on cached microarchitectural state
6
causes some annoyances:
6
(caches, TLBs, etc) between passing and failing of the PAC
7
* Cross-references between documents become much harder or
7
Authentication.
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
8
15
Merely hiding our developer documentation from end users seems like
9
QEMU doesn't do speculative execution, so we can advertise
16
it's not enough benefit for these costs. Combine all the
10
this feature.
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
11
37
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
38
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
39
Message-id: 20210108161416.21129-3-peter.maydell@linaro.org
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
15
Message-id: 20240418152004.2106516-6-peter.maydell@linaro.org
40
---
16
---
41
docs/conf.py | 46 ++++++++++++++++++++++++++++++-
17
docs/system/arm/emulation.rst | 1 +
42
docs/devel/conf.py | 15 -----------
18
target/arm/tcg/cpu64.c | 4 ++++
43
docs/index.html.in | 17 ------------
19
2 files changed, 5 insertions(+)
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
20
59
diff --git a/docs/conf.py b/docs/conf.py
21
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
60
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
61
--- a/docs/conf.py
23
--- a/docs/system/arm/emulation.rst
62
+++ b/docs/conf.py
24
+++ b/docs/system/arm/emulation.rst
63
@@ -XXX,XX +XXX,XX @@ latex_documents = [
25
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
64
26
- FEAT_FP16 (Half-precision floating-point data processing)
65
# -- Options for manual page output ---------------------------------------
27
- FEAT_FPAC (Faulting on AUT* instructions)
66
# Individual manual/conf.py can override this to create man pages
28
- FEAT_FPACCOMBINE (Faulting on combined pointer authentication instructions)
67
-man_pages = []
29
+- FEAT_FPACC_SPEC (Speculative behavior of combined pointer authentication instructions)
68
+man_pages = [
30
- FEAT_FRINTTS (Floating-point to integer instructions)
69
+ ('interop/qemu-ga', 'qemu-ga',
31
- FEAT_FlagM (Flag manipulation instructions v2)
70
+ 'QEMU Guest Agent',
32
- FEAT_FlagM2 (Enhancements to flag manipulation instructions)
71
+ ['Michael Roth <mdroth@linux.vnet.ibm.com>'], 8),
33
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
72
+ ('interop/qemu-ga-ref', 'qemu-ga-ref',
73
+ 'QEMU Guest Agent Protocol Reference',
74
+ [], 7),
75
+ ('interop/qemu-qmp-ref', 'qemu-qmp-ref',
76
+ 'QEMU QMP Reference Manual',
77
+ [], 7),
78
+ ('interop/qemu-storage-daemon-qmp-ref', 'qemu-storage-daemon-qmp-ref',
79
+ 'QEMU Storage Daemon QMP Reference Manual',
80
+ [], 7),
81
+ ('system/qemu-manpage', 'qemu',
82
+ 'QEMU User Documentation',
83
+ ['Fabrice Bellard'], 1),
84
+ ('system/qemu-block-drivers', 'qemu-block-drivers',
85
+ 'QEMU block drivers reference',
86
+ ['Fabrice Bellard and the QEMU Project developers'], 7),
87
+ ('system/qemu-cpu-models', 'qemu-cpu-models',
88
+ 'QEMU CPU Models',
89
+ ['The QEMU Project developers'], 7),
90
+ ('tools/qemu-img', 'qemu-img',
91
+ 'QEMU disk image utility',
92
+ ['Fabrice Bellard'], 1),
93
+ ('tools/qemu-nbd', 'qemu-nbd',
94
+ 'QEMU Disk Network Block Device Server',
95
+ ['Anthony Liguori <anthony@codemonkey.ws>'], 8),
96
+ ('tools/qemu-pr-helper', 'qemu-pr-helper',
97
+ 'QEMU persistent reservation helper',
98
+ [], 8),
99
+ ('tools/qemu-storage-daemon', 'qemu-storage-daemon',
100
+ 'QEMU storage daemon',
101
+ [], 1),
102
+ ('tools/qemu-trace-stap', 'qemu-trace-stap',
103
+ 'QEMU SystemTap trace tool',
104
+ [], 1),
105
+ ('tools/virtfs-proxy-helper', 'virtfs-proxy-helper',
106
+ 'QEMU 9p virtfs proxy filesystem helper',
107
+ ['M. Mohan Kumar'], 1),
108
+ ('tools/virtiofsd', 'virtiofsd',
109
+ 'QEMU virtio-fs shared file system daemon',
110
+ ['Stefan Hajnoczi <stefanha@redhat.com>',
111
+ 'Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>'], 1),
112
+]
113
114
# -- Options for Texinfo output -------------------------------------------
115
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
-
130
-qemu_docdir = os.path.abspath("..")
131
-parent_config = os.path.join(qemu_docdir, "conf.py")
132
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
133
-
134
-# This slightly misuses the 'description', but is the best way to get
135
-# the manual title to appear in the sidebar.
136
-html_theme_options['description'] = u'Developer''s Guide'
137
diff --git a/docs/index.html.in b/docs/index.html.in
138
deleted file mode 100644
139
index XXXXXXX..XXXXXXX
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
34
index XXXXXXX..XXXXXXX 100644
196
--- a/docs/meson.build
35
--- a/target/arm/tcg/cpu64.c
197
+++ b/docs/meson.build
36
+++ b/target/arm/tcg/cpu64.c
198
@@ -XXX,XX +XXX,XX @@ if build_docs
37
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
199
meson.source_root() / 'docs/sphinx/qmp_lexer.py',
38
t = FIELD_DP64(t, ID_AA64MMFR2, E0PD, 1); /* FEAT_E0PD */
200
qapi_gen_depends ]
39
cpu->isar.id_aa64mmfr2 = t;
201
40
202
- configure_file(output: 'index.html',
41
+ t = cpu->isar.id_aa64mmfr3;
203
- input: files('index.html.in'),
42
+ t = FIELD_DP64(t, ID_AA64MMFR3, SPEC_FPACC, 1); /* FEAT_FPACC_SPEC */
204
- configuration: {'VERSION': meson.project_version()},
43
+ cpu->isar.id_aa64mmfr3 = t;
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
+
44
+
242
+ this_manual = custom_target('QEMU manual',
45
t = cpu->isar.id_aa64zfr0;
243
build_by_default: build_docs,
46
t = FIELD_DP64(t, ID_AA64ZFR0, SVEVER, 1);
244
- output: [manual + '.stamp'],
47
t = FIELD_DP64(t, ID_AA64ZFR0, AES, 2); /* FEAT_SVE_PMULL128 */
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
--
48
--
418
2.20.1
49
2.34.1
419
50
420
51
diff view generated by jsdifflib
1
A copy-and-paste error meant that the return value for register offset 0x44
1
The Linux kernel 5.10.16 binary for sunxi has been removed from
2
(the RX Status FIFO PEEK register) returned a byte from a bogus offset in
2
apt.armbian.com. This means that the avocado tests for these machines
3
the rx status FIFO. Fix the typo.
3
will be skipped (status CANCEL) if the old binary isn't present in
4
the avocado cache.
5
6
Update to 6.6.16, in the same way we did in commit e384db41d8661
7
when we moved to 5.10.16 in 2021.
4
8
5
Cc: qemu-stable@nongnu.org
9
Cc: qemu-stable@nongnu.org
6
Fixes: https://bugs.launchpad.net/qemu/+bug/1904954
10
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2284
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Reviewed-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
9
Message-id: 20210108180401.2263-2-peter.maydell@linaro.org
13
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
14
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
15
Message-id: 20240415151845.1564201-1-peter.maydell@linaro.org
10
---
16
---
11
hw/net/lan9118.c | 2 +-
17
tests/avocado/boot_linux_console.py | 70 ++++++++++++++---------------
12
1 file changed, 1 insertion(+), 1 deletion(-)
18
tests/avocado/replay_kernel.py | 8 ++--
19
2 files changed, 39 insertions(+), 39 deletions(-)
13
20
14
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
21
diff --git a/tests/avocado/boot_linux_console.py b/tests/avocado/boot_linux_console.py
15
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/net/lan9118.c
23
--- a/tests/avocado/boot_linux_console.py
17
+++ b/hw/net/lan9118.c
24
+++ b/tests/avocado/boot_linux_console.py
18
@@ -XXX,XX +XXX,XX @@ static uint64_t lan9118_readl(void *opaque, hwaddr offset,
25
@@ -XXX,XX +XXX,XX @@ def test_arm_cubieboard_initrd(self):
19
case 0x40:
26
:avocado: tags=accel:tcg
20
return rx_status_fifo_pop(s);
27
"""
21
case 0x44:
28
deb_url = ('https://apt.armbian.com/pool/main/l/'
22
- return s->rx_status_fifo[s->tx_status_fifo_head];
29
- 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
23
+ return s->rx_status_fifo[s->rx_status_fifo_head];
30
- deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
24
case 0x48:
31
+ 'linux-6.6.16/linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb')
25
return tx_status_fifo_pop(s);
32
+ deb_hash = 'f7c3c8c5432f765445dc6e7eab02f3bbe668256b'
26
case 0x4c:
33
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
34
kernel_path = self.extract_from_deb(deb_path,
35
- '/boot/vmlinuz-5.10.16-sunxi')
36
- dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb'
37
+ '/boot/vmlinuz-6.6.16-current-sunxi')
38
+ dtb_path = '/usr/lib/linux-image-6.6.16-current-sunxi/sun4i-a10-cubieboard.dtb'
39
dtb_path = self.extract_from_deb(deb_path, dtb_path)
40
initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
41
'2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
42
@@ -XXX,XX +XXX,XX @@ def test_arm_cubieboard_sata(self):
43
:avocado: tags=accel:tcg
44
"""
45
deb_url = ('https://apt.armbian.com/pool/main/l/'
46
- 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
47
- deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
48
+ 'linux-6.6.16/linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb')
49
+ deb_hash = 'f7c3c8c5432f765445dc6e7eab02f3bbe668256b'
50
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
51
kernel_path = self.extract_from_deb(deb_path,
52
- '/boot/vmlinuz-5.10.16-sunxi')
53
- dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb'
54
+ '/boot/vmlinuz-6.6.16-current-sunxi')
55
+ dtb_path = '/usr/lib/linux-image-6.6.16-current-sunxi/sun4i-a10-cubieboard.dtb'
56
dtb_path = self.extract_from_deb(deb_path, dtb_path)
57
rootfs_url = ('https://github.com/groeck/linux-build-test/raw/'
58
'2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
59
@@ -XXX,XX +XXX,XX @@ def test_arm_bpim2u(self):
60
:avocado: tags=machine:bpim2u
61
:avocado: tags=accel:tcg
62
"""
63
- deb_url = ('https://apt.armbian.com/pool/main/l/linux-5.10.16-sunxi/'
64
- 'linux-image-current-sunxi_21.02.2_armhf.deb')
65
- deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
66
+ deb_url = ('https://apt.armbian.com/pool/main/l/'
67
+ 'linux-6.6.16/linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb')
68
+ deb_hash = 'f7c3c8c5432f765445dc6e7eab02f3bbe668256b'
69
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
70
kernel_path = self.extract_from_deb(deb_path,
71
- '/boot/vmlinuz-5.10.16-sunxi')
72
- dtb_path = ('/usr/lib/linux-image-current-sunxi/'
73
+ '/boot/vmlinuz-6.6.16-current-sunxi')
74
+ dtb_path = ('/usr/lib/linux-image-6.6.16-current-sunxi/'
75
'sun8i-r40-bananapi-m2-ultra.dtb')
76
dtb_path = self.extract_from_deb(deb_path, dtb_path)
77
78
@@ -XXX,XX +XXX,XX @@ def test_arm_bpim2u_initrd(self):
79
:avocado: tags=accel:tcg
80
:avocado: tags=machine:bpim2u
81
"""
82
- deb_url = ('https://apt.armbian.com/pool/main/l/linux-5.10.16-sunxi/'
83
- 'linux-image-current-sunxi_21.02.2_armhf.deb')
84
- deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
85
+ deb_url = ('https://apt.armbian.com/pool/main/l/'
86
+ 'linux-6.6.16/linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb')
87
+ deb_hash = 'f7c3c8c5432f765445dc6e7eab02f3bbe668256b'
88
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
89
kernel_path = self.extract_from_deb(deb_path,
90
- '/boot/vmlinuz-5.10.16-sunxi')
91
- dtb_path = ('/usr/lib/linux-image-current-sunxi/'
92
+ '/boot/vmlinuz-6.6.16-current-sunxi')
93
+ dtb_path = ('/usr/lib/linux-image-6.6.16-current-sunxi/'
94
'sun8i-r40-bananapi-m2-ultra.dtb')
95
dtb_path = self.extract_from_deb(deb_path, dtb_path)
96
initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
97
@@ -XXX,XX +XXX,XX @@ def test_arm_bpim2u_gmac(self):
98
"""
99
self.require_netdev('user')
100
101
- deb_url = ('https://apt.armbian.com/pool/main/l/linux-5.10.16-sunxi/'
102
- 'linux-image-current-sunxi_21.02.2_armhf.deb')
103
- deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
104
+ deb_url = ('https://apt.armbian.com/pool/main/l/'
105
+ 'linux-6.6.16/linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb')
106
+ deb_hash = 'f7c3c8c5432f765445dc6e7eab02f3bbe668256b'
107
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
108
kernel_path = self.extract_from_deb(deb_path,
109
- '/boot/vmlinuz-5.10.16-sunxi')
110
- dtb_path = ('/usr/lib/linux-image-current-sunxi/'
111
+ '/boot/vmlinuz-6.6.16-current-sunxi')
112
+ dtb_path = ('/usr/lib/linux-image-6.6.16-current-sunxi/'
113
'sun8i-r40-bananapi-m2-ultra.dtb')
114
dtb_path = self.extract_from_deb(deb_path, dtb_path)
115
rootfs_url = ('http://storage.kernelci.org/images/rootfs/buildroot/'
116
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi(self):
117
:avocado: tags=accel:tcg
118
"""
119
deb_url = ('https://apt.armbian.com/pool/main/l/'
120
- 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
121
- deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
122
+ 'linux-6.6.16/linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb')
123
+ deb_hash = 'f7c3c8c5432f765445dc6e7eab02f3bbe668256b'
124
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
125
kernel_path = self.extract_from_deb(deb_path,
126
- '/boot/vmlinuz-5.10.16-sunxi')
127
- dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb'
128
+ '/boot/vmlinuz-6.6.16-current-sunxi')
129
+ dtb_path = '/usr/lib/linux-image-6.6.16-current-sunxi/sun8i-h3-orangepi-pc.dtb'
130
dtb_path = self.extract_from_deb(deb_path, dtb_path)
131
132
self.vm.set_console()
133
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_initrd(self):
134
:avocado: tags=machine:orangepi-pc
135
"""
136
deb_url = ('https://apt.armbian.com/pool/main/l/'
137
- 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
138
- deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
139
+ 'linux-6.6.16/linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb')
140
+ deb_hash = 'f7c3c8c5432f765445dc6e7eab02f3bbe668256b'
141
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
142
kernel_path = self.extract_from_deb(deb_path,
143
- '/boot/vmlinuz-5.10.16-sunxi')
144
- dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb'
145
+ '/boot/vmlinuz-6.6.16-current-sunxi')
146
+ dtb_path = '/usr/lib/linux-image-6.6.16-current-sunxi/sun8i-h3-orangepi-pc.dtb'
147
dtb_path = self.extract_from_deb(deb_path, dtb_path)
148
initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
149
'2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
150
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_sd(self):
151
self.require_netdev('user')
152
153
deb_url = ('https://apt.armbian.com/pool/main/l/'
154
- 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
155
- deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
156
+ 'linux-6.6.16/linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb')
157
+ deb_hash = 'f7c3c8c5432f765445dc6e7eab02f3bbe668256b'
158
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
159
kernel_path = self.extract_from_deb(deb_path,
160
- '/boot/vmlinuz-5.10.16-sunxi')
161
- dtb_path = '/usr/lib/linux-image-current-sunxi/sun8i-h3-orangepi-pc.dtb'
162
+ '/boot/vmlinuz-6.6.16-current-sunxi')
163
+ dtb_path = '/usr/lib/linux-image-6.6.16-current-sunxi/sun8i-h3-orangepi-pc.dtb'
164
dtb_path = self.extract_from_deb(deb_path, dtb_path)
165
rootfs_url = ('http://storage.kernelci.org/images/rootfs/buildroot/'
166
'buildroot-baseline/20221116.0/armel/rootfs.ext2.xz')
167
diff --git a/tests/avocado/replay_kernel.py b/tests/avocado/replay_kernel.py
168
index XXXXXXX..XXXXXXX 100644
169
--- a/tests/avocado/replay_kernel.py
170
+++ b/tests/avocado/replay_kernel.py
171
@@ -XXX,XX +XXX,XX @@ def test_arm_cubieboard_initrd(self):
172
:avocado: tags=machine:cubieboard
173
"""
174
deb_url = ('https://apt.armbian.com/pool/main/l/'
175
- 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb')
176
- deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
177
+ 'linux-6.6.16/linux-image-current-sunxi_24.2.1_armhf__6.6.16-Seb3e-D6b4a-P2359-Ce96bHfe66-HK01ba-V014b-B067e-R448a.deb')
178
+ deb_hash = 'f7c3c8c5432f765445dc6e7eab02f3bbe668256b'
179
deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
180
kernel_path = self.extract_from_deb(deb_path,
181
- '/boot/vmlinuz-5.10.16-sunxi')
182
- dtb_path = '/usr/lib/linux-image-current-sunxi/sun4i-a10-cubieboard.dtb'
183
+ '/boot/vmlinuz-6.6.16-current-sunxi')
184
+ dtb_path = '/usr/lib/linux-image-6.6.16-current-sunxi/sun4i-a10-cubieboard.dtb'
185
dtb_path = self.extract_from_deb(deb_path, dtb_path)
186
initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
187
'2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
27
--
188
--
28
2.20.1
189
2.34.1
29
30
diff view generated by jsdifflib
1
From: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
1
The generic timer frequency is settable by board code via a QOM
2
property "cntfrq", but otherwise defaults to 62.5MHz. The way this
3
is done includes some complication resulting from how this was
4
originally a fixed value with no QOM property. Clean it up:
2
5
3
This adds for the Small Translation tables extension in AArch64 state.
6
* always set cpu->gt_cntfrq_hz to some sensible value, whether
7
the CPU has the generic timer or not, and whether it's system
8
or user-only emulation
9
* this means we can always use gt_cntfrq_hz, and never need
10
the old GTIMER_SCALE define
11
* set the default value in exactly one place, in the realize fn
4
12
5
Signed-off-by: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
13
The aim here is to pave the way for handling the ARMv8.6 requirement
14
that the generic timer frequency is always 1GHz. We're going to do
15
that by having old CPU types keep their legacy-in-QEMU behaviour and
16
having the default for any new CPU types be a 1GHz rather han 62.5MHz
17
cntfrq, so we want the point where the default is decided to be in
18
one place, and in code, not in a DEFINE_PROP_UINT64() initializer.
19
20
This commit should have no behavioural changes.
21
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Message-id: 20240426122913.3427983-2-peter.maydell@linaro.org
8
---
26
---
9
target/arm/cpu.h | 5 +++++
27
target/arm/internals.h | 7 ++++---
10
target/arm/helper.c | 15 +++++++++++++--
28
target/arm/cpu.c | 31 +++++++++++++++++--------------
11
2 files changed, 18 insertions(+), 2 deletions(-)
29
target/arm/helper.c | 16 ++++++++--------
30
3 files changed, 29 insertions(+), 25 deletions(-)
12
31
13
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
32
diff --git a/target/arm/internals.h b/target/arm/internals.h
14
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/cpu.h
34
--- a/target/arm/internals.h
16
+++ b/target/arm/cpu.h
35
+++ b/target/arm/internals.h
17
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_uao(const ARMISARegisters *id)
36
@@ -XXX,XX +XXX,XX @@ static inline bool excp_is_internal(int excp)
18
return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0;
37
|| excp == EXCP_SEMIHOST;
19
}
38
}
20
39
21
+static inline bool isar_feature_aa64_st(const ARMISARegisters *id)
40
-/* Scale factor for generic timers, ie number of ns per tick.
22
+{
41
- * This gives a 62.5MHz timer.
23
+ return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, ST) != 0;
42
+/*
24
+}
43
+ * Default frequency for the generic timer, in Hz.
44
+ * This is 62.5MHz, which gives a 16 ns tick period.
45
*/
46
-#define GTIMER_SCALE 16
47
+#define GTIMER_DEFAULT_HZ 62500000
48
49
/* Bit definitions for the v7M CONTROL register */
50
FIELD(V7M_CONTROL, NPRIV, 0, 1)
51
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/cpu.c
54
+++ b/target/arm/cpu.c
55
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_initfn(Object *obj)
56
}
57
}
58
59
+/*
60
+ * 0 means "unset, use the default value". That default might vary depending
61
+ * on the CPU type, and is set in the realize fn.
62
+ */
63
static Property arm_cpu_gt_cntfrq_property =
64
- DEFINE_PROP_UINT64("cntfrq", ARMCPU, gt_cntfrq_hz,
65
- NANOSECONDS_PER_SECOND / GTIMER_SCALE);
66
+ DEFINE_PROP_UINT64("cntfrq", ARMCPU, gt_cntfrq_hz, 0);
67
68
static Property arm_cpu_reset_cbar_property =
69
DEFINE_PROP_UINT64("reset-cbar", ARMCPU, reset_cbar, 0);
70
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
71
return;
72
}
73
74
+ if (!cpu->gt_cntfrq_hz) {
75
+ /*
76
+ * 0 means "the board didn't set a value, use the default".
77
+ * The default value of the generic timer frequency (as seen in
78
+ * CNTFRQ_EL0) is 62.5MHz, which corresponds to a period of 16ns.
79
+ * This is what you get (a) for a CONFIG_USER_ONLY CPU (b) if the
80
+ * board doesn't set it.
81
+ */
82
+ cpu->gt_cntfrq_hz = GTIMER_DEFAULT_HZ;
83
+ }
25
+
84
+
26
static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
85
#ifndef CONFIG_USER_ONLY
27
{
86
/* The NVIC and M-profile CPU are two halves of a single piece of
28
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;
87
* hardware; trying to use one without the other is a command line
88
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
89
}
90
91
{
92
- uint64_t scale;
93
-
94
- if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
95
- if (!cpu->gt_cntfrq_hz) {
96
- error_setg(errp, "Invalid CNTFRQ: %"PRId64"Hz",
97
- cpu->gt_cntfrq_hz);
98
- return;
99
- }
100
- scale = gt_cntfrq_period_ns(cpu);
101
- } else {
102
- scale = GTIMER_SCALE;
103
- }
104
+ uint64_t scale = gt_cntfrq_period_ns(cpu);
105
106
cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
107
arm_gt_ptimer_cb, cpu);
29
diff --git a/target/arm/helper.c b/target/arm/helper.c
108
diff --git a/target/arm/helper.c b/target/arm/helper.c
30
index XXXXXXX..XXXXXXX 100644
109
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/helper.c
110
--- a/target/arm/helper.c
32
+++ b/target/arm/helper.c
111
+++ b/target/arm/helper.c
33
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
112
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v6k_cp_reginfo[] = {
34
{
113
.resetvalue = 0 },
35
uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
114
};
36
bool epd, hpd, using16k, using64k;
115
37
- int select, tsz, tbi;
116
+static void arm_gt_cntfrq_reset(CPUARMState *env, const ARMCPRegInfo *opaque)
38
+ int select, tsz, tbi, max_tsz;
117
+{
39
118
+ ARMCPU *cpu = env_archcpu(env);
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
}
46
- tsz = MIN(tsz, 39); /* TODO: ARMv8.4-TTST */
47
+
119
+
48
+ if (cpu_isar_feature(aa64_st, env_archcpu(env))) {
120
+ cpu->env.cp15.c14_cntfrq = cpu->gt_cntfrq_hz;
49
+ max_tsz = 48 - using64k;
121
+}
50
+ } else {
51
+ max_tsz = 39;
52
+ }
53
+
122
+
54
+ tsz = MIN(tsz, max_tsz);
123
#ifndef CONFIG_USER_ONLY
55
tsz = MAX(tsz, 16); /* TODO: ARMv8.2-LVA */
124
56
125
static CPAccessResult gt_cntfrq_access(CPUARMState *env, const ARMCPRegInfo *ri,
57
/* Present TBI as a composite with TBID. */
126
@@ -XXX,XX +XXX,XX @@ void arm_gt_hvtimer_cb(void *opaque)
58
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
127
gt_recalc_timer(cpu, GTIMER_HYPVIRT);
59
if (!aarch64 || stride == 9) {
128
}
60
/* AArch32 or 4KB pages */
129
61
startlevel = 2 - sl0;
130
-static void arm_gt_cntfrq_reset(CPUARMState *env, const ARMCPRegInfo *opaque)
62
+
131
-{
63
+ if (cpu_isar_feature(aa64_st, cpu)) {
132
- ARMCPU *cpu = env_archcpu(env);
64
+ startlevel &= 3;
133
-
65
+ }
134
- cpu->env.cp15.c14_cntfrq = cpu->gt_cntfrq_hz;
66
} else {
135
-}
67
/* 16KB or 64KB pages */
136
-
68
startlevel = 3 - sl0;
137
static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
138
/*
139
* Note that CNTFRQ is purely reads-as-written for the benefit
140
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
141
.opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 0,
142
.type = ARM_CP_CONST, .access = PL0_R /* no PL1_RW in linux-user */,
143
.fieldoffset = offsetof(CPUARMState, cp15.c14_cntfrq),
144
- .resetvalue = NANOSECONDS_PER_SECOND / GTIMER_SCALE,
145
+ .resetfn = arm_gt_cntfrq_reset,
146
},
147
{ .name = "CNTVCT_EL0", .state = ARM_CP_STATE_AA64,
148
.opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 2,
69
--
149
--
70
2.20.1
150
2.34.1
71
151
72
152
diff view generated by jsdifflib
1
From: Leif Lindholm <leif@nuviainc.com>
1
Currently QEMU CPUs always run with a generic timer counter frequency
2
of 62.5MHz, but ARMv8.6 CPUs will run at 1GHz. For older versions of
3
the TF-A firmware that sbsa-ref runs, the frequency of the generic
4
timer is hardcoded into the firmware, and so if the CPU actually has
5
a different frequency then timers in the guest will be set
6
incorrectly.
2
7
3
Add entries present in ARM DDI 0487F.c (August 2020).
8
The default frequency used by the 'max' CPU is about to change, so
9
make the sbsa-ref board force the CPU frequency to the value which
10
the firmware expects.
4
11
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
12
Newer versions of TF-A will read the frequency from the CPU's
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
CNTFRQ_EL0 register:
7
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
14
https://github.com/ARM-software/arm-trusted-firmware/commit/4c77fac98dac0bebc63798aae9101ac865b87148
8
Message-id: 20210108185154.8108-6-leif@nuviainc.com
15
so in the longer term we could make this board use the 1GHz
16
frequency. We will need to make sure we update the binaries used
17
by our avocado test
18
Aarch64SbsarefMachine.test_sbsaref_alpine_linux_max_pauth_impdef
19
before we can do that.
20
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
23
Reviewed-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
24
Message-id: 20240426122913.3427983-3-peter.maydell@linaro.org
10
---
25
---
11
target/arm/cpu.h | 15 +++++++++++++++
26
hw/arm/sbsa-ref.c | 15 +++++++++++++++
12
1 file changed, 15 insertions(+)
27
1 file changed, 15 insertions(+)
13
28
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
29
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
15
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
31
--- a/hw/arm/sbsa-ref.c
17
+++ b/target/arm/cpu.h
32
+++ b/hw/arm/sbsa-ref.c
18
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64ISAR1, GPI, 28, 4)
33
@@ -XXX,XX +XXX,XX @@
19
FIELD(ID_AA64ISAR1, FRINTTS, 32, 4)
34
#define NUM_SMMU_IRQS 4
20
FIELD(ID_AA64ISAR1, SB, 36, 4)
35
#define NUM_SATA_PORTS 6
21
FIELD(ID_AA64ISAR1, SPECRES, 40, 4)
36
22
+FIELD(ID_AA64ISAR1, BF16, 44, 4)
37
+/*
23
+FIELD(ID_AA64ISAR1, DGH, 48, 4)
38
+ * Generic timer frequency in Hz (which drives both the CPU generic timers
24
+FIELD(ID_AA64ISAR1, I8MM, 52, 4)
39
+ * and the SBSA watchdog-timer). Older versions of the TF-A firmware
25
40
+ * typically used with sbsa-ref (including the binaries in our Avocado test
26
FIELD(ID_AA64PFR0, EL0, 0, 4)
41
+ * Aarch64SbsarefMachine.test_sbsaref_alpine_linux_max_pauth_impdef
27
FIELD(ID_AA64PFR0, EL1, 4, 4)
42
+ * assume it is this value.
28
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64PFR0, ADVSIMD, 20, 4)
43
+ *
29
FIELD(ID_AA64PFR0, GIC, 24, 4)
44
+ * TODO: this value is not architecturally correct for an Armv8.6 or
30
FIELD(ID_AA64PFR0, RAS, 28, 4)
45
+ * better CPU, so we should move to 1GHz once the TF-A fix above has
31
FIELD(ID_AA64PFR0, SVE, 32, 4)
46
+ * made it into a release and into our Avocado test.
32
+FIELD(ID_AA64PFR0, SEL2, 36, 4)
47
+ */
33
+FIELD(ID_AA64PFR0, MPAM, 40, 4)
48
+#define SBSA_GTIMER_HZ 62500000
34
+FIELD(ID_AA64PFR0, AMU, 44, 4)
49
+
35
+FIELD(ID_AA64PFR0, DIT, 48, 4)
50
enum {
36
+FIELD(ID_AA64PFR0, CSV2, 56, 4)
51
SBSA_FLASH,
37
+FIELD(ID_AA64PFR0, CSV3, 60, 4)
52
SBSA_MEM,
38
53
@@ -XXX,XX +XXX,XX @@ static void sbsa_ref_init(MachineState *machine)
39
FIELD(ID_AA64PFR1, BT, 0, 4)
54
&error_abort);
40
FIELD(ID_AA64PFR1, SSBS, 4, 4)
55
}
41
FIELD(ID_AA64PFR1, MTE, 8, 4)
56
42
FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4)
57
+ object_property_set_int(cpuobj, "cntfrq", SBSA_GTIMER_HZ, &error_abort);
43
+FIELD(ID_AA64PFR1, MPAM_FRAC, 16, 4)
58
+
44
59
object_property_set_link(cpuobj, "memory", OBJECT(sysmem),
45
FIELD(ID_AA64MMFR0, PARANGE, 0, 4)
60
&error_abort);
46
FIELD(ID_AA64MMFR0, ASIDBITS, 4, 4)
61
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
--
62
--
74
2.20.1
63
2.34.1
75
64
76
65
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
Currently the sbsa_gdwt watchdog device hardcodes its frequency at
2
62.5MHz. In real hardware, this watchdog is supposed to be driven
3
from the system counter, which also drives the CPU generic timers.
4
Newer CPU types (in particular from Armv8.6) should have a CPU
5
generic timer frequency of 1GHz, so we can't leave the watchdog
6
on the old QEMU default of 62.5GHz.
2
7
3
The ADC is part of NPCM7XX Module. Its behavior is controled by the
8
Make the frequency a QOM property so it can be set by the board,
4
ADC_CON register. It converts one of the eight analog inputs into a
9
and have our only board that uses this device set that frequency
5
digital input and stores it in the ADC_DATA register when enabled.
10
to the same value it sets the CPU frequency.
6
11
7
Users can alter input value by using qom-set QMP command.
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
14
Message-id: 20240426122913.3427983-4-peter.maydell@linaro.org
15
---
16
include/hw/watchdog/sbsa_gwdt.h | 3 +--
17
hw/arm/sbsa-ref.c | 1 +
18
hw/watchdog/sbsa_gwdt.c | 15 ++++++++++++++-
19
3 files changed, 16 insertions(+), 3 deletions(-)
8
20
9
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
21
diff --git a/include/hw/watchdog/sbsa_gwdt.h b/include/hw/watchdog/sbsa_gwdt.h
10
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
11
Signed-off-by: Hao Wu <wuhaotsh@google.com>
12
Message-id: 20210108190945.949196-4-wuhaotsh@google.com
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>
16
---
17
docs/system/arm/nuvoton.rst | 2 +-
18
meson.build | 1 +
19
hw/adc/trace.h | 1 +
20
include/hw/adc/npcm7xx_adc.h | 69 ++++++
21
include/hw/arm/npcm7xx.h | 2 +
22
hw/adc/npcm7xx_adc.c | 301 ++++++++++++++++++++++++++
23
hw/arm/npcm7xx.c | 24 ++-
24
tests/qtest/npcm7xx_adc-test.c | 377 +++++++++++++++++++++++++++++++++
25
hw/adc/meson.build | 1 +
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
22
index XXXXXXX..XXXXXXX 100644
37
--- a/docs/system/arm/nuvoton.rst
23
--- a/include/hw/watchdog/sbsa_gwdt.h
38
+++ b/docs/system/arm/nuvoton.rst
24
+++ b/include/hw/watchdog/sbsa_gwdt.h
39
@@ -XXX,XX +XXX,XX @@ Supported devices
25
@@ -XXX,XX +XXX,XX @@
40
* Random Number Generator (RNG)
26
#define SBSA_GWDT_RMMIO_SIZE 0x1000
41
* USB host (USBH)
27
#define SBSA_GWDT_CMMIO_SIZE 0x1000
42
* GPIO controller
28
43
+ * Analog to Digital Converter (ADC)
29
-#define SBSA_TIMER_FREQ 62500000 /* Hz */
44
30
-
45
Missing devices
31
typedef struct SBSA_GWDTState {
46
---------------
32
/* <private> */
47
@@ -XXX,XX +XXX,XX @@ Missing devices
33
SysBusDevice parent_obj;
48
* USB device (USBD)
34
@@ -XXX,XX +XXX,XX @@ typedef struct SBSA_GWDTState {
49
* SMBus controller (SMBF)
35
qemu_irq irq;
50
* Peripheral SPI controller (PSPI)
36
51
- * Analog to Digital Converter (ADC)
37
QEMUTimer *timer;
52
* SD/MMC host
38
+ uint64_t freq;
53
* PECI interface
39
54
* Pulse Width Modulation (PWM)
40
uint32_t id;
55
diff --git a/meson.build b/meson.build
41
uint32_t wcs;
42
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
56
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
57
--- a/meson.build
44
--- a/hw/arm/sbsa-ref.c
58
+++ b/meson.build
45
+++ b/hw/arm/sbsa-ref.c
59
@@ -XXX,XX +XXX,XX @@ if have_system
46
@@ -XXX,XX +XXX,XX @@ static void create_wdt(const SBSAMachineState *sms)
60
'chardev',
47
SysBusDevice *s = SYS_BUS_DEVICE(dev);
61
'hw/9pfs',
48
int irq = sbsa_ref_irqmap[SBSA_GWDT_WS0];
62
'hw/acpi',
49
63
+ 'hw/adc',
50
+ qdev_prop_set_uint64(dev, "clock-frequency", SBSA_GTIMER_HZ);
64
'hw/alpha',
51
sysbus_realize_and_unref(s, &error_fatal);
65
'hw/arm',
52
sysbus_mmio_map(s, 0, rbase);
66
'hw/audio',
53
sysbus_mmio_map(s, 1, cbase);
67
diff --git a/hw/adc/trace.h b/hw/adc/trace.h
54
diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
68
new file mode 100644
55
index XXXXXXX..XXXXXXX 100644
69
index XXXXXXX..XXXXXXX
56
--- a/hw/watchdog/sbsa_gwdt.c
70
--- /dev/null
57
+++ b/hw/watchdog/sbsa_gwdt.c
71
+++ b/hw/adc/trace.h
72
@@ -0,0 +1 @@
73
+#include "trace/trace-hw_adc.h"
74
diff --git a/include/hw/adc/npcm7xx_adc.h b/include/hw/adc/npcm7xx_adc.h
75
new file mode 100644
76
index XXXXXXX..XXXXXXX
77
--- /dev/null
78
+++ b/include/hw/adc/npcm7xx_adc.h
79
@@ -XXX,XX +XXX,XX @@
58
@@ -XXX,XX +XXX,XX @@
80
+/*
59
#include "qemu/osdep.h"
81
+ * Nuvoton NPCM7xx ADC Module
60
#include "sysemu/reset.h"
82
+ *
61
#include "sysemu/watchdog.h"
83
+ * Copyright 2020 Google LLC
84
+ *
85
+ * This program is free software; you can redistribute it and/or modify it
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
+ *
90
+ * This program is distributed in the hope that it will be useful, but WITHOUT
91
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
92
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
93
+ * for more details.
94
+ */
95
+#ifndef NPCM7XX_ADC_H
96
+#define NPCM7XX_ADC_H
97
+
98
+#include "hw/clock.h"
99
+#include "hw/irq.h"
100
+#include "hw/sysbus.h"
101
+#include "qemu/timer.h"
102
+
103
+#define NPCM7XX_ADC_NUM_INPUTS 8
104
+/**
105
+ * This value should not be changed unless write_adc_calibration function in
106
+ * hw/arm/npcm7xx.c is also changed.
107
+ */
108
+#define NPCM7XX_ADC_NUM_CALIB 2
109
+
110
+/**
111
+ * struct NPCM7xxADCState - Analog to Digital Converter Module device state.
112
+ * @parent: System bus device.
113
+ * @iomem: Memory region through which registers are accessed.
114
+ * @conv_timer: The timer counts down remaining cycles for the conversion.
115
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
116
+ * @con: The Control Register.
117
+ * @data: The Data Buffer.
118
+ * @clock: The ADC Clock.
119
+ * @adci: The input voltage in units of uV. 1uv = 1e-6V.
120
+ * @vref: The external reference voltage.
121
+ * @iref: The internal reference voltage, initialized at launch time.
122
+ * @rv: The calibrated output values of 0.5V and 1.5V for the ADC.
123
+ */
124
+typedef struct {
125
+ SysBusDevice parent;
126
+
127
+ MemoryRegion iomem;
128
+
129
+ QEMUTimer conv_timer;
130
+
131
+ qemu_irq irq;
132
+ uint32_t con;
133
+ uint32_t data;
134
+ Clock *clock;
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
151
--- a/include/hw/arm/npcm7xx.h
152
+++ b/include/hw/arm/npcm7xx.h
153
@@ -XXX,XX +XXX,XX @@
154
#define NPCM7XX_H
155
156
#include "hw/boards.h"
157
+#include "hw/adc/npcm7xx_adc.h"
158
#include "hw/cpu/a9mpcore.h"
159
#include "hw/gpio/npcm7xx_gpio.h"
160
#include "hw/mem/npcm7xx_mc.h"
161
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
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"
62
+#include "hw/qdev-properties.h"
195
+#include "hw/registerfields.h"
63
#include "hw/watchdog/sbsa_gwdt.h"
196
+#include "migration/vmstate.h"
64
#include "qemu/timer.h"
197
+#include "qemu/log.h"
65
#include "migration/vmstate.h"
198
+#include "qemu/module.h"
66
@@ -XXX,XX +XXX,XX @@ static void sbsa_gwdt_update_timer(SBSA_GWDTState *s, WdtRefreshType rtype)
199
+#include "qemu/timer.h"
67
timeout = s->woru;
200
+#include "qemu/units.h"
68
timeout <<= 32;
201
+#include "trace.h"
69
timeout |= s->worl;
202
+
70
- timeout = muldiv64(timeout, NANOSECONDS_PER_SECOND, SBSA_TIMER_FREQ);
203
+REG32(NPCM7XX_ADC_CON, 0x0)
71
+ timeout = muldiv64(timeout, NANOSECONDS_PER_SECOND, s->freq);
204
+REG32(NPCM7XX_ADC_DATA, 0x4)
72
timeout += qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
205
+
73
206
+/* Register field definitions. */
74
if ((rtype == EXPLICIT_REFRESH) || ((rtype == TIMEOUT_REFRESH) &&
207
+#define NPCM7XX_ADC_CON_MUX(rv) extract32(rv, 24, 4)
75
@@ -XXX,XX +XXX,XX @@ static void wdt_sbsa_gwdt_realize(DeviceState *dev, Error **errp)
208
+#define NPCM7XX_ADC_CON_INT_EN BIT(21)
76
dev);
209
+#define NPCM7XX_ADC_CON_REFSEL BIT(19)
77
}
210
+#define NPCM7XX_ADC_CON_INT BIT(18)
78
211
+#define NPCM7XX_ADC_CON_EN BIT(17)
79
+static Property wdt_sbsa_gwdt_props[] = {
212
+#define NPCM7XX_ADC_CON_RST BIT(16)
80
+ /*
213
+#define NPCM7XX_ADC_CON_CONV BIT(14)
81
+ * Timer frequency in Hz. This must match the frequency used by
214
+#define NPCM7XX_ADC_CON_DIV(rv) extract32(rv, 1, 8)
82
+ * the CPU's generic timer. Default 62.5Hz matches QEMU's legacy
215
+
83
+ * CPU timer frequency default.
216
+#define NPCM7XX_ADC_MAX_RESULT 1023
84
+ */
217
+#define NPCM7XX_ADC_DEFAULT_IREF 2000000
85
+ DEFINE_PROP_UINT64("clock-frequency", struct SBSA_GWDTState, freq,
218
+#define NPCM7XX_ADC_CONV_CYCLES 20
86
+ 62500000),
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(),
87
+ DEFINE_PROP_END_OF_LIST(),
447
+};
88
+};
448
+
89
+
449
+static void npcm7xx_adc_class_init(ObjectClass *klass, void *data)
90
static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, void *data)
450
+{
91
{
451
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
92
DeviceClass *dc = DEVICE_CLASS(klass);
452
+ DeviceClass *dc = DEVICE_CLASS(klass);
93
@@ -XXX,XX +XXX,XX @@ static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, void *data)
453
+
94
set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);
454
+ dc->desc = "NPCM7xx ADC Module";
95
dc->vmsd = &vmstate_sbsa_gwdt;
455
+ dc->vmsd = &vmstate_npcm7xx_adc;
96
dc->desc = "SBSA-compliant generic watchdog device";
456
+ rc->phases.enter = npcm7xx_adc_enter_reset;
97
+ device_class_set_props(dc, wdt_sbsa_gwdt_props);
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
}
98
}
509
99
510
+static void npcm7xx_write_adc_calibration(NPCM7xxState *s)
100
static const TypeInfo wdt_sbsa_gwdt_info = {
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
--
101
--
969
2.20.1
102
2.34.1
970
103
971
104
diff view generated by jsdifflib
1
From: Leif Lindholm <leif@nuviainc.com>
1
In previous versions of the Arm architecture, the frequency of the
2
2
generic timers as reported in CNTFRQ_EL0 could be any IMPDEF value,
3
When FEAT_MTE is implemented, the AArch64 view of CTR_EL0 adds the
3
and for QEMU we picked 62.5MHz, giving a timer tick period of 16ns.
4
TminLine field in bits [37:32].
4
In Armv8.6, the architecture standardized this frequency to 1GHz.
5
Extend the ctr field to be able to hold this context.
5
6
6
Because there is no ID register feature field that indicates whether
7
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
7
a CPU is v8.6 or that it ought to have this counter frequency, we
8
Reviewed-by: Hao Wu <wuhaotsh@google.com>
8
implement this by changing our default CNTFRQ value for all CPUs,
9
with exceptions for backwards compatibility:
10
11
* CPU types which we already implement will retain the old
12
default value. None of these are v8.6 CPUs, so this is
13
architecturally OK.
14
* CPUs used in versioned machine types with a version of 9.0
15
or earlier will retain the old default value.
16
17
The upshot is that the only CPU type that changes is 'max'; but any
18
new type we add in future (whether v8.6 or not) will also get the new
19
1GHz default.
20
21
It remains the case that the machine model can override the default
22
value via the 'cntfrq' QOM property (regardless of the CPU type).
23
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
26
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Message-id: 20210108185154.8108-4-leif@nuviainc.com
27
Message-id: 20240426122913.3427983-5-peter.maydell@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
28
---
14
target/arm/cpu.h | 2 +-
29
target/arm/cpu.h | 11 +++++++++++
15
1 file changed, 1 insertion(+), 1 deletion(-)
30
target/arm/internals.h | 12 ++++++++++--
31
hw/core/machine.c | 4 +++-
32
target/arm/cpu.c | 23 +++++++++++++++++------
33
target/arm/cpu64.c | 2 ++
34
target/arm/tcg/cpu32.c | 4 ++++
35
target/arm/tcg/cpu64.c | 18 ++++++++++++++++++
36
7 files changed, 65 insertions(+), 9 deletions(-)
16
37
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
38
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.h
40
--- a/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
41
+++ b/target/arm/cpu.h
21
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
42
@@ -XXX,XX +XXX,XX @@ struct ArchCPU {
22
uint64_t midr;
43
*/
23
uint32_t revidr;
44
bool host_cpu_probe_failed;
24
uint32_t reset_fpsid;
45
25
- uint32_t ctr;
46
+ /* QOM property to indicate we should use the back-compat CNTFRQ default */
26
+ uint64_t ctr;
47
+ bool backcompat_cntfrq;
27
uint32_t reset_sctlr;
48
+
28
uint64_t pmceid0;
49
/* Specify the number of cores in this CPU cluster. Used for the L2CTLR
29
uint64_t pmceid1;
50
* register.
51
*/
52
@@ -XXX,XX +XXX,XX @@ enum arm_features {
53
ARM_FEATURE_M_SECURITY, /* M profile Security Extension */
54
ARM_FEATURE_M_MAIN, /* M profile Main Extension */
55
ARM_FEATURE_V8_1M, /* M profile extras only in v8.1M and later */
56
+ /*
57
+ * ARM_FEATURE_BACKCOMPAT_CNTFRQ makes the CPU default cntfrq be 62.5MHz
58
+ * if the board doesn't set a value, instead of 1GHz. It is for backwards
59
+ * compatibility and used only with CPU definitions that were already
60
+ * in QEMU before we changed the default. It should not be set on any
61
+ * CPU types added in future.
62
+ */
63
+ ARM_FEATURE_BACKCOMPAT_CNTFRQ, /* 62.5MHz timer default */
64
};
65
66
static inline int arm_feature(CPUARMState *env, int feature)
67
diff --git a/target/arm/internals.h b/target/arm/internals.h
68
index XXXXXXX..XXXXXXX 100644
69
--- a/target/arm/internals.h
70
+++ b/target/arm/internals.h
71
@@ -XXX,XX +XXX,XX @@ static inline bool excp_is_internal(int excp)
72
73
/*
74
* Default frequency for the generic timer, in Hz.
75
- * This is 62.5MHz, which gives a 16 ns tick period.
76
+ * ARMv8.6 and later CPUs architecturally must use a 1GHz timer; before
77
+ * that it was an IMPDEF choice, and QEMU initially picked 62.5MHz,
78
+ * which gives a 16ns tick period.
79
+ *
80
+ * We will use the back-compat value:
81
+ * - for QEMU CPU types added before we standardized on 1GHz
82
+ * - for versioned machine types with a version of 9.0 or earlier
83
+ * In any case, the machine model may override via the cntfrq property.
84
*/
85
-#define GTIMER_DEFAULT_HZ 62500000
86
+#define GTIMER_DEFAULT_HZ 1000000000
87
+#define GTIMER_BACKCOMPAT_HZ 62500000
88
89
/* Bit definitions for the v7M CONTROL register */
90
FIELD(V7M_CONTROL, NPRIV, 0, 1)
91
diff --git a/hw/core/machine.c b/hw/core/machine.c
92
index XXXXXXX..XXXXXXX 100644
93
--- a/hw/core/machine.c
94
+++ b/hw/core/machine.c
95
@@ -XXX,XX +XXX,XX @@
96
#include "hw/virtio/virtio-iommu.h"
97
#include "audio/audio.h"
98
99
-GlobalProperty hw_compat_9_0[] = {};
100
+GlobalProperty hw_compat_9_0[] = {
101
+ {"arm-cpu", "backcompat-cntfrq", "true" },
102
+};
103
const size_t hw_compat_9_0_len = G_N_ELEMENTS(hw_compat_9_0);
104
105
GlobalProperty hw_compat_8_2[] = {
106
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
107
index XXXXXXX..XXXXXXX 100644
108
--- a/target/arm/cpu.c
109
+++ b/target/arm/cpu.c
110
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
111
112
if (!cpu->gt_cntfrq_hz) {
113
/*
114
- * 0 means "the board didn't set a value, use the default".
115
- * The default value of the generic timer frequency (as seen in
116
- * CNTFRQ_EL0) is 62.5MHz, which corresponds to a period of 16ns.
117
- * This is what you get (a) for a CONFIG_USER_ONLY CPU (b) if the
118
- * board doesn't set it.
119
+ * 0 means "the board didn't set a value, use the default". (We also
120
+ * get here for the CONFIG_USER_ONLY case.)
121
+ * ARMv8.6 and later CPUs architecturally must use a 1GHz timer; before
122
+ * that it was an IMPDEF choice, and QEMU initially picked 62.5MHz,
123
+ * which gives a 16ns tick period.
124
+ *
125
+ * We will use the back-compat value:
126
+ * - for QEMU CPU types added before we standardized on 1GHz
127
+ * - for versioned machine types with a version of 9.0 or earlier
128
*/
129
- cpu->gt_cntfrq_hz = GTIMER_DEFAULT_HZ;
130
+ if (arm_feature(env, ARM_FEATURE_BACKCOMPAT_CNTFRQ) ||
131
+ cpu->backcompat_cntfrq) {
132
+ cpu->gt_cntfrq_hz = GTIMER_BACKCOMPAT_HZ;
133
+ } else {
134
+ cpu->gt_cntfrq_hz = GTIMER_DEFAULT_HZ;
135
+ }
136
}
137
138
#ifndef CONFIG_USER_ONLY
139
@@ -XXX,XX +XXX,XX @@ static Property arm_cpu_properties[] = {
140
mp_affinity, ARM64_AFFINITY_INVALID),
141
DEFINE_PROP_INT32("node-id", ARMCPU, node_id, CPU_UNSET_NUMA_NODE_ID),
142
DEFINE_PROP_INT32("core-count", ARMCPU, core_count, -1),
143
+ /* True to default to the backward-compat old CNTFRQ rather than 1Ghz */
144
+ DEFINE_PROP_BOOL("backcompat-cntfrq", ARMCPU, backcompat_cntfrq, false),
145
DEFINE_PROP_END_OF_LIST()
146
};
147
148
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
149
index XXXXXXX..XXXXXXX 100644
150
--- a/target/arm/cpu64.c
151
+++ b/target/arm/cpu64.c
152
@@ -XXX,XX +XXX,XX @@ static void aarch64_a57_initfn(Object *obj)
153
set_feature(&cpu->env, ARM_FEATURE_V8);
154
set_feature(&cpu->env, ARM_FEATURE_NEON);
155
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
156
+ set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
157
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
158
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
159
set_feature(&cpu->env, ARM_FEATURE_EL2);
160
@@ -XXX,XX +XXX,XX @@ static void aarch64_a53_initfn(Object *obj)
161
set_feature(&cpu->env, ARM_FEATURE_V8);
162
set_feature(&cpu->env, ARM_FEATURE_NEON);
163
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
164
+ set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
165
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
166
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
167
set_feature(&cpu->env, ARM_FEATURE_EL2);
168
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
169
index XXXXXXX..XXXXXXX 100644
170
--- a/target/arm/tcg/cpu32.c
171
+++ b/target/arm/tcg/cpu32.c
172
@@ -XXX,XX +XXX,XX @@ static void cortex_a7_initfn(Object *obj)
173
set_feature(&cpu->env, ARM_FEATURE_NEON);
174
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
175
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
176
+ set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
177
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
178
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
179
set_feature(&cpu->env, ARM_FEATURE_EL2);
180
@@ -XXX,XX +XXX,XX @@ static void cortex_a15_initfn(Object *obj)
181
set_feature(&cpu->env, ARM_FEATURE_NEON);
182
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
183
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
184
+ set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
185
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
186
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
187
set_feature(&cpu->env, ARM_FEATURE_EL2);
188
@@ -XXX,XX +XXX,XX @@ static void cortex_r52_initfn(Object *obj)
189
set_feature(&cpu->env, ARM_FEATURE_PMSA);
190
set_feature(&cpu->env, ARM_FEATURE_NEON);
191
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
192
+ set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
193
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
194
set_feature(&cpu->env, ARM_FEATURE_AUXCR);
195
cpu->midr = 0x411fd133; /* r1p3 */
196
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
197
set_feature(&cpu->env, ARM_FEATURE_V8);
198
set_feature(&cpu->env, ARM_FEATURE_NEON);
199
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
200
+ set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
201
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
202
set_feature(&cpu->env, ARM_FEATURE_EL2);
203
set_feature(&cpu->env, ARM_FEATURE_EL3);
204
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
205
index XXXXXXX..XXXXXXX 100644
206
--- a/target/arm/tcg/cpu64.c
207
+++ b/target/arm/tcg/cpu64.c
208
@@ -XXX,XX +XXX,XX @@ static void aarch64_a35_initfn(Object *obj)
209
set_feature(&cpu->env, ARM_FEATURE_V8);
210
set_feature(&cpu->env, ARM_FEATURE_NEON);
211
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
212
+ set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
213
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
214
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
215
set_feature(&cpu->env, ARM_FEATURE_EL2);
216
@@ -XXX,XX +XXX,XX @@ static void aarch64_a55_initfn(Object *obj)
217
set_feature(&cpu->env, ARM_FEATURE_V8);
218
set_feature(&cpu->env, ARM_FEATURE_NEON);
219
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
220
+ set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
221
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
222
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
223
set_feature(&cpu->env, ARM_FEATURE_EL2);
224
@@ -XXX,XX +XXX,XX @@ static void aarch64_a72_initfn(Object *obj)
225
set_feature(&cpu->env, ARM_FEATURE_V8);
226
set_feature(&cpu->env, ARM_FEATURE_NEON);
227
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
228
+ set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
229
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
230
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
231
set_feature(&cpu->env, ARM_FEATURE_EL2);
232
@@ -XXX,XX +XXX,XX @@ static void aarch64_a76_initfn(Object *obj)
233
set_feature(&cpu->env, ARM_FEATURE_V8);
234
set_feature(&cpu->env, ARM_FEATURE_NEON);
235
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
236
+ set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
237
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
238
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
239
set_feature(&cpu->env, ARM_FEATURE_EL2);
240
@@ -XXX,XX +XXX,XX @@ static void aarch64_a64fx_initfn(Object *obj)
241
set_feature(&cpu->env, ARM_FEATURE_V8);
242
set_feature(&cpu->env, ARM_FEATURE_NEON);
243
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
244
+ set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
245
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
246
set_feature(&cpu->env, ARM_FEATURE_EL2);
247
set_feature(&cpu->env, ARM_FEATURE_EL3);
248
@@ -XXX,XX +XXX,XX @@ static void aarch64_neoverse_n1_initfn(Object *obj)
249
set_feature(&cpu->env, ARM_FEATURE_V8);
250
set_feature(&cpu->env, ARM_FEATURE_NEON);
251
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
252
+ set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
253
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
254
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
255
set_feature(&cpu->env, ARM_FEATURE_EL2);
256
@@ -XXX,XX +XXX,XX @@ static void aarch64_neoverse_v1_initfn(Object *obj)
257
set_feature(&cpu->env, ARM_FEATURE_V8);
258
set_feature(&cpu->env, ARM_FEATURE_NEON);
259
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
260
+ set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
261
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
262
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
263
set_feature(&cpu->env, ARM_FEATURE_EL2);
264
@@ -XXX,XX +XXX,XX @@ static void aarch64_a710_initfn(Object *obj)
265
set_feature(&cpu->env, ARM_FEATURE_V8);
266
set_feature(&cpu->env, ARM_FEATURE_NEON);
267
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
268
+ set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
269
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
270
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
271
set_feature(&cpu->env, ARM_FEATURE_EL2);
272
@@ -XXX,XX +XXX,XX @@ static void aarch64_neoverse_n2_initfn(Object *obj)
273
set_feature(&cpu->env, ARM_FEATURE_V8);
274
set_feature(&cpu->env, ARM_FEATURE_NEON);
275
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
276
+ set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
277
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
278
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
279
set_feature(&cpu->env, ARM_FEATURE_EL2);
280
@@ -XXX,XX +XXX,XX @@ void aarch64_max_tcg_initfn(Object *obj)
281
uint64_t t;
282
uint32_t u;
283
284
+ /*
285
+ * Unset ARM_FEATURE_BACKCOMPAT_CNTFRQ, which we would otherwise default
286
+ * to because we started with aarch64_a57_initfn(). A 'max' CPU might
287
+ * be a v8.6-or-later one, in which case the cntfrq must be 1GHz; and
288
+ * because it is our "may change" CPU type we are OK with it not being
289
+ * backwards-compatible with how it worked in old QEMU.
290
+ */
291
+ unset_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
292
+
293
/*
294
* Reset MIDR so the guest doesn't mistake our 'max' CPU type for a real
295
* one and try to apply errata workarounds or use impdef features we
30
--
296
--
31
2.20.1
297
2.34.1
32
298
33
299
diff view generated by jsdifflib
1
From: Leif Lindholm <leif@nuviainc.com>
1
From: Alexandra Diupina <adiupina@astralinux.ru>
2
2
3
The AArch64 view of CLIDR_EL1 extends the ICB field to include also bit
3
The DMA descriptor structures for this device have
4
32, as well as adding a Ttype<n> field when FEAT_MTE is implemented.
4
a set of "address extension" fields which extend the 32
5
Extend the clidr field to be able to hold this context.
5
bit source addresses with an extra 16 bits to give a
6
48 bit address:
7
https://docs.amd.com/r/en-US/ug1085-zynq-ultrascale-trm/ADDR_EXT-Field
6
8
7
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
9
However, we misimplemented this address extension in several ways:
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
* we only extracted 12 bits of the extension fields, not 16
11
* we didn't shift the extension field up far enough
12
* we accidentally did the shift as 32-bit arithmetic, which
13
meant that we would have an overflow instead of setting
14
bits [47:32] of the resulting 64-bit address
15
16
Add a type cast and use extract64() instead of extract32()
17
to avoid integer overflow on addition. Fix bit fields
18
extraction according to documentation.
19
20
Found by Linux Verification Center (linuxtesting.org) with SVACE.
21
22
Cc: qemu-stable@nongnu.org
23
Fixes: d3c6369a96 ("introduce xlnx-dpdma")
24
Signed-off-by: Alexandra Diupina <adiupina@astralinux.ru>
25
Message-id: 20240428181131.23801-1-adiupina@astralinux.ru
26
[PMM: adjusted commit message]
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
27
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>
28
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
29
---
14
target/arm/cpu.h | 2 +-
30
hw/dma/xlnx_dpdma.c | 20 ++++++++++----------
15
1 file changed, 1 insertion(+), 1 deletion(-)
31
1 file changed, 10 insertions(+), 10 deletions(-)
16
32
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
33
diff --git a/hw/dma/xlnx_dpdma.c b/hw/dma/xlnx_dpdma.c
18
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.h
35
--- a/hw/dma/xlnx_dpdma.c
20
+++ b/target/arm/cpu.h
36
+++ b/hw/dma/xlnx_dpdma.c
21
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
37
@@ -XXX,XX +XXX,XX @@ static uint64_t xlnx_dpdma_desc_get_source_address(DPDMADescriptor *desc,
22
uint32_t id_afr0;
38
23
uint64_t id_aa64afr0;
39
switch (frag) {
24
uint64_t id_aa64afr1;
40
case 0:
25
- uint32_t clidr;
41
- addr = desc->source_address
26
+ uint64_t clidr;
42
- + (extract32(desc->address_extension, 16, 12) << 20);
27
uint64_t mp_affinity; /* MP ID without feature bits */
43
+ addr = (uint64_t)desc->source_address
28
/* The elements of this array are the CCSIDR values for each cache,
44
+ + (extract64(desc->address_extension, 16, 16) << 32);
29
* in the order L1DCache, L1ICache, L2DCache, L2ICache, etc.
45
break;
46
case 1:
47
- addr = desc->source_address2
48
- + (extract32(desc->address_extension_23, 0, 12) << 8);
49
+ addr = (uint64_t)desc->source_address2
50
+ + (extract64(desc->address_extension_23, 0, 16) << 32);
51
break;
52
case 2:
53
- addr = desc->source_address3
54
- + (extract32(desc->address_extension_23, 16, 12) << 20);
55
+ addr = (uint64_t)desc->source_address3
56
+ + (extract64(desc->address_extension_23, 16, 16) << 32);
57
break;
58
case 3:
59
- addr = desc->source_address4
60
- + (extract32(desc->address_extension_45, 0, 12) << 8);
61
+ addr = (uint64_t)desc->source_address4
62
+ + (extract64(desc->address_extension_45, 0, 16) << 32);
63
break;
64
case 4:
65
- addr = desc->source_address5
66
- + (extract32(desc->address_extension_45, 16, 12) << 20);
67
+ addr = (uint64_t)desc->source_address5
68
+ + (extract64(desc->address_extension_45, 16, 16) << 32);
69
break;
70
default:
71
addr = 0;
30
--
72
--
31
2.20.1
73
2.34.1
32
33
diff view generated by jsdifflib
1
From: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
Signed-off-by: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
3
"make check-qtest-aarch64" recently started failing on FreeBSD builds,
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
and valgrind on Linux also detected that there is something fishy with
5
the new stm32l4x5-usart: The code forgot to set the correct class_size
6
here, so the various class_init functions in this file wrote beyond
7
the allocated buffer when setting the subc->type field.
8
9
Fixes: 4fb37aea7e ("hw/char: Implement STM32L4x5 USART skeleton")
10
Signed-off-by: Thomas Huth <thuth@redhat.com>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
Message-id: 20240429075908.36302-1-thuth@redhat.com
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
---
14
---
7
target/arm/cpu64.c | 1 +
15
hw/char/stm32l4x5_usart.c | 1 +
8
1 file changed, 1 insertion(+)
16
1 file changed, 1 insertion(+)
9
17
10
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
18
diff --git a/hw/char/stm32l4x5_usart.c b/hw/char/stm32l4x5_usart.c
11
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
12
--- a/target/arm/cpu64.c
20
--- a/hw/char/stm32l4x5_usart.c
13
+++ b/target/arm/cpu64.c
21
+++ b/hw/char/stm32l4x5_usart.c
14
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
22
@@ -XXX,XX +XXX,XX @@ static const TypeInfo stm32l4x5_usart_types[] = {
15
t = cpu->isar.id_aa64mmfr2;
23
.parent = TYPE_SYS_BUS_DEVICE,
16
t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1);
24
.instance_size = sizeof(Stm32l4x5UsartBaseState),
17
t = FIELD_DP64(t, ID_AA64MMFR2, CNP, 1); /* TTCNP */
25
.instance_init = stm32l4x5_usart_base_init,
18
+ t = FIELD_DP64(t, ID_AA64MMFR2, ST, 1); /* TTST */
26
+ .class_size = sizeof(Stm32l4x5UsartBaseClass),
19
cpu->isar.id_aa64mmfr2 = t;
27
.class_init = stm32l4x5_usart_base_class_init,
20
28
.abstract = true,
21
/* Replicate the same data to the 32-bit id registers. */
29
}, {
22
--
30
--
23
2.20.1
31
2.34.1
24
32
25
33
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
This patch makes NPCM7XX Timer to use a the timer clock generated by the
3
Use little endian for derivative OTP fuse key.
4
CLK module instead of the magic number TIMER_REF_HZ.
5
4
6
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
5
Cc: qemu-stable@nongnu.org
7
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
6
Fixes: c752bb079b ("hw/nvram: NPCM7xx OTP device model")
8
Signed-off-by: Hao Wu <wuhaotsh@google.com>
7
Suggested-by: Avi Fishman <Avi.Fishman@nuvoton.com>
9
Message-id: 20210108190945.949196-3-wuhaotsh@google.com
8
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Message-id: 20240422125813.1403-1-philmd@linaro.org
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
12
---
13
include/hw/misc/npcm7xx_clk.h | 6 -----
13
hw/arm/npcm7xx.c | 3 ++-
14
include/hw/timer/npcm7xx_timer.h | 1 +
14
1 file changed, 2 insertions(+), 1 deletion(-)
15
hw/arm/npcm7xx.c | 5 ++++
16
hw/timer/npcm7xx_timer.c | 39 +++++++++++++++-----------------
17
4 files changed, 24 insertions(+), 27 deletions(-)
18
15
19
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/misc/npcm7xx_clk.h
22
+++ b/include/hw/misc/npcm7xx_clk.h
23
@@ -XXX,XX +XXX,XX @@
24
#include "hw/clock.h"
25
#include "hw/sysbus.h"
26
27
-/*
28
- * The reference clock frequency for the timer modules, and the SECCNT and
29
- * CNTR25M registers in this module, is always 25 MHz.
30
- */
31
-#define NPCM7XX_TIMER_REF_HZ (25000000)
32
-
33
/*
34
* Number of registers in our device state structure. Don't change this without
35
* incrementing the version_id in the vmstate.
36
diff --git a/include/hw/timer/npcm7xx_timer.h b/include/hw/timer/npcm7xx_timer.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/hw/timer/npcm7xx_timer.h
39
+++ b/include/hw/timer/npcm7xx_timer.h
40
@@ -XXX,XX +XXX,XX @@ struct NPCM7xxTimerCtrlState {
41
42
uint32_t tisr;
43
44
+ Clock *clock;
45
NPCM7xxTimer timer[NPCM7XX_TIMERS_PER_CTRL];
46
NPCM7xxWatchdogTimer watchdog_timer;
47
};
48
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
16
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
49
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/arm/npcm7xx.c
18
--- a/hw/arm/npcm7xx.c
51
+++ b/hw/arm/npcm7xx.c
19
+++ b/hw/arm/npcm7xx.c
52
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@
53
#include "hw/char/serial.h"
21
#include "hw/qdev-clock.h"
54
#include "hw/loader.h"
55
#include "hw/misc/unimp.h"
56
+#include "hw/qdev-clock.h"
57
#include "hw/qdev-properties.h"
22
#include "hw/qdev-properties.h"
58
#include "qapi/error.h"
23
#include "qapi/error.h"
24
+#include "qemu/bswap.h"
59
#include "qemu/units.h"
25
#include "qemu/units.h"
60
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
26
#include "sysemu/sysemu.h"
61
int first_irq;
27
#include "target/arm/cpu-qom.h"
62
int j;
28
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init_fuses(NPCM7xxState *s)
63
29
* The initial mask of disabled modules indicates the chip derivative (e.g.
64
+ /* Connect the timer clock. */
30
* NPCM750 or NPCM730).
65
+ qdev_connect_clock_in(DEVICE(&s->tim[i]), "clock", qdev_get_clock_out(
31
*/
66
+ DEVICE(&s->clk), "timer-clock"));
32
- value = tswap32(nc->disabled_modules);
67
+
33
+ value = cpu_to_le32(nc->disabled_modules);
68
sysbus_realize(sbd, &error_abort);
34
npcm7xx_otp_array_write(&s->fuse_array, &value, NPCM7XX_FUSE_DERIVATIVE,
69
sysbus_mmio_map(sbd, 0, npcm7xx_tim_addr[i]);
35
sizeof(value));
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
}
36
}
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
--
37
--
193
2.20.1
38
2.34.1
194
39
195
40
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
This device implements the IM120417002 colors shield v1.1 for Arduino
4
identical PWM modules. Each module contains 4 PWM entries. Each PWM has
4
(which relies on the DM163 8x3-channel led driving logic) and features
5
two outputs: frequency and duty_cycle. Both are computed using inputs
5
a simple display of an 8x8 RGB matrix. The columns of the matrix are
6
from software side.
6
driven by the DM163 and the rows are driven externally.
7
7
8
This module does not model detail pulse signals since it is expensive.
8
Acked-by: Alistair Francis <alistair.francis@wdc.com>
9
It also does not model interrupts and watchdogs that are dependant on
9
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
10
the detail models. The interfaces for these are left in the module so
10
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
11
that anyone in need for these functionalities can implement on their
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
own.
12
Message-id: 20240424200929.240921-2-ines.varhol@telecom-paris.fr
13
13
[PMM: updated to new reset hold method prototype]
14
The user can read the duty cycle and frequency using qom-get command.
15
16
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
17
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
18
Signed-off-by: Hao Wu <wuhaotsh@google.com>
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>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
15
---
23
docs/system/arm/nuvoton.rst | 2 +-
16
docs/system/arm/b-l475e-iot01a.rst | 3 +-
24
include/hw/arm/npcm7xx.h | 2 +
17
include/hw/display/dm163.h | 59 +++++
25
include/hw/misc/npcm7xx_pwm.h | 105 +++++++
18
hw/display/dm163.c | 349 +++++++++++++++++++++++++++++
26
hw/arm/npcm7xx.c | 26 +-
19
hw/display/Kconfig | 3 +
27
hw/misc/npcm7xx_pwm.c | 550 ++++++++++++++++++++++++++++++++++
20
hw/display/meson.build | 1 +
28
hw/misc/meson.build | 1 +
21
hw/display/trace-events | 14 ++
29
hw/misc/trace-events | 6 +
22
6 files changed, 428 insertions(+), 1 deletion(-)
30
7 files changed, 689 insertions(+), 3 deletions(-)
23
create mode 100644 include/hw/display/dm163.h
31
create mode 100644 include/hw/misc/npcm7xx_pwm.h
24
create mode 100644 hw/display/dm163.c
32
create mode 100644 hw/misc/npcm7xx_pwm.c
33
25
34
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
26
diff --git a/docs/system/arm/b-l475e-iot01a.rst b/docs/system/arm/b-l475e-iot01a.rst
35
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
36
--- a/docs/system/arm/nuvoton.rst
28
--- a/docs/system/arm/b-l475e-iot01a.rst
37
+++ b/docs/system/arm/nuvoton.rst
29
+++ b/docs/system/arm/b-l475e-iot01a.rst
38
@@ -XXX,XX +XXX,XX @@ Supported devices
30
@@ -XXX,XX +XXX,XX @@ USART, I2C, SPI, CAN and USB OTG, as well as a variety of sensors.
39
* USB host (USBH)
31
Supported devices
40
* GPIO controller
32
"""""""""""""""""
41
* Analog to Digital Converter (ADC)
33
42
+ * Pulse Width Modulation (PWM)
34
-Currently B-L475E-IOT01A machine's only supports the following devices:
35
+Currently B-L475E-IOT01A machines support the following devices:
36
37
- Cortex-M4F based STM32L4x5 SoC
38
- STM32L4x5 EXTI (Extended interrupts and events controller)
39
@@ -XXX,XX +XXX,XX @@ Currently B-L475E-IOT01A machine's only supports the following devices:
40
- STM32L4x5 RCC (Reset and clock control)
41
- STM32L4x5 GPIOs (General-purpose I/Os)
42
- STM32L4x5 USARTs, UARTs and LPUART (Serial ports)
43
+- optional 8x8 led display (based on DM163 driver)
43
44
44
Missing devices
45
Missing devices
45
---------------
46
"""""""""""""""
46
@@ -XXX,XX +XXX,XX @@ Missing devices
47
diff --git a/include/hw/display/dm163.h b/include/hw/display/dm163.h
47
* Peripheral SPI controller (PSPI)
48
* SD/MMC host
49
* PECI interface
50
- * Pulse Width Modulation (PWM)
51
* Tachometer
52
* PCI and PCIe root complex and bridges
53
* VDM and MCTP support
54
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.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
48
new file mode 100644
76
index XXXXXXX..XXXXXXX
49
index XXXXXXX..XXXXXXX
77
--- /dev/null
50
--- /dev/null
78
+++ b/include/hw/misc/npcm7xx_pwm.h
51
+++ b/include/hw/display/dm163.h
79
@@ -XXX,XX +XXX,XX @@
52
@@ -XXX,XX +XXX,XX @@
80
+/*
53
+/*
81
+ * Nuvoton NPCM7xx PWM Module
54
+ * QEMU DM163 8x3-channel constant current led driver
55
+ * driving columns of associated 8x8 RGB matrix.
82
+ *
56
+ *
83
+ * Copyright 2020 Google LLC
57
+ * Copyright (C) 2024 Samuel Tardieu <sam@rfc1149.net>
58
+ * Copyright (C) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
59
+ * Copyright (C) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
84
+ *
60
+ *
85
+ * This program is free software; you can redistribute it and/or modify it
61
+ * 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
+ *
90
+ * This program is distributed in the hope that it will be useful, but WITHOUT
91
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
92
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
93
+ * for more details.
94
+ */
62
+ */
95
+#ifndef NPCM7XX_PWM_H
63
+
96
+#define NPCM7XX_PWM_H
64
+#ifndef HW_DISPLAY_DM163_H
97
+
65
+#define HW_DISPLAY_DM163_H
98
+#include "hw/clock.h"
66
+
99
+#include "hw/sysbus.h"
67
+#include "qom/object.h"
100
+#include "hw/irq.h"
68
+#include "hw/qdev-core.h"
101
+
69
+
102
+/* Each PWM module holds 4 PWM channels. */
70
+#define TYPE_DM163 "dm163"
103
+#define NPCM7XX_PWM_PER_MODULE 4
71
+OBJECT_DECLARE_SIMPLE_TYPE(DM163State, DM163);
104
+
72
+
105
+/*
73
+#define RGB_MATRIX_NUM_ROWS 8
106
+ * Number of registers in one pwm module. Don't change this without increasing
74
+#define RGB_MATRIX_NUM_COLS 8
107
+ * the version_id in vmstate.
75
+#define DM163_NUM_LEDS (RGB_MATRIX_NUM_COLS * 3)
108
+ */
76
+/* The last row is filled with 0 (turned off row) */
109
+#define NPCM7XX_PWM_NR_REGS (0x54 / sizeof(uint32_t))
77
+#define COLOR_BUFFER_SIZE (RGB_MATRIX_NUM_ROWS + 1)
110
+
78
+
111
+/*
79
+typedef struct DM163State {
112
+ * The maximum duty values. Each duty unit represents 1/NPCM7XX_PWM_MAX_DUTY
80
+ DeviceState parent_obj;
113
+ * cycles. For example, if NPCM7XX_PWM_MAX_DUTY=1,000,000 and a PWM has a duty
81
+
114
+ * value of 100,000 the duty cycle for that PWM is 10%.
82
+ /* DM163 driver */
115
+ */
83
+ uint64_t bank0_shift_register[3];
116
+#define NPCM7XX_PWM_MAX_DUTY 1000000
84
+ uint64_t bank1_shift_register[3];
117
+
85
+ uint16_t latched_outputs[DM163_NUM_LEDS];
118
+typedef struct NPCM7xxPWMState NPCM7xxPWMState;
86
+ uint16_t outputs[DM163_NUM_LEDS];
119
+
87
+ qemu_irq sout;
120
+/**
88
+
121
+ * struct NPCM7xxPWM - The state of a single PWM channel.
89
+ uint8_t sin;
122
+ * @module: The PWM module that contains this channel.
90
+ uint8_t dck;
123
+ * @irq: GIC interrupt line to fire on expiration if enabled.
91
+ uint8_t rst_b;
124
+ * @running: Whether this PWM channel is generating output.
92
+ uint8_t lat_b;
125
+ * @inverted: Whether this PWM channel is inverted.
93
+ uint8_t selbk;
126
+ * @index: The index of this PWM channel.
94
+ uint8_t en_b;
127
+ * @cnr: The counter register.
95
+
128
+ * @cmr: The comparator register.
96
+ /* IM120417002 colors shield */
129
+ * @pdr: The data register.
97
+ uint8_t activated_rows;
130
+ * @pwdr: The watchdog register.
98
+
131
+ * @freq: The frequency of this PWM channel.
99
+ /* 8x8 RGB matrix */
132
+ * @duty: The duty cycle of this PWM channel. One unit represents
100
+ QemuConsole *console;
133
+ * 1/NPCM7XX_MAX_DUTY cycles.
101
+ uint8_t redraw;
134
+ */
102
+ /* Rows currently being displayed on the matrix. */
135
+typedef struct NPCM7xxPWM {
103
+ /* The last row is filled with 0 (turned off row) */
136
+ NPCM7xxPWMState *module;
104
+ uint32_t buffer[COLOR_BUFFER_SIZE][RGB_MATRIX_NUM_COLS];
137
+
105
+ uint8_t last_buffer_idx;
138
+ qemu_irq irq;
106
+ uint8_t buffer_idx_of_row[RGB_MATRIX_NUM_ROWS];
139
+
107
+ /* Used to simulate retinal persistence of rows */
140
+ bool running;
108
+ uint8_t row_persistence_delay[RGB_MATRIX_NUM_ROWS];
141
+ bool inverted;
109
+} DM163State;
142
+
110
+
143
+ uint8_t index;
111
+#endif /* HW_DISPLAY_DM163_H */
144
+ uint32_t cnr;
112
diff --git a/hw/display/dm163.c b/hw/display/dm163.c
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
+};
179
+
180
+#define TYPE_NPCM7XX_PWM "npcm7xx-pwm"
181
+#define NPCM7XX_PWM(obj) \
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
113
new file mode 100644
252
index XXXXXXX..XXXXXXX
114
index XXXXXXX..XXXXXXX
253
--- /dev/null
115
--- /dev/null
254
+++ b/hw/misc/npcm7xx_pwm.c
116
+++ b/hw/display/dm163.c
255
@@ -XXX,XX +XXX,XX @@
117
@@ -XXX,XX +XXX,XX @@
256
+/*
118
+/*
257
+ * Nuvoton NPCM7xx PWM Module
119
+ * QEMU DM163 8x3-channel constant current led driver
120
+ * driving columns of associated 8x8 RGB matrix.
258
+ *
121
+ *
259
+ * Copyright 2020 Google LLC
122
+ * Copyright (C) 2024 Samuel Tardieu <sam@rfc1149.net>
123
+ * Copyright (C) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
124
+ * Copyright (C) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
260
+ *
125
+ *
261
+ * This program is free software; you can redistribute it and/or modify it
126
+ * 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
+ *
266
+ * This program is distributed in the hope that it will be useful, but WITHOUT
267
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
268
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
269
+ * for more details.
270
+ */
127
+ */
271
+
128
+
129
+/*
130
+ * The reference used for the DM163 is the following :
131
+ * http://www.siti.com.tw/product/spec/LED/DM163.pdf
132
+ */
133
+
272
+#include "qemu/osdep.h"
134
+#include "qemu/osdep.h"
135
+#include "qapi/error.h"
136
+#include "migration/vmstate.h"
273
+#include "hw/irq.h"
137
+#include "hw/irq.h"
274
+#include "hw/qdev-clock.h"
275
+#include "hw/qdev-properties.h"
138
+#include "hw/qdev-properties.h"
276
+#include "hw/misc/npcm7xx_pwm.h"
139
+#include "hw/display/dm163.h"
277
+#include "hw/registerfields.h"
140
+#include "ui/console.h"
278
+#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"
141
+#include "trace.h"
285
+
142
+
286
+REG32(NPCM7XX_PWM_PPR, 0x00);
143
+#define LED_SQUARE_SIZE 100
287
+REG32(NPCM7XX_PWM_CSR, 0x04);
144
+/* Number of frames a row stays visible after being turned off. */
288
+REG32(NPCM7XX_PWM_PCR, 0x08);
145
+#define ROW_PERSISTENCE 3
289
+REG32(NPCM7XX_PWM_CNR0, 0x0c);
146
+#define TURNED_OFF_ROW (COLOR_BUFFER_SIZE - 1)
290
+REG32(NPCM7XX_PWM_CMR0, 0x10);
147
+
291
+REG32(NPCM7XX_PWM_PDR0, 0x14);
148
+static const VMStateDescription vmstate_dm163 = {
292
+REG32(NPCM7XX_PWM_CNR1, 0x18);
149
+ .name = TYPE_DM163,
293
+REG32(NPCM7XX_PWM_CMR1, 0x1c);
150
+ .version_id = 1,
294
+REG32(NPCM7XX_PWM_PDR1, 0x20);
151
+ .minimum_version_id = 1,
295
+REG32(NPCM7XX_PWM_CNR2, 0x24);
152
+ .fields = (const VMStateField[]) {
296
+REG32(NPCM7XX_PWM_CMR2, 0x28);
153
+ VMSTATE_UINT64_ARRAY(bank0_shift_register, DM163State, 3),
297
+REG32(NPCM7XX_PWM_PDR2, 0x2c);
154
+ VMSTATE_UINT64_ARRAY(bank1_shift_register, DM163State, 3),
298
+REG32(NPCM7XX_PWM_CNR3, 0x30);
155
+ VMSTATE_UINT16_ARRAY(latched_outputs, DM163State, DM163_NUM_LEDS),
299
+REG32(NPCM7XX_PWM_CMR3, 0x34);
156
+ VMSTATE_UINT16_ARRAY(outputs, DM163State, DM163_NUM_LEDS),
300
+REG32(NPCM7XX_PWM_PDR3, 0x38);
157
+ VMSTATE_UINT8(dck, DM163State),
301
+REG32(NPCM7XX_PWM_PIER, 0x3c);
158
+ VMSTATE_UINT8(en_b, DM163State),
302
+REG32(NPCM7XX_PWM_PIIR, 0x40);
159
+ VMSTATE_UINT8(lat_b, DM163State),
303
+REG32(NPCM7XX_PWM_PWDR0, 0x44);
160
+ VMSTATE_UINT8(rst_b, DM163State),
304
+REG32(NPCM7XX_PWM_PWDR1, 0x48);
161
+ VMSTATE_UINT8(selbk, DM163State),
305
+REG32(NPCM7XX_PWM_PWDR2, 0x4c);
162
+ VMSTATE_UINT8(sin, DM163State),
306
+REG32(NPCM7XX_PWM_PWDR3, 0x50);
163
+ VMSTATE_UINT8(activated_rows, DM163State),
307
+
164
+ VMSTATE_UINT32_2DARRAY(buffer, DM163State, COLOR_BUFFER_SIZE,
308
+/* Register field definitions. */
165
+ RGB_MATRIX_NUM_COLS),
309
+#define NPCM7XX_PPR(rv, index) extract32((rv), npcm7xx_ppr_base[index], 8)
166
+ VMSTATE_UINT8(last_buffer_idx, DM163State),
310
+#define NPCM7XX_CSR(rv, index) extract32((rv), npcm7xx_csr_base[index], 3)
167
+ VMSTATE_UINT8_ARRAY(buffer_idx_of_row, DM163State, RGB_MATRIX_NUM_ROWS),
311
+#define NPCM7XX_CH(rv, index) extract32((rv), npcm7xx_ch_base[index], 4)
168
+ VMSTATE_UINT8_ARRAY(row_persistence_delay, DM163State,
312
+#define NPCM7XX_CH_EN BIT(0)
169
+ RGB_MATRIX_NUM_ROWS),
313
+#define NPCM7XX_CH_INV BIT(2)
170
+ VMSTATE_END_OF_LIST()
314
+#define NPCM7XX_CH_MOD BIT(3)
171
+ }
315
+
172
+};
316
+/* Offset of each PWM channel's prescaler in the PPR register. */
173
+
317
+static const int npcm7xx_ppr_base[] = { 0, 0, 8, 8 };
174
+static void dm163_reset_hold(Object *obj, ResetType type)
318
+/* Offset of each PWM channel's clock selector in the CSR register. */
175
+{
319
+static const int npcm7xx_csr_base[] = { 0, 4, 8, 12 };
176
+ DM163State *s = DM163(obj);
320
+/* Offset of each PWM channel's control variable in the PCR register. */
177
+
321
+static const int npcm7xx_ch_base[] = { 0, 8, 12, 16 };
178
+ s->sin = 0;
322
+
179
+ s->dck = 0;
323
+static uint32_t npcm7xx_pwm_calculate_freq(NPCM7xxPWM *p)
180
+ s->rst_b = 0;
324
+{
181
+ /* Ensuring the first falling edge of lat_b isn't missed */
325
+ uint32_t ppr;
182
+ s->lat_b = 1;
326
+ uint32_t csr;
183
+ s->selbk = 0;
327
+ uint32_t freq;
184
+ s->en_b = 0;
328
+
185
+ /* Reset stops the PWM, not the shift and latched registers. */
329
+ if (!p->running) {
186
+ memset(s->outputs, 0, sizeof(s->outputs));
330
+ return 0;
187
+
331
+ }
188
+ s->activated_rows = 0;
332
+
189
+ s->redraw = 0;
333
+ csr = NPCM7XX_CSR(p->module->csr, p->index);
190
+ trace_dm163_redraw(s->redraw);
334
+ ppr = NPCM7XX_PPR(p->module->ppr, p->index);
191
+ for (unsigned i = 0; i < COLOR_BUFFER_SIZE; i++) {
335
+ freq = clock_get_hz(p->module->clock);
192
+ memset(s->buffer[i], 0, sizeof(s->buffer[0]));
336
+ freq /= ppr + 1;
193
+ }
337
+ /* csr can only be 0~4 */
194
+ s->last_buffer_idx = 0;
338
+ if (csr > 4) {
195
+ memset(s->buffer_idx_of_row, TURNED_OFF_ROW, sizeof(s->buffer_idx_of_row));
339
+ qemu_log_mask(LOG_GUEST_ERROR,
196
+ memset(s->row_persistence_delay, 0, sizeof(s->row_persistence_delay));
340
+ "%s: invalid csr value %u\n",
197
+}
341
+ __func__, csr);
198
+
342
+ csr = 4;
199
+static void dm163_dck_gpio_handler(void *opaque, int line, int new_state)
343
+ }
200
+{
344
+ /* freq won't be changed if csr == 4. */
201
+ DM163State *s = opaque;
345
+ if (csr < 4) {
202
+
346
+ freq >>= csr + 1;
203
+ if (new_state && !s->dck) {
347
+ }
204
+ /*
348
+
205
+ * On raising dck, sample selbk to get the bank to use, and
349
+ return freq / (p->cnr + 1);
206
+ * sample sin for the bit to enter into the bank shift buffer.
350
+}
207
+ */
351
+
208
+ uint64_t *sb =
352
+static uint32_t npcm7xx_pwm_calculate_duty(NPCM7xxPWM *p)
209
+ s->selbk ? s->bank1_shift_register : s->bank0_shift_register;
353
+{
210
+ /* Output the outgoing bit on sout */
354
+ uint64_t duty;
211
+ const bool sout = (s->selbk ? sb[2] & MAKE_64BIT_MASK(63, 1) :
355
+
212
+ sb[2] & MAKE_64BIT_MASK(15, 1)) != 0;
356
+ if (p->running) {
213
+ qemu_set_irq(s->sout, sout);
357
+ if (p->cnr == 0) {
214
+ /* Enter sin into the shift buffer */
358
+ duty = 0;
215
+ sb[2] = (sb[2] << 1) | ((sb[1] >> 63) & 1);
359
+ } else if (p->cmr >= p->cnr) {
216
+ sb[1] = (sb[1] << 1) | ((sb[0] >> 63) & 1);
360
+ duty = NPCM7XX_PWM_MAX_DUTY;
217
+ sb[0] = (sb[0] << 1) | s->sin;
361
+ } else {
218
+ }
362
+ duty = NPCM7XX_PWM_MAX_DUTY * (p->cmr + 1) / (p->cnr + 1);
219
+
220
+ s->dck = new_state;
221
+ trace_dm163_dck(new_state);
222
+}
223
+
224
+static void dm163_propagate_outputs(DM163State *s)
225
+{
226
+ s->last_buffer_idx = (s->last_buffer_idx + 1) % RGB_MATRIX_NUM_ROWS;
227
+ /* Values are output when reset is high and enable is low. */
228
+ if (s->rst_b && !s->en_b) {
229
+ memcpy(s->outputs, s->latched_outputs, sizeof(s->outputs));
230
+ } else {
231
+ memset(s->outputs, 0, sizeof(s->outputs));
232
+ }
233
+ for (unsigned x = 0; x < RGB_MATRIX_NUM_COLS; x++) {
234
+ /* Grouping the 3 RGB channels in a pixel value */
235
+ const uint16_t b = extract16(s->outputs[3 * x + 0], 6, 8);
236
+ const uint16_t g = extract16(s->outputs[3 * x + 1], 6, 8);
237
+ const uint16_t r = extract16(s->outputs[3 * x + 2], 6, 8);
238
+ uint32_t rgba = 0;
239
+
240
+ trace_dm163_channels(3 * x + 2, r);
241
+ trace_dm163_channels(3 * x + 1, g);
242
+ trace_dm163_channels(3 * x + 0, b);
243
+
244
+ rgba = deposit32(rgba, 0, 8, r);
245
+ rgba = deposit32(rgba, 8, 8, g);
246
+ rgba = deposit32(rgba, 16, 8, b);
247
+
248
+ /* Led values are sent from the last one to the first one */
249
+ s->buffer[s->last_buffer_idx][RGB_MATRIX_NUM_COLS - x - 1] = rgba;
250
+ }
251
+ for (unsigned row = 0; row < RGB_MATRIX_NUM_ROWS; row++) {
252
+ if (s->activated_rows & (1 << row)) {
253
+ s->buffer_idx_of_row[row] = s->last_buffer_idx;
254
+ s->redraw |= (1 << row);
255
+ trace_dm163_redraw(s->redraw);
363
+ }
256
+ }
257
+ }
258
+}
259
+
260
+static void dm163_en_b_gpio_handler(void *opaque, int line, int new_state)
261
+{
262
+ DM163State *s = opaque;
263
+
264
+ s->en_b = new_state;
265
+ dm163_propagate_outputs(s);
266
+ trace_dm163_en_b(new_state);
267
+}
268
+
269
+static uint8_t dm163_bank0(const DM163State *s, uint8_t led)
270
+{
271
+ /*
272
+ * Bank 0 uses 6 bits per led, so a value may be stored accross
273
+ * two uint64_t entries.
274
+ */
275
+ const uint8_t low_bit = 6 * led;
276
+ const uint8_t low_word = low_bit / 64;
277
+ const uint8_t high_word = (low_bit + 5) / 64;
278
+ const uint8_t low_shift = low_bit % 64;
279
+
280
+ if (low_word == high_word) {
281
+ /* Simple case: the value belongs to one entry. */
282
+ return extract64(s->bank0_shift_register[low_word], low_shift, 6);
283
+ }
284
+
285
+ const uint8_t nb_bits_in_low_word = 64 - low_shift;
286
+ const uint8_t nb_bits_in_high_word = 6 - nb_bits_in_low_word;
287
+
288
+ const uint64_t bits_in_low_word = \
289
+ extract64(s->bank0_shift_register[low_word], low_shift,
290
+ nb_bits_in_low_word);
291
+ const uint64_t bits_in_high_word = \
292
+ extract64(s->bank0_shift_register[high_word], 0,
293
+ nb_bits_in_high_word);
294
+ uint8_t val = 0;
295
+
296
+ val = deposit32(val, 0, nb_bits_in_low_word, bits_in_low_word);
297
+ val = deposit32(val, nb_bits_in_low_word, nb_bits_in_high_word,
298
+ bits_in_high_word);
299
+
300
+ return val;
301
+}
302
+
303
+static uint8_t dm163_bank1(const DM163State *s, uint8_t led)
304
+{
305
+ const uint64_t entry = s->bank1_shift_register[led / RGB_MATRIX_NUM_COLS];
306
+ return extract64(entry, 8 * (led % RGB_MATRIX_NUM_COLS), 8);
307
+}
308
+
309
+static void dm163_lat_b_gpio_handler(void *opaque, int line, int new_state)
310
+{
311
+ DM163State *s = opaque;
312
+
313
+ if (s->lat_b && !new_state) {
314
+ for (int led = 0; led < DM163_NUM_LEDS; led++) {
315
+ s->latched_outputs[led] = dm163_bank0(s, led) * dm163_bank1(s, led);
316
+ }
317
+ dm163_propagate_outputs(s);
318
+ }
319
+
320
+ s->lat_b = new_state;
321
+ trace_dm163_lat_b(new_state);
322
+}
323
+
324
+static void dm163_rst_b_gpio_handler(void *opaque, int line, int new_state)
325
+{
326
+ DM163State *s = opaque;
327
+
328
+ s->rst_b = new_state;
329
+ dm163_propagate_outputs(s);
330
+ trace_dm163_rst_b(new_state);
331
+}
332
+
333
+static void dm163_selbk_gpio_handler(void *opaque, int line, int new_state)
334
+{
335
+ DM163State *s = opaque;
336
+
337
+ s->selbk = new_state;
338
+ trace_dm163_selbk(new_state);
339
+}
340
+
341
+static void dm163_sin_gpio_handler(void *opaque, int line, int new_state)
342
+{
343
+ DM163State *s = opaque;
344
+
345
+ s->sin = new_state;
346
+ trace_dm163_sin(new_state);
347
+}
348
+
349
+static void dm163_rows_gpio_handler(void *opaque, int line, int new_state)
350
+{
351
+ DM163State *s = opaque;
352
+
353
+ if (new_state) {
354
+ s->activated_rows |= (1 << line);
355
+ s->buffer_idx_of_row[line] = s->last_buffer_idx;
356
+ s->redraw |= (1 << line);
357
+ trace_dm163_redraw(s->redraw);
364
+ } else {
358
+ } else {
365
+ duty = 0;
359
+ s->activated_rows &= ~(1 << line);
366
+ }
360
+ s->row_persistence_delay[line] = ROW_PERSISTENCE;
367
+
361
+ }
368
+ if (p->inverted) {
362
+ trace_dm163_activated_rows(s->activated_rows);
369
+ duty = NPCM7XX_PWM_MAX_DUTY - duty;
363
+}
370
+ }
364
+
371
+
365
+static void dm163_invalidate_display(void *opaque)
372
+ return duty;
366
+{
373
+}
367
+ DM163State *s = (DM163State *)opaque;
374
+
368
+ s->redraw = 0xFF;
375
+static void npcm7xx_pwm_update_freq(NPCM7xxPWM *p)
369
+ trace_dm163_redraw(s->redraw);
376
+{
370
+}
377
+ uint32_t freq = npcm7xx_pwm_calculate_freq(p);
371
+
378
+
372
+static void update_row_persistence_delay(DM163State *s, unsigned row)
379
+ if (freq != p->freq) {
373
+{
380
+ trace_npcm7xx_pwm_update_freq(DEVICE(p->module)->canonical_path,
374
+ if (s->row_persistence_delay[row]) {
381
+ p->index, p->freq, freq);
375
+ s->row_persistence_delay[row]--;
382
+ p->freq = freq;
376
+ } else {
383
+ }
377
+ /*
384
+}
378
+ * If the ROW_PERSISTENCE delay is up,
385
+
379
+ * the row is turned off.
386
+static void npcm7xx_pwm_update_duty(NPCM7xxPWM *p)
380
+ */
387
+{
381
+ s->buffer_idx_of_row[row] = TURNED_OFF_ROW;
388
+ uint32_t duty = npcm7xx_pwm_calculate_duty(p);
382
+ s->redraw |= (1 << row);
389
+
383
+ trace_dm163_redraw(s->redraw);
390
+ if (duty != p->duty) {
384
+ }
391
+ trace_npcm7xx_pwm_update_duty(DEVICE(p->module)->canonical_path,
385
+}
392
+ p->index, p->duty, duty);
386
+
393
+ p->duty = duty;
387
+static uint32_t *update_display_of_row(DM163State *s, uint32_t *dest,
394
+ }
388
+ unsigned row)
395
+}
389
+{
396
+
390
+ for (unsigned _ = 0; _ < LED_SQUARE_SIZE; _++) {
397
+static void npcm7xx_pwm_update_output(NPCM7xxPWM *p)
391
+ for (int x = 0; x < RGB_MATRIX_NUM_COLS * LED_SQUARE_SIZE; x++) {
398
+{
392
+ /* UI layer guarantees that there's 32 bits per pixel (Mar 2024) */
399
+ npcm7xx_pwm_update_freq(p);
393
+ *dest++ = s->buffer[s->buffer_idx_of_row[row]][x / LED_SQUARE_SIZE];
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
+ }
394
+ }
414
+ }
395
+ }
415
+}
396
+
416
+
397
+ dpy_gfx_update(s->console, 0, LED_SQUARE_SIZE * row,
417
+static void npcm7xx_pwm_write_csr(NPCM7xxPWMState *s, uint32_t new_csr)
398
+ RGB_MATRIX_NUM_COLS * LED_SQUARE_SIZE, LED_SQUARE_SIZE);
418
+{
399
+ s->redraw &= ~(1 << row);
419
+ int i;
400
+ trace_dm163_redraw(s->redraw);
420
+ uint32_t old_csr = s->csr;
401
+
421
+
402
+ return dest;
422
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_csr_base) != NPCM7XX_PWM_PER_MODULE);
403
+}
423
+ s->csr = new_csr;
404
+
424
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
405
+static void dm163_update_display(void *opaque)
425
+ if (NPCM7XX_CSR(old_csr, i) != NPCM7XX_CSR(new_csr, i)) {
406
+{
426
+ npcm7xx_pwm_update_freq(&s->pwm[i]);
407
+ DM163State *s = (DM163State *)opaque;
408
+ DisplaySurface *surface = qemu_console_surface(s->console);
409
+ uint32_t *dest;
410
+
411
+ dest = surface_data(surface);
412
+ for (unsigned row = 0; row < RGB_MATRIX_NUM_ROWS; row++) {
413
+ update_row_persistence_delay(s, row);
414
+ if (!extract8(s->redraw, row, 1)) {
415
+ dest += LED_SQUARE_SIZE * LED_SQUARE_SIZE * RGB_MATRIX_NUM_COLS;
416
+ continue;
427
+ }
417
+ }
428
+ }
418
+ dest = update_display_of_row(s, dest, row);
429
+}
419
+ }
430
+
420
+}
431
+static void npcm7xx_pwm_write_pcr(NPCM7xxPWMState *s, uint32_t new_pcr)
421
+
432
+{
422
+static const GraphicHwOps dm163_ops = {
433
+ int i;
423
+ .invalidate = dm163_invalidate_display,
434
+ bool inverted;
424
+ .gfx_update = dm163_update_display,
435
+ uint32_t pcr;
436
+ NPCM7xxPWM *p;
437
+
438
+ s->pcr = new_pcr;
439
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_ch_base) != NPCM7XX_PWM_PER_MODULE);
440
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
441
+ p = &s->pwm[i];
442
+ pcr = NPCM7XX_CH(new_pcr, i);
443
+ inverted = pcr & NPCM7XX_CH_INV;
444
+
445
+ /*
446
+ * We only run a PWM channel with toggle mode. Single-shot mode does not
447
+ * generate frequency and duty-cycle values.
448
+ */
449
+ if ((pcr & NPCM7XX_CH_EN) && (pcr & NPCM7XX_CH_MOD)) {
450
+ if (p->running) {
451
+ /* Re-run this PWM channel if inverted changed. */
452
+ if (p->inverted ^ inverted) {
453
+ p->inverted = inverted;
454
+ npcm7xx_pwm_update_duty(p);
455
+ }
456
+ } else {
457
+ /* Run this PWM channel. */
458
+ p->running = true;
459
+ p->inverted = inverted;
460
+ npcm7xx_pwm_update_output(p);
461
+ }
462
+ } else {
463
+ /* Clear this PWM channel. */
464
+ p->running = false;
465
+ p->inverted = inverted;
466
+ npcm7xx_pwm_update_output(p);
467
+ }
468
+ }
469
+
470
+}
471
+
472
+static hwaddr npcm7xx_cnr_index(hwaddr offset)
473
+{
474
+ switch (offset) {
475
+ case A_NPCM7XX_PWM_CNR0:
476
+ return 0;
477
+ case A_NPCM7XX_PWM_CNR1:
478
+ return 1;
479
+ case A_NPCM7XX_PWM_CNR2:
480
+ return 2;
481
+ case A_NPCM7XX_PWM_CNR3:
482
+ return 3;
483
+ default:
484
+ g_assert_not_reached();
485
+ }
486
+}
487
+
488
+static hwaddr npcm7xx_cmr_index(hwaddr offset)
489
+{
490
+ switch (offset) {
491
+ case A_NPCM7XX_PWM_CMR0:
492
+ return 0;
493
+ case A_NPCM7XX_PWM_CMR1:
494
+ return 1;
495
+ case A_NPCM7XX_PWM_CMR2:
496
+ return 2;
497
+ case A_NPCM7XX_PWM_CMR3:
498
+ return 3;
499
+ default:
500
+ g_assert_not_reached();
501
+ }
502
+}
503
+
504
+static hwaddr npcm7xx_pdr_index(hwaddr offset)
505
+{
506
+ switch (offset) {
507
+ case A_NPCM7XX_PWM_PDR0:
508
+ return 0;
509
+ case A_NPCM7XX_PWM_PDR1:
510
+ return 1;
511
+ case A_NPCM7XX_PWM_PDR2:
512
+ return 2;
513
+ case A_NPCM7XX_PWM_PDR3:
514
+ return 3;
515
+ default:
516
+ g_assert_not_reached();
517
+ }
518
+}
519
+
520
+static hwaddr npcm7xx_pwdr_index(hwaddr offset)
521
+{
522
+ switch (offset) {
523
+ case A_NPCM7XX_PWM_PWDR0:
524
+ return 0;
525
+ case A_NPCM7XX_PWM_PWDR1:
526
+ return 1;
527
+ case A_NPCM7XX_PWM_PWDR2:
528
+ return 2;
529
+ case A_NPCM7XX_PWM_PWDR3:
530
+ return 3;
531
+ default:
532
+ g_assert_not_reached();
533
+ }
534
+}
535
+
536
+static uint64_t npcm7xx_pwm_read(void *opaque, hwaddr offset, unsigned size)
537
+{
538
+ NPCM7xxPWMState *s = opaque;
539
+ uint64_t value = 0;
540
+
541
+ switch (offset) {
542
+ case A_NPCM7XX_PWM_CNR0:
543
+ case A_NPCM7XX_PWM_CNR1:
544
+ case A_NPCM7XX_PWM_CNR2:
545
+ case A_NPCM7XX_PWM_CNR3:
546
+ value = s->pwm[npcm7xx_cnr_index(offset)].cnr;
547
+ break;
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:
591
+ qemu_log_mask(LOG_GUEST_ERROR,
592
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
593
+ __func__, offset);
594
+ break;
595
+ }
596
+
597
+ trace_npcm7xx_pwm_read(DEVICE(s)->canonical_path, offset, value);
598
+ return value;
599
+}
600
+
601
+static void npcm7xx_pwm_write(void *opaque, hwaddr offset,
602
+ uint64_t v, unsigned size)
603
+{
604
+ NPCM7xxPWMState *s = opaque;
605
+ NPCM7xxPWM *p;
606
+ uint32_t value = v;
607
+
608
+ trace_npcm7xx_pwm_write(DEVICE(s)->canonical_path, offset, value);
609
+ switch (offset) {
610
+ case A_NPCM7XX_PWM_CNR0:
611
+ case A_NPCM7XX_PWM_CNR1:
612
+ case A_NPCM7XX_PWM_CNR2:
613
+ case A_NPCM7XX_PWM_CNR3:
614
+ p = &s->pwm[npcm7xx_cnr_index(offset)];
615
+ p->cnr = value;
616
+ npcm7xx_pwm_update_output(p);
617
+ break;
618
+
619
+ case A_NPCM7XX_PWM_CMR0:
620
+ case A_NPCM7XX_PWM_CMR1:
621
+ case A_NPCM7XX_PWM_CMR2:
622
+ case A_NPCM7XX_PWM_CMR3:
623
+ p = &s->pwm[npcm7xx_cmr_index(offset)];
624
+ p->cmr = value;
625
+ npcm7xx_pwm_update_output(p);
626
+ break;
627
+
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:
671
+ qemu_log_mask(LOG_GUEST_ERROR,
672
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
673
+ __func__, offset);
674
+ break;
675
+ }
676
+}
677
+
678
+static const struct MemoryRegionOps npcm7xx_pwm_ops = {
679
+ .read = npcm7xx_pwm_read,
680
+ .write = npcm7xx_pwm_write,
681
+ .endianness = DEVICE_LITTLE_ENDIAN,
682
+ .valid = {
683
+ .min_access_size = 4,
684
+ .max_access_size = 4,
685
+ .unaligned = false,
686
+ },
687
+};
425
+};
688
+
426
+
689
+static void npcm7xx_pwm_enter_reset(Object *obj, ResetType type)
427
+static void dm163_realize(DeviceState *dev, Error **errp)
690
+{
428
+{
691
+ NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
429
+ DM163State *s = DM163(dev);
692
+ int i;
430
+
693
+
431
+ qdev_init_gpio_in(dev, dm163_rows_gpio_handler, RGB_MATRIX_NUM_ROWS);
694
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
432
+ qdev_init_gpio_in(dev, dm163_sin_gpio_handler, 1);
695
+ NPCM7xxPWM *p = &s->pwm[i];
433
+ qdev_init_gpio_in(dev, dm163_dck_gpio_handler, 1);
696
+
434
+ qdev_init_gpio_in(dev, dm163_rst_b_gpio_handler, 1);
697
+ p->cnr = 0x00000000;
435
+ qdev_init_gpio_in(dev, dm163_lat_b_gpio_handler, 1);
698
+ p->cmr = 0x00000000;
436
+ qdev_init_gpio_in(dev, dm163_selbk_gpio_handler, 1);
699
+ p->pdr = 0x00000000;
437
+ qdev_init_gpio_in(dev, dm163_en_b_gpio_handler, 1);
700
+ p->pwdr = 0x00000000;
438
+ qdev_init_gpio_out_named(dev, &s->sout, "sout", 1);
701
+ }
439
+
702
+
440
+ s->console = graphic_console_init(dev, 0, &dm163_ops, s);
703
+ s->ppr = 0x00000000;
441
+ qemu_console_resize(s->console, RGB_MATRIX_NUM_COLS * LED_SQUARE_SIZE,
704
+ s->csr = 0x00000000;
442
+ RGB_MATRIX_NUM_ROWS * LED_SQUARE_SIZE);
705
+ s->pcr = 0x00000000;
443
+}
706
+ s->pier = 0x00000000;
444
+
707
+ s->piir = 0x00000000;
445
+static void dm163_class_init(ObjectClass *klass, void *data)
708
+}
446
+{
709
+
447
+ DeviceClass *dc = DEVICE_CLASS(klass);
710
+static void npcm7xx_pwm_hold_reset(Object *obj)
448
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
711
+{
449
+
712
+ NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
450
+ dc->desc = "DM163";
713
+ int i;
451
+ dc->vmsd = &vmstate_dm163;
714
+
452
+ dc->realize = dm163_realize;
715
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
453
+ rc->phases.hold = dm163_reset_hold;
716
+ qemu_irq_lower(s->pwm[i].irq);
454
+ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
717
+ }
455
+}
718
+}
456
+
719
+
457
+static const TypeInfo dm163_types[] = {
720
+static void npcm7xx_pwm_init(Object *obj)
458
+ {
721
+{
459
+ .name = TYPE_DM163,
722
+ NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
460
+ .parent = TYPE_DEVICE,
723
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
461
+ .instance_size = sizeof(DM163State),
724
+ int i;
462
+ .class_init = dm163_class_init
725
+
463
+ }
726
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
727
+ NPCM7xxPWM *p = &s->pwm[i];
728
+ p->module = s;
729
+ p->index = i;
730
+ sysbus_init_irq(sbd, &p->irq);
731
+ }
732
+
733
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_pwm_ops, s,
734
+ TYPE_NPCM7XX_PWM, 4 * KiB);
735
+ sysbus_init_mmio(sbd, &s->iomem);
736
+ s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL);
737
+
738
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
739
+ object_property_add_uint32_ptr(obj, "freq[*]",
740
+ &s->pwm[i].freq, OBJ_PROP_FLAG_READ);
741
+ object_property_add_uint32_ptr(obj, "duty[*]",
742
+ &s->pwm[i].duty, OBJ_PROP_FLAG_READ);
743
+ }
744
+}
745
+
746
+static const VMStateDescription vmstate_npcm7xx_pwm = {
747
+ .name = "npcm7xx-pwm",
748
+ .version_id = 0,
749
+ .minimum_version_id = 0,
750
+ .fields = (VMStateField[]) {
751
+ VMSTATE_BOOL(running, NPCM7xxPWM),
752
+ VMSTATE_BOOL(inverted, NPCM7xxPWM),
753
+ VMSTATE_UINT8(index, NPCM7xxPWM),
754
+ VMSTATE_UINT32(cnr, NPCM7xxPWM),
755
+ VMSTATE_UINT32(cmr, NPCM7xxPWM),
756
+ VMSTATE_UINT32(pdr, NPCM7xxPWM),
757
+ VMSTATE_UINT32(pwdr, NPCM7xxPWM),
758
+ VMSTATE_UINT32(freq, NPCM7xxPWM),
759
+ VMSTATE_UINT32(duty, NPCM7xxPWM),
760
+ VMSTATE_END_OF_LIST(),
761
+ },
762
+};
464
+};
763
+
465
+
764
+static const VMStateDescription vmstate_npcm7xx_pwm_module = {
466
+DEFINE_TYPES(dm163_types)
765
+ .name = "npcm7xx-pwm-module",
467
diff --git a/hw/display/Kconfig b/hw/display/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
468
index XXXXXXX..XXXXXXX 100644
808
--- a/hw/misc/meson.build
469
--- a/hw/display/Kconfig
809
+++ b/hw/misc/meson.build
470
+++ b/hw/display/Kconfig
810
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c'))
471
@@ -XXX,XX +XXX,XX @@ config XLNX_DISPLAYPORT
811
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
472
bool
812
'npcm7xx_clk.c',
473
# defaults to "N", enabled by specific boards
813
'npcm7xx_gcr.c',
474
depends on PIXMAN
814
+ 'npcm7xx_pwm.c',
475
+
815
'npcm7xx_rng.c',
476
+config DM163
816
))
477
+ bool
817
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files(
478
diff --git a/hw/display/meson.build b/hw/display/meson.build
818
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
819
index XXXXXXX..XXXXXXX 100644
479
index XXXXXXX..XXXXXXX 100644
820
--- a/hw/misc/trace-events
480
--- a/hw/display/meson.build
821
+++ b/hw/misc/trace-events
481
+++ b/hw/display/meson.build
822
@@ -XXX,XX +XXX,XX @@ npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " valu
482
@@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_NEXTCUBE', if_true: files('next-fb.c'))
823
npcm7xx_rng_read(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
483
824
npcm7xx_rng_write(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
484
system_ss.add(when: 'CONFIG_VGA', if_true: files('vga.c'))
825
485
system_ss.add(when: 'CONFIG_VIRTIO', if_true: files('virtio-dmabuf.c'))
826
+# npcm7xx_pwm.c
486
+system_ss.add(when: 'CONFIG_DM163', if_true: files('dm163.c'))
827
+npcm7xx_pwm_read(const char *id, uint64_t offset, uint32_t value) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
487
828
+npcm7xx_pwm_write(const char *id, uint64_t offset, uint32_t value) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
488
if (config_all_devices.has_key('CONFIG_VGA_CIRRUS') or
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"
489
config_all_devices.has_key('CONFIG_VGA_PCI') or
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"
490
diff --git a/hw/display/trace-events b/hw/display/trace-events
831
+
491
index XXXXXXX..XXXXXXX 100644
832
# stm32f4xx_syscfg.c
492
--- a/hw/display/trace-events
833
stm32f4xx_syscfg_set_irq(int gpio, int line, int level) "Interupt: GPIO: %d, Line: %d; Level: %d"
493
+++ b/hw/display/trace-events
834
stm32f4xx_pulse_exti(int irq) "Pulse EXTI: %d"
494
@@ -XXX,XX +XXX,XX @@ macfb_ctrl_write(uint64_t addr, uint64_t value, unsigned int size) "addr 0x%"PRI
495
macfb_sense_read(uint32_t value) "video sense: 0x%"PRIx32
496
macfb_sense_write(uint32_t value) "video sense: 0x%"PRIx32
497
macfb_update_mode(uint32_t width, uint32_t height, uint8_t depth) "setting mode to width %"PRId32 " height %"PRId32 " size %d"
498
+
499
+# dm163.c
500
+dm163_redraw(uint8_t redraw) "0x%02x"
501
+dm163_dck(unsigned new_state) "dck : %u"
502
+dm163_en_b(unsigned new_state) "en_b : %u"
503
+dm163_rst_b(unsigned new_state) "rst_b : %u"
504
+dm163_lat_b(unsigned new_state) "lat_b : %u"
505
+dm163_sin(unsigned new_state) "sin : %u"
506
+dm163_selbk(unsigned new_state) "selbk : %u"
507
+dm163_activated_rows(int new_state) "Activated rows : 0x%" PRIx32 ""
508
+dm163_bits_ppi(unsigned dest_width) "dest_width : %u"
509
+dm163_leds(int led, uint32_t value) "led %d: 0x%x"
510
+dm163_channels(int channel, uint8_t value) "channel %d: 0x%x"
511
+dm163_refresh_rate(uint32_t rr) "refresh rate %d"
835
--
512
--
836
2.20.1
513
2.34.1
837
514
838
515
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
Exposing SYSCFG inputs to the SoC is practical in order to wire the SoC
4
[-Wdeprecated-declarations]
4
to the optional DM163 display from the board code (GPIOs outputs need
5
if ([[NSWorkspace sharedWorkspace] openFile: full_file_path] == YES) {
5
to be connected to both SYSCFG inputs and DM163 inputs).
6
^
7
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSWorkspace.h:350:1: note:
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
6
12
Signed-off-by: Roman Bolshakov <r.bolshakov@yadro.com>
7
STM32L4x5 SYSCFG in-irq interception needed to be changed accordingly.
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
14
Message-id: 20210102150718.47618-1-r.bolshakov@yadro.com
9
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
10
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
Message-id: 20240424200929.240921-3-ines.varhol@telecom-paris.fr
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
14
---
17
ui/cocoa.m | 5 ++++-
15
hw/arm/stm32l4x5_soc.c | 6 ++++--
18
1 file changed, 4 insertions(+), 1 deletion(-)
16
tests/qtest/stm32l4x5_gpio-test.c | 13 ++++++++-----
17
tests/qtest/stm32l4x5_syscfg-test.c | 17 ++++++++++-------
18
3 files changed, 22 insertions(+), 14 deletions(-)
19
19
20
diff --git a/ui/cocoa.m b/ui/cocoa.m
20
diff --git a/hw/arm/stm32l4x5_soc.c b/hw/arm/stm32l4x5_soc.c
21
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
22
--- a/ui/cocoa.m
22
--- a/hw/arm/stm32l4x5_soc.c
23
+++ b/ui/cocoa.m
23
+++ b/hw/arm/stm32l4x5_soc.c
24
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
24
@@ -XXX,XX +XXX,XX @@
25
/* Where to look for local files */
25
/*
26
NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"docs/"};
26
* STM32L4x5 SoC family
27
NSString *full_file_path;
27
*
28
+ NSURL *full_file_url;
28
- * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
29
29
- * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
30
/* iterate thru the possible paths until the file is found */
30
+ * Copyright (c) 2023-2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
31
int index;
31
+ * Copyright (c) 2023-2024 Inès Varhol <ines.varhol@telecom-paris.fr>
32
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
32
*
33
full_file_path = [full_file_path stringByDeletingLastPathComponent];
33
* SPDX-License-Identifier: GPL-2.0-or-later
34
full_file_path = [NSString stringWithFormat: @"%@/%@%@", full_file_path,
34
*
35
path_array[index], filename];
35
@@ -XXX,XX +XXX,XX @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
36
- if ([[NSWorkspace sharedWorkspace] openFile: full_file_path] == YES) {
37
+ full_file_url = [NSURL fileURLWithPath: full_file_path
38
+ isDirectory: false];
39
+ if ([[NSWorkspace sharedWorkspace] openURL: full_file_url] == YES) {
40
return;
41
}
36
}
42
}
37
}
38
39
+ qdev_pass_gpios(DEVICE(&s->syscfg), dev_soc, NULL);
40
+
41
/* EXTI device */
42
busdev = SYS_BUS_DEVICE(&s->exti);
43
if (!sysbus_realize(busdev, errp)) {
44
diff --git a/tests/qtest/stm32l4x5_gpio-test.c b/tests/qtest/stm32l4x5_gpio-test.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/tests/qtest/stm32l4x5_gpio-test.c
47
+++ b/tests/qtest/stm32l4x5_gpio-test.c
48
@@ -XXX,XX +XXX,XX @@
49
#define OTYPER_PUSH_PULL 0
50
#define OTYPER_OPEN_DRAIN 1
51
52
+/* SoC forwards GPIOs to SysCfg */
53
+#define SYSCFG "/machine/soc"
54
+
55
const uint32_t moder_reset[NUM_GPIOS] = {
56
0xABFFFFFF,
57
0xFFFFFEBF,
58
@@ -XXX,XX +XXX,XX @@ static void test_gpio_output_mode(const void *data)
59
uint32_t gpio = test_gpio_addr(data);
60
unsigned int gpio_id = get_gpio_id(gpio);
61
62
- qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
63
+ qtest_irq_intercept_in(global_qtest, SYSCFG);
64
65
/* Set a bit in ODR and check nothing happens */
66
gpio_set_bit(gpio, ODR, pin, 1);
67
@@ -XXX,XX +XXX,XX @@ static void test_gpio_input_mode(const void *data)
68
uint32_t gpio = test_gpio_addr(data);
69
unsigned int gpio_id = get_gpio_id(gpio);
70
71
- qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
72
+ qtest_irq_intercept_in(global_qtest, SYSCFG);
73
74
/* Configure a line as input, raise it, and check that the pin is high */
75
gpio_set_2bits(gpio, MODER, pin, MODER_INPUT);
76
@@ -XXX,XX +XXX,XX @@ static void test_pull_up_pull_down(const void *data)
77
uint32_t gpio = test_gpio_addr(data);
78
unsigned int gpio_id = get_gpio_id(gpio);
79
80
- qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
81
+ qtest_irq_intercept_in(global_qtest, SYSCFG);
82
83
/* Configure a line as input with pull-up, check the line is set high */
84
gpio_set_2bits(gpio, MODER, pin, MODER_INPUT);
85
@@ -XXX,XX +XXX,XX @@ static void test_push_pull(const void *data)
86
uint32_t gpio = test_gpio_addr(data);
87
uint32_t gpio2 = GPIO_BASE_ADDR + (GPIO_H - gpio);
88
89
- qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
90
+ qtest_irq_intercept_in(global_qtest, SYSCFG);
91
92
/* Setting a line high externally, configuring it in push-pull output */
93
/* And checking the pin was disconnected */
94
@@ -XXX,XX +XXX,XX @@ static void test_open_drain(const void *data)
95
uint32_t gpio = test_gpio_addr(data);
96
uint32_t gpio2 = GPIO_BASE_ADDR + (GPIO_H - gpio);
97
98
- qtest_irq_intercept_in(global_qtest, "/machine/soc/syscfg");
99
+ qtest_irq_intercept_in(global_qtest, SYSCFG);
100
101
/* Setting a line high externally, configuring it in open-drain output */
102
/* And checking the pin was disconnected */
103
diff --git a/tests/qtest/stm32l4x5_syscfg-test.c b/tests/qtest/stm32l4x5_syscfg-test.c
104
index XXXXXXX..XXXXXXX 100644
105
--- a/tests/qtest/stm32l4x5_syscfg-test.c
106
+++ b/tests/qtest/stm32l4x5_syscfg-test.c
107
@@ -XXX,XX +XXX,XX @@
108
/*
109
* QTest testcase for STM32L4x5_SYSCFG
110
*
111
- * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
112
- * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
113
+ * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
114
+ * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
115
*
116
* This work is licensed under the terms of the GNU GPL, version 2 or later.
117
* See the COPYING file in the top-level directory.
118
@@ -XXX,XX +XXX,XX @@
119
#define SYSCFG_SWPR2 0x28
120
#define INVALID_ADDR 0x2C
121
122
+/* SoC forwards GPIOs to SysCfg */
123
+#define SYSCFG "/machine/soc"
124
+#define EXTI "/machine/soc/exti"
125
+
126
static void syscfg_writel(unsigned int offset, uint32_t value)
127
{
128
writel(SYSCFG_BASE_ADDR + offset, value);
129
@@ -XXX,XX +XXX,XX @@ static uint32_t syscfg_readl(unsigned int offset)
130
131
static void syscfg_set_irq(int num, int level)
132
{
133
- qtest_set_irq_in(global_qtest, "/machine/soc/syscfg",
134
- NULL, num, level);
135
+ qtest_set_irq_in(global_qtest, SYSCFG, NULL, num, level);
136
}
137
138
static void system_reset(void)
139
@@ -XXX,XX +XXX,XX @@ static void test_interrupt(void)
140
* Test that GPIO rising lines result in an irq
141
* with the right configuration
142
*/
143
- qtest_irq_intercept_in(global_qtest, "/machine/soc/exti");
144
+ qtest_irq_intercept_in(global_qtest, EXTI);
145
146
/* GPIOA is the default source for EXTI lines 0 to 15 */
147
148
@@ -XXX,XX +XXX,XX @@ static void test_irq_pin_multiplexer(void)
149
* Test that syscfg irq sets the right exti irq
150
*/
151
152
- qtest_irq_intercept_in(global_qtest, "/machine/soc/exti");
153
+ qtest_irq_intercept_in(global_qtest, EXTI);
154
155
syscfg_set_irq(0, 1);
156
157
@@ -XXX,XX +XXX,XX @@ static void test_irq_gpio_multiplexer(void)
158
* Test that an irq is generated only by the right GPIO
159
*/
160
161
- qtest_irq_intercept_in(global_qtest, "/machine/soc/exti");
162
+ qtest_irq_intercept_in(global_qtest, EXTI);
163
164
/* GPIOA is the default source for EXTI lines 0 to 15 */
165
43
--
166
--
44
2.20.1
167
2.34.1
45
168
46
169
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
A device shouldn't access its parent object which is QOM internal.
3
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
4
Instead it should use type cast for this purporse. This patch fixes this
4
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
5
issue for all NPCM7XX Devices.
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
6
Message-id: 20240424200929.240921-4-ines.varhol@telecom-paris.fr
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>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
8
---
12
hw/arm/npcm7xx_boards.c | 2 +-
9
hw/arm/b-l475e-iot01a.c | 46 ++++++++++++++++++++++++++++-------------
13
hw/mem/npcm7xx_mc.c | 2 +-
10
1 file changed, 32 insertions(+), 14 deletions(-)
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
11
21
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
12
diff --git a/hw/arm/b-l475e-iot01a.c b/hw/arm/b-l475e-iot01a.c
22
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/npcm7xx_boards.c
14
--- a/hw/arm/b-l475e-iot01a.c
24
+++ b/hw/arm/npcm7xx_boards.c
15
+++ b/hw/arm/b-l475e-iot01a.c
25
@@ -XXX,XX +XXX,XX @@ static NPCM7xxState *npcm7xx_create_soc(MachineState *machine,
16
@@ -XXX,XX +XXX,XX @@
26
uint32_t hw_straps)
17
* B-L475E-IOT01A Discovery Kit machine
18
* (B-L475E-IOT01A IoT Node)
19
*
20
- * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
21
- * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
22
+ * Copyright (c) 2023-2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
23
+ * Copyright (c) 2023-2024 Inès Varhol <ines.varhol@telecom-paris.fr>
24
*
25
* SPDX-License-Identifier: GPL-2.0-or-later
26
*
27
@@ -XXX,XX +XXX,XX @@
28
29
/* B-L475E-IOT01A implementation is derived from netduinoplus2 */
30
31
-static void b_l475e_iot01a_init(MachineState *machine)
32
+#define TYPE_B_L475E_IOT01A MACHINE_TYPE_NAME("b-l475e-iot01a")
33
+OBJECT_DECLARE_SIMPLE_TYPE(Bl475eMachineState, B_L475E_IOT01A)
34
+
35
+typedef struct Bl475eMachineState {
36
+ MachineState parent_obj;
37
+
38
+ Stm32l4x5SocState soc;
39
+} Bl475eMachineState;
40
+
41
+static void bl475e_init(MachineState *machine)
27
{
42
{
28
NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_GET_CLASS(machine);
43
+ Bl475eMachineState *s = B_L475E_IOT01A(machine);
29
- MachineClass *mc = &nmc->parent;
44
const Stm32l4x5SocClass *sc;
30
+ MachineClass *mc = MACHINE_CLASS(nmc);
45
- DeviceState *dev;
31
Object *obj;
46
32
47
- dev = qdev_new(TYPE_STM32L4X5XG_SOC);
33
if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
48
- object_property_add_child(OBJECT(machine), "soc", OBJECT(dev));
34
diff --git a/hw/mem/npcm7xx_mc.c b/hw/mem/npcm7xx_mc.c
49
- sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
35
index XXXXXXX..XXXXXXX 100644
50
+ object_initialize_child(OBJECT(machine), "soc", &s->soc,
36
--- a/hw/mem/npcm7xx_mc.c
51
+ TYPE_STM32L4X5XG_SOC);
37
+++ b/hw/mem/npcm7xx_mc.c
52
+ sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
38
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_mc_realize(DeviceState *dev, Error **errp)
53
39
54
- sc = STM32L4X5_SOC_GET_CLASS(dev);
40
memory_region_init_io(&s->mmio, OBJECT(s), &npcm7xx_mc_ops, s, "regs",
55
- armv7m_load_kernel(ARM_CPU(first_cpu),
41
NPCM7XX_MC_REGS_SIZE);
56
- machine->kernel_filename,
42
- sysbus_init_mmio(&s->parent, &s->mmio);
57
- 0, sc->flash_size);
43
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio);
58
+ sc = STM32L4X5_SOC_GET_CLASS(&s->soc);
59
+ armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0,
60
+ sc->flash_size);
44
}
61
}
45
62
46
static void npcm7xx_mc_class_init(ObjectClass *klass, void *data)
63
-static void b_l475e_iot01a_machine_init(MachineClass *mc)
47
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
64
+static void bl475e_machine_init(ObjectClass *oc, void *data)
48
index XXXXXXX..XXXXXXX 100644
65
{
49
--- a/hw/misc/npcm7xx_clk.c
66
+ MachineClass *mc = MACHINE_CLASS(oc);
50
+++ b/hw/misc/npcm7xx_clk.c
67
static const char *machine_valid_cpu_types[] = {
51
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_init(Object *obj)
68
ARM_CPU_TYPE_NAME("cortex-m4"),
52
69
NULL
53
memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s,
70
};
54
TYPE_NPCM7XX_CLK, 4 * KiB);
71
mc->desc = "B-L475E-IOT01A Discovery Kit (Cortex-M4)";
55
- sysbus_init_mmio(&s->parent, &s->iomem);
72
- mc->init = b_l475e_iot01a_init;
56
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
73
+ mc->init = bl475e_init;
74
mc->valid_cpu_types = machine_valid_cpu_types;
75
76
/* SRAM pre-allocated as part of the SoC instantiation */
77
mc->default_ram_size = 0;
57
}
78
}
58
79
59
static int npcm7xx_clk_post_load(void *opaque, int version_id)
80
-DEFINE_MACHINE("b-l475e-iot01a", b_l475e_iot01a_machine_init)
60
diff --git a/hw/misc/npcm7xx_gcr.c b/hw/misc/npcm7xx_gcr.c
81
+static const TypeInfo bl475e_machine_type[] = {
61
index XXXXXXX..XXXXXXX 100644
82
+ {
62
--- a/hw/misc/npcm7xx_gcr.c
83
+ .name = TYPE_B_L475E_IOT01A,
63
+++ b/hw/misc/npcm7xx_gcr.c
84
+ .parent = TYPE_MACHINE,
64
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_gcr_init(Object *obj)
85
+ .instance_size = sizeof(Bl475eMachineState),
65
86
+ .class_init = bl475e_machine_init,
66
memory_region_init_io(&s->iomem, obj, &npcm7xx_gcr_ops, s,
87
+ }
67
TYPE_NPCM7XX_GCR, 4 * KiB);
88
+};
68
- sysbus_init_mmio(&s->parent, &s->iomem);
89
+
69
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
90
+DEFINE_TYPES(bl475e_machine_type)
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
--
91
--
113
2.20.1
92
2.34.1
114
93
115
94
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
This patch allows NPCM7XX CLK module to compute clocks that are used by
3
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
4
other NPCM7XX modules.
4
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
5
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Add a new struct NPCM7xxClockConverterState which represents a
6
Message-id: 20240424200929.240921-5-ines.varhol@telecom-paris.fr
7
single converter. Each clock converter in CLK module represents one
8
converter in NPCM7XX CLK Module(PLL, SEL or Divider). Each converter
9
takes one or more input clocks and converts them into one output clock.
10
They form a clock hierarchy in the CLK module and are responsible for
11
outputing clocks for various other modules in an NPCM7XX SoC.
12
13
Each converter has a function pointer called "convert" which represents
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>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
---
8
---
27
include/hw/misc/npcm7xx_clk.h | 140 +++++-
9
hw/arm/b-l475e-iot01a.c | 59 +++++++++++++++++++++++++++++++++++++++--
28
hw/misc/npcm7xx_clk.c | 805 +++++++++++++++++++++++++++++++++-
10
hw/arm/Kconfig | 1 +
29
2 files changed, 932 insertions(+), 13 deletions(-)
11
2 files changed, 58 insertions(+), 2 deletions(-)
30
12
31
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
13
diff --git a/hw/arm/b-l475e-iot01a.c b/hw/arm/b-l475e-iot01a.c
32
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
33
--- a/include/hw/misc/npcm7xx_clk.h
15
--- a/hw/arm/b-l475e-iot01a.c
34
+++ b/include/hw/misc/npcm7xx_clk.h
16
+++ b/hw/arm/b-l475e-iot01a.c
35
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@
36
#define NPCM7XX_CLK_H
18
#include "hw/boards.h"
37
19
#include "hw/qdev-properties.h"
38
#include "exec/memory.h"
20
#include "qemu/error-report.h"
39
+#include "hw/clock.h"
21
-#include "hw/arm/stm32l4x5_soc.h"
40
#include "hw/sysbus.h"
22
#include "hw/arm/boot.h"
41
23
+#include "hw/core/split-irq.h"
42
/*
24
+#include "hw/arm/stm32l4x5_soc.h"
43
@@ -XXX,XX +XXX,XX @@
25
+#include "hw/gpio/stm32l4x5_gpio.h"
44
26
+#include "hw/display/dm163.h"
45
#define NPCM7XX_WATCHDOG_RESET_GPIO_IN "npcm7xx-clk-watchdog-reset-gpio-in"
27
46
28
-/* B-L475E-IOT01A implementation is derived from netduinoplus2 */
47
-typedef struct NPCM7xxCLKState {
29
+/* B-L475E-IOT01A implementation is inspired from netduinoplus2 and arduino */
48
+/* Maximum amount of clock inputs in a SEL module. */
49
+#define NPCM7XX_CLK_SEL_MAX_INPUT 5
50
+
30
+
51
+/* PLLs in CLK module. */
31
+/*
52
+typedef enum NPCM7xxClockPLL {
32
+ * There are actually 14 input pins in the DM163 device.
53
+ NPCM7XX_CLOCK_PLL0,
33
+ * Here the DM163 input pin EN isn't connected to the STM32L4x5
54
+ NPCM7XX_CLOCK_PLL1,
34
+ * GPIOs as the IM120417002 colors shield doesn't actually use
55
+ NPCM7XX_CLOCK_PLL2,
35
+ * this pin to drive the RGB matrix.
56
+ NPCM7XX_CLOCK_PLLG,
36
+ */
57
+ NPCM7XX_CLOCK_NR_PLLS,
37
+#define NUM_DM163_INPUTS 13
58
+} NPCM7xxClockPLL;
59
+
38
+
60
+/* SEL/MUX in CLK module. */
39
+static const unsigned dm163_input[NUM_DM163_INPUTS] = {
61
+typedef enum NPCM7xxClockSEL {
40
+ 1 * GPIO_NUM_PINS + 2, /* ROW0 PB2 */
62
+ NPCM7XX_CLOCK_PIXCKSEL,
41
+ 0 * GPIO_NUM_PINS + 15, /* ROW1 PA15 */
63
+ NPCM7XX_CLOCK_MCCKSEL,
42
+ 0 * GPIO_NUM_PINS + 2, /* ROW2 PA2 */
64
+ NPCM7XX_CLOCK_CPUCKSEL,
43
+ 0 * GPIO_NUM_PINS + 7, /* ROW3 PA7 */
65
+ NPCM7XX_CLOCK_CLKOUTSEL,
44
+ 0 * GPIO_NUM_PINS + 6, /* ROW4 PA6 */
66
+ NPCM7XX_CLOCK_UARTCKSEL,
45
+ 0 * GPIO_NUM_PINS + 5, /* ROW5 PA5 */
67
+ NPCM7XX_CLOCK_TIMCKSEL,
46
+ 1 * GPIO_NUM_PINS + 0, /* ROW6 PB0 */
68
+ NPCM7XX_CLOCK_SDCKSEL,
47
+ 0 * GPIO_NUM_PINS + 3, /* ROW7 PA3 */
69
+ NPCM7XX_CLOCK_GFXMSEL,
48
+ 0 * GPIO_NUM_PINS + 4, /* SIN (SDA) PA4 */
70
+ NPCM7XX_CLOCK_SUCKSEL,
49
+ 1 * GPIO_NUM_PINS + 1, /* DCK (SCK) PB1 */
71
+ NPCM7XX_CLOCK_NR_SELS,
50
+ 2 * GPIO_NUM_PINS + 3, /* RST_B (RST) PC3 */
72
+} NPCM7xxClockSEL;
51
+ 2 * GPIO_NUM_PINS + 4, /* LAT_B (LAT) PC4 */
52
+ 2 * GPIO_NUM_PINS + 5, /* SELBK (SB) PC5 */
53
+};
54
55
#define TYPE_B_L475E_IOT01A MACHINE_TYPE_NAME("b-l475e-iot01a")
56
OBJECT_DECLARE_SIMPLE_TYPE(Bl475eMachineState, B_L475E_IOT01A)
57
@@ -XXX,XX +XXX,XX @@ typedef struct Bl475eMachineState {
58
MachineState parent_obj;
59
60
Stm32l4x5SocState soc;
61
+ SplitIRQ gpio_splitters[NUM_DM163_INPUTS];
62
+ DM163State dm163;
63
} Bl475eMachineState;
64
65
static void bl475e_init(MachineState *machine)
66
{
67
Bl475eMachineState *s = B_L475E_IOT01A(machine);
68
const Stm32l4x5SocClass *sc;
69
+ DeviceState *dev, *gpio_out_splitter;
70
+ unsigned gpio, pin;
71
72
object_initialize_child(OBJECT(machine), "soc", &s->soc,
73
TYPE_STM32L4X5XG_SOC);
74
@@ -XXX,XX +XXX,XX @@ static void bl475e_init(MachineState *machine)
75
sc = STM32L4X5_SOC_GET_CLASS(&s->soc);
76
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0,
77
sc->flash_size);
73
+
78
+
74
+/* Dividers in CLK module. */
79
+ if (object_class_by_name(TYPE_DM163)) {
75
+typedef enum NPCM7xxClockDivider {
80
+ object_initialize_child(OBJECT(machine), "dm163",
76
+ NPCM7XX_CLOCK_PLL1D2, /* PLL1/2 */
81
+ &s->dm163, TYPE_DM163);
77
+ NPCM7XX_CLOCK_PLL2D2, /* PLL2/2 */
82
+ dev = DEVICE(&s->dm163);
78
+ NPCM7XX_CLOCK_MC_DIVIDER,
83
+ qdev_realize(dev, NULL, &error_abort);
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
+
84
+
100
+typedef struct NPCM7xxCLKState NPCM7xxCLKState;
85
+ for (unsigned i = 0; i < NUM_DM163_INPUTS; i++) {
86
+ object_initialize_child(OBJECT(machine), "gpio-out-splitters[*]",
87
+ &s->gpio_splitters[i], TYPE_SPLIT_IRQ);
88
+ gpio_out_splitter = DEVICE(&s->gpio_splitters[i]);
89
+ qdev_prop_set_uint32(gpio_out_splitter, "num-lines", 2);
90
+ qdev_realize(gpio_out_splitter, NULL, &error_fatal);
101
+
91
+
102
+/**
92
+ qdev_connect_gpio_out(gpio_out_splitter, 0,
103
+ * struct NPCM7xxClockPLLState - A PLL module in CLK module.
93
+ qdev_get_gpio_in(DEVICE(&s->soc), dm163_input[i]));
104
+ * @name: The name of the module.
94
+ qdev_connect_gpio_out(gpio_out_splitter, 1,
105
+ * @clk: The CLK module that owns this module.
95
+ qdev_get_gpio_in(dev, i));
106
+ * @clock_in: The input clock of this module.
96
+ gpio = dm163_input[i] / GPIO_NUM_PINS;
107
+ * @clock_out: The output clock of this module.
97
+ pin = dm163_input[i] % GPIO_NUM_PINS;
108
+ * @reg: The control registers for this PLL module.
98
+ qdev_connect_gpio_out(DEVICE(&s->soc.gpio[gpio]), pin,
109
+ */
99
+ qdev_get_gpio_in(DEVICE(gpio_out_splitter), 0));
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
+{
256
+ NPCM7xxClockPLLState *s = opaque;
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
+}
271
+
272
+static void npcm7xx_clk_update_sel(void *opaque)
273
+{
274
+ NPCM7xxClockSELState *s = opaque;
275
+ uint32_t index = extract32(s->clk->regs[NPCM7XX_CLK_CLKSEL], s->offset,
276
+ s->len);
277
+
278
+ if (index >= s->input_size) {
279
+ qemu_log_mask(LOG_GUEST_ERROR,
280
+ "%s: SEL index: %u out of range\n",
281
+ __func__, index);
282
+ index = 0;
283
+ }
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
+ }
100
+ }
834
+ }
101
+ }
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
}
102
}
886
103
887
+static void npcm7xx_clk_init_clock_hierarchy(NPCM7xxCLKState *s)
104
static void bl475e_machine_init(ObjectClass *oc, void *data)
888
+{
105
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
889
+ int i;
106
index XXXXXXX..XXXXXXX 100644
890
+
107
--- a/hw/arm/Kconfig
891
+ s->clkref = qdev_init_clock_in(DEVICE(s), "clkref", NULL, NULL);
108
+++ b/hw/arm/Kconfig
892
+
109
@@ -XXX,XX +XXX,XX @@ config B_L475E_IOT01A
893
+ /* First pass: init all converter modules */
110
default y
894
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(pll_init_info_list) != NPCM7XX_CLOCK_NR_PLLS);
111
depends on TCG && ARM
895
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(sel_init_info_list) != NPCM7XX_CLOCK_NR_SELS);
112
select STM32L4X5_SOC
896
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(divider_init_info_list)
113
+ imply DM163
897
+ != NPCM7XX_CLOCK_NR_DIVIDERS);
114
898
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
115
config STM32L4X5_SOC
899
+ object_initialize_child(OBJECT(s), pll_init_info_list[i].name,
116
bool
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;
945
+}
946
+
947
+static void npcm7xx_clk_realize(DeviceState *dev, Error **errp)
948
+{
949
+ int i;
950
+ NPCM7xxCLKState *s = NPCM7XX_CLK(dev);
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
+ }
962
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
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
+}
973
+
974
+static const VMStateDescription vmstate_npcm7xx_clk_pll = {
975
+ .name = "npcm7xx-clock-pll",
976
.version_id = 0,
977
.minimum_version_id = 0,
978
- .fields = (VMStateField[]) {
979
- VMSTATE_UINT32_ARRAY(regs, NPCM7xxCLKState, NPCM7XX_CLK_NR_REGS),
980
- VMSTATE_INT64(ref_ns, NPCM7xxCLKState),
981
+ .fields = (VMStateField[]) {
982
+ VMSTATE_CLOCK(clock_in, NPCM7xxClockPLLState),
983
VMSTATE_END_OF_LIST(),
984
},
985
};
986
987
+static const VMStateDescription vmstate_npcm7xx_clk_sel = {
988
+ .name = "npcm7xx-clock-sel",
989
+ .version_id = 0,
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
+{
1023
+ DeviceClass *dc = DEVICE_CLASS(klass);
1024
+
1025
+ dc->desc = "NPCM7xx Clock PLL Module";
1026
+ dc->vmsd = &vmstate_npcm7xx_clk_pll;
1027
+}
1028
+
1029
+static void npcm7xx_clk_sel_class_init(ObjectClass *klass, void *data)
1030
+{
1031
+ DeviceClass *dc = DEVICE_CLASS(klass);
1032
+
1033
+ dc->desc = "NPCM7xx Clock SEL Module";
1034
+ dc->vmsd = &vmstate_npcm7xx_clk_sel;
1035
+}
1036
+
1037
+static void npcm7xx_clk_divider_class_init(ObjectClass *klass, void *data)
1038
+{
1039
+ DeviceClass *dc = DEVICE_CLASS(klass);
1040
+
1041
+ dc->desc = "NPCM7xx Clock Divider Module";
1042
+ dc->vmsd = &vmstate_npcm7xx_clk_divider;
1043
+}
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
+};
1063
+
1064
+static const TypeInfo npcm7xx_clk_sel_info = {
1065
+ .name = TYPE_NPCM7XX_CLOCK_SEL,
1066
+ .parent = TYPE_DEVICE,
1067
+ .instance_size = sizeof(NPCM7xxClockSELState),
1068
+ .instance_init = npcm7xx_clk_sel_init,
1069
+ .class_init = npcm7xx_clk_sel_class_init,
1070
+};
1071
+
1072
+static const TypeInfo npcm7xx_clk_divider_info = {
1073
+ .name = TYPE_NPCM7XX_CLOCK_DIVIDER,
1074
+ .parent = TYPE_DEVICE,
1075
+ .instance_size = sizeof(NPCM7xxClockDividerState),
1076
+ .instance_init = npcm7xx_clk_divider_init,
1077
+ .class_init = npcm7xx_clk_divider_class_init,
1078
+};
1079
+
1080
static const TypeInfo npcm7xx_clk_info = {
1081
.name = TYPE_NPCM7XX_CLK,
1082
.parent = TYPE_SYS_BUS_DEVICE,
1083
@@ -XXX,XX +XXX,XX @@ static const TypeInfo npcm7xx_clk_info = {
1084
1085
static void npcm7xx_clk_register_type(void)
1086
{
1087
+ type_register_static(&npcm7xx_clk_pll_info);
1088
+ type_register_static(&npcm7xx_clk_sel_info);
1089
+ type_register_static(&npcm7xx_clk_divider_info);
1090
type_register_static(&npcm7xx_clk_info);
1091
}
1092
type_init(npcm7xx_clk_register_type);
1093
--
117
--
1094
2.20.1
118
2.34.1
1095
119
1096
120
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
`test_dm163_bank()`
4
expected.
4
Checks that the pin "sout" of the DM163 led driver outputs the values
5
5
received on pin "sin" with the expected latency (depending on the bank).
6
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
6
7
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
7
`test_dm163_gpio_connection()`
8
Signed-off-by: Hao Wu <wuhaotsh@google.com>
8
Check that changes to relevant STM32L4x5 GPIO pins are propagated to the
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
DM163 device.
10
Message-id: 20210108190945.949196-6-wuhaotsh@google.com
10
11
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
12
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
13
Acked-by: Thomas Huth <thuth@redhat.com>
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
15
Message-id: 20240424200929.240921-6-ines.varhol@telecom-paris.fr
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
17
---
13
tests/qtest/npcm7xx_pwm-test.c | 490 +++++++++++++++++++++++++++++++++
18
tests/qtest/dm163-test.c | 194 +++++++++++++++++++++++++++++++++++++++
14
tests/qtest/meson.build | 1 +
19
tests/qtest/meson.build | 2 +
15
2 files changed, 491 insertions(+)
20
2 files changed, 196 insertions(+)
16
create mode 100644 tests/qtest/npcm7xx_pwm-test.c
21
create mode 100644 tests/qtest/dm163-test.c
17
22
18
diff --git a/tests/qtest/npcm7xx_pwm-test.c b/tests/qtest/npcm7xx_pwm-test.c
23
diff --git a/tests/qtest/dm163-test.c b/tests/qtest/dm163-test.c
19
new file mode 100644
24
new file mode 100644
20
index XXXXXXX..XXXXXXX
25
index XXXXXXX..XXXXXXX
21
--- /dev/null
26
--- /dev/null
22
+++ b/tests/qtest/npcm7xx_pwm-test.c
27
+++ b/tests/qtest/dm163-test.c
23
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@
24
+/*
29
+/*
25
+ * QTests for Nuvoton NPCM7xx PWM Modules.
30
+ * QTest testcase for DM163
26
+ *
31
+ *
27
+ * Copyright 2020 Google LLC
32
+ * Copyright (C) 2024 Samuel Tardieu <sam@rfc1149.net>
33
+ * Copyright (C) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
34
+ * Copyright (C) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
28
+ *
35
+ *
29
+ * This program is free software; you can redistribute it and/or modify it
36
+ * SPDX-License-Identifier: GPL-2.0-or-later
30
+ * under the terms of the GNU General Public License as published by the
31
+ * Free Software Foundation; either version 2 of the License, or
32
+ * (at your option) any later version.
33
+ *
34
+ * This program is distributed in the hope that it will be useful, but WITHOUT
35
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
36
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
37
+ * for more details.
38
+ */
37
+ */
39
+
38
+
40
+#include "qemu/osdep.h"
39
+#include "qemu/osdep.h"
41
+#include "qemu/bitops.h"
40
+#include "libqtest.h"
42
+#include "libqos/libqtest.h"
41
+
43
+#include "qapi/qmp/qdict.h"
42
+enum DM163_INPUTS {
44
+#include "qapi/qmp/qnum.h"
43
+ SIN = 8,
45
+
44
+ DCK = 9,
46
+#define REF_HZ 25000000
45
+ RST_B = 10,
47
+
46
+ LAT_B = 11,
48
+/* Register field definitions. */
47
+ SELBK = 12,
49
+#define CH_EN BIT(0)
48
+ EN_B = 13
50
+#define CH_INV BIT(2)
49
+};
51
+#define CH_MOD BIT(3)
50
+
52
+
51
+#define DEVICE_NAME "/machine/dm163"
53
+/* Registers shared between all PWMs in a module */
52
+#define GPIO_OUT(name, value) qtest_set_irq_in(qts, DEVICE_NAME, NULL, name, \
54
+#define PPR 0x00
53
+ value)
55
+#define CSR 0x04
54
+#define GPIO_PULSE(name) \
56
+#define PCR 0x08
55
+ do { \
57
+#define PIER 0x3c
56
+ GPIO_OUT(name, 1); \
58
+#define PIIR 0x40
57
+ GPIO_OUT(name, 0); \
59
+
58
+ } while (0)
60
+/* CLK module related */
59
+
61
+#define CLK_BA 0xf0801000
60
+
62
+#define CLKSEL 0x04
61
+static void rise_gpio_pin_dck(QTestState *qts)
63
+#define CLKDIV1 0x08
62
+{
64
+#define CLKDIV2 0x2c
63
+ /* Configure output mode for pin PB1 */
65
+#define PLLCON0 0x0c
64
+ qtest_writel(qts, 0x48000400, 0xFFFFFEB7);
66
+#define PLLCON1 0x10
65
+ /* Write 1 in ODR for PB1 */
67
+#define PLL_INDV(rv) extract32((rv), 0, 6)
66
+ qtest_writel(qts, 0x48000414, 0x00000002);
68
+#define PLL_FBDV(rv) extract32((rv), 16, 12)
67
+}
69
+#define PLL_OTDV1(rv) extract32((rv), 8, 3)
68
+
70
+#define PLL_OTDV2(rv) extract32((rv), 13, 3)
69
+static void lower_gpio_pin_dck(QTestState *qts)
71
+#define APB3CKDIV(rv) extract32((rv), 28, 2)
70
+{
72
+#define CLK2CKDIV(rv) extract32((rv), 0, 1)
71
+ /* Configure output mode for pin PB1 */
73
+#define CLK4CKDIV(rv) extract32((rv), 26, 2)
72
+ qtest_writel(qts, 0x48000400, 0xFFFFFEB7);
74
+#define CPUCKSEL(rv) extract32((rv), 0, 2)
73
+ /* Write 0 in ODR for PB1 */
75
+
74
+ qtest_writel(qts, 0x48000414, 0x00000000);
76
+#define MAX_DUTY 1000000
75
+}
77
+
76
+
78
+typedef struct PWMModule {
77
+static void rise_gpio_pin_selbk(QTestState *qts)
79
+ int irq;
78
+{
80
+ uint64_t base_addr;
79
+ /* Configure output mode for pin PC5 */
81
+} PWMModule;
80
+ qtest_writel(qts, 0x48000800, 0xFFFFF7FF);
82
+
81
+ /* Write 1 in ODR for PC5 */
83
+typedef struct PWM {
82
+ qtest_writel(qts, 0x48000814, 0x00000020);
84
+ uint32_t cnr_offset;
83
+}
85
+ uint32_t cmr_offset;
84
+
86
+ uint32_t pdr_offset;
85
+static void lower_gpio_pin_selbk(QTestState *qts)
87
+ uint32_t pwdr_offset;
86
+{
88
+} PWM;
87
+ /* Configure output mode for pin PC5 */
89
+
88
+ qtest_writel(qts, 0x48000800, 0xFFFFF7FF);
90
+typedef struct TestData {
89
+ /* Write 0 in ODR for PC5 */
91
+ const PWMModule *module;
90
+ qtest_writel(qts, 0x48000814, 0x00000000);
92
+ const PWM *pwm;
91
+}
93
+} TestData;
92
+
94
+
93
+static void rise_gpio_pin_lat_b(QTestState *qts)
95
+static const PWMModule pwm_module_list[] = {
94
+{
96
+ {
95
+ /* Configure output mode for pin PC4 */
97
+ .irq = 93,
96
+ qtest_writel(qts, 0x48000800, 0xFFFFFDFF);
98
+ .base_addr = 0xf0103000
97
+ /* Write 1 in ODR for PC4 */
99
+ },
98
+ qtest_writel(qts, 0x48000814, 0x00000010);
100
+ {
99
+}
101
+ .irq = 94,
100
+
102
+ .base_addr = 0xf0104000
101
+static void lower_gpio_pin_lat_b(QTestState *qts)
102
+{
103
+ /* Configure output mode for pin PC4 */
104
+ qtest_writel(qts, 0x48000800, 0xFFFFFDFF);
105
+ /* Write 0 in ODR for PC4 */
106
+ qtest_writel(qts, 0x48000814, 0x00000000);
107
+}
108
+
109
+static void rise_gpio_pin_rst_b(QTestState *qts)
110
+{
111
+ /* Configure output mode for pin PC3 */
112
+ qtest_writel(qts, 0x48000800, 0xFFFFFF7F);
113
+ /* Write 1 in ODR for PC3 */
114
+ qtest_writel(qts, 0x48000814, 0x00000008);
115
+}
116
+
117
+static void lower_gpio_pin_rst_b(QTestState *qts)
118
+{
119
+ /* Configure output mode for pin PC3 */
120
+ qtest_writel(qts, 0x48000800, 0xFFFFFF7F);
121
+ /* Write 0 in ODR for PC3 */
122
+ qtest_writel(qts, 0x48000814, 0x00000000);
123
+}
124
+
125
+static void rise_gpio_pin_sin(QTestState *qts)
126
+{
127
+ /* Configure output mode for pin PA4 */
128
+ qtest_writel(qts, 0x48000000, 0xFFFFFDFF);
129
+ /* Write 1 in ODR for PA4 */
130
+ qtest_writel(qts, 0x48000014, 0x00000010);
131
+}
132
+
133
+static void lower_gpio_pin_sin(QTestState *qts)
134
+{
135
+ /* Configure output mode for pin PA4 */
136
+ qtest_writel(qts, 0x48000000, 0xFFFFFDFF);
137
+ /* Write 0 in ODR for PA4 */
138
+ qtest_writel(qts, 0x48000014, 0x00000000);
139
+}
140
+
141
+static void test_dm163_bank(const void *opaque)
142
+{
143
+ const unsigned bank = (uintptr_t) opaque;
144
+ const int width = bank ? 192 : 144;
145
+
146
+ QTestState *qts = qtest_initf("-M b-l475e-iot01a");
147
+ qtest_irq_intercept_out_named(qts, DEVICE_NAME, "sout");
148
+ GPIO_OUT(RST_B, 1);
149
+ GPIO_OUT(EN_B, 0);
150
+ GPIO_OUT(DCK, 0);
151
+ GPIO_OUT(SELBK, bank);
152
+ GPIO_OUT(LAT_B, 1);
153
+
154
+ /* Fill bank with zeroes */
155
+ GPIO_OUT(SIN, 0);
156
+ for (int i = 0; i < width; i++) {
157
+ GPIO_PULSE(DCK);
103
+ }
158
+ }
104
+};
159
+ /* Fill bank with ones, check that we get the previous zeroes */
105
+
160
+ GPIO_OUT(SIN, 1);
106
+static const PWM pwm_list[] = {
161
+ for (int i = 0; i < width; i++) {
107
+ {
162
+ GPIO_PULSE(DCK);
108
+ .cnr_offset = 0x0c,
163
+ g_assert(!qtest_get_irq(qts, 0));
109
+ .cmr_offset = 0x10,
110
+ .pdr_offset = 0x14,
111
+ .pwdr_offset = 0x44,
112
+ },
113
+ {
114
+ .cnr_offset = 0x18,
115
+ .cmr_offset = 0x1c,
116
+ .pdr_offset = 0x20,
117
+ .pwdr_offset = 0x48,
118
+ },
119
+ {
120
+ .cnr_offset = 0x24,
121
+ .cmr_offset = 0x28,
122
+ .pdr_offset = 0x2c,
123
+ .pwdr_offset = 0x4c,
124
+ },
125
+ {
126
+ .cnr_offset = 0x30,
127
+ .cmr_offset = 0x34,
128
+ .pdr_offset = 0x38,
129
+ .pwdr_offset = 0x50,
130
+ },
131
+};
132
+
133
+static const int ppr_base[] = { 0, 0, 8, 8 };
134
+static const int csr_base[] = { 0, 4, 8, 12 };
135
+static const int pcr_base[] = { 0, 8, 12, 16 };
136
+
137
+static const uint32_t ppr_list[] = {
138
+ 0,
139
+ 1,
140
+ 10,
141
+ 100,
142
+ 255, /* Max possible value. */
143
+};
144
+
145
+static const uint32_t csr_list[] = {
146
+ 0,
147
+ 1,
148
+ 2,
149
+ 3,
150
+ 4, /* Max possible value. */
151
+};
152
+
153
+static const uint32_t cnr_list[] = {
154
+ 0,
155
+ 1,
156
+ 50,
157
+ 100,
158
+ 150,
159
+ 200,
160
+ 1000,
161
+ 10000,
162
+ 65535, /* Max possible value. */
163
+};
164
+
165
+static const uint32_t cmr_list[] = {
166
+ 0,
167
+ 1,
168
+ 10,
169
+ 50,
170
+ 100,
171
+ 150,
172
+ 200,
173
+ 1000,
174
+ 10000,
175
+ 65535, /* Max possible value. */
176
+};
177
+
178
+/* Returns the index of the PWM module. */
179
+static int pwm_module_index(const PWMModule *module)
180
+{
181
+ ptrdiff_t diff = module - pwm_module_list;
182
+
183
+ g_assert_true(diff >= 0 && diff < ARRAY_SIZE(pwm_module_list));
184
+
185
+ return diff;
186
+}
187
+
188
+/* Returns the index of the PWM entry. */
189
+static int pwm_index(const PWM *pwm)
190
+{
191
+ ptrdiff_t diff = pwm - pwm_list;
192
+
193
+ g_assert_true(diff >= 0 && diff < ARRAY_SIZE(pwm_list));
194
+
195
+ return diff;
196
+}
197
+
198
+static uint64_t pwm_qom_get(QTestState *qts, const char *path, const char *name)
199
+{
200
+ QDict *response;
201
+
202
+ g_test_message("Getting properties %s from %s", name, path);
203
+ response = qtest_qmp(qts, "{ 'execute': 'qom-get',"
204
+ " 'arguments': { 'path': %s, 'property': %s}}",
205
+ path, name);
206
+ /* The qom set message returns successfully. */
207
+ g_assert_true(qdict_haskey(response, "return"));
208
+ return qnum_get_uint(qobject_to(QNum, qdict_get(response, "return")));
209
+}
210
+
211
+static uint64_t pwm_get_freq(QTestState *qts, int module_index, int pwm_index)
212
+{
213
+ char path[100];
214
+ char name[100];
215
+
216
+ sprintf(path, "/machine/soc/pwm[%d]", module_index);
217
+ sprintf(name, "freq[%d]", pwm_index);
218
+
219
+ return pwm_qom_get(qts, path, name);
220
+}
221
+
222
+static uint64_t pwm_get_duty(QTestState *qts, int module_index, int pwm_index)
223
+{
224
+ char path[100];
225
+ char name[100];
226
+
227
+ sprintf(path, "/machine/soc/pwm[%d]", module_index);
228
+ sprintf(name, "duty[%d]", pwm_index);
229
+
230
+ return pwm_qom_get(qts, path, name);
231
+}
232
+
233
+static uint32_t get_pll(uint32_t con)
234
+{
235
+ return REF_HZ * PLL_FBDV(con) / (PLL_INDV(con) * PLL_OTDV1(con)
236
+ * PLL_OTDV2(con));
237
+}
238
+
239
+static uint64_t read_pclk(QTestState *qts)
240
+{
241
+ uint64_t freq = REF_HZ;
242
+ uint32_t clksel = qtest_readl(qts, CLK_BA + CLKSEL);
243
+ uint32_t pllcon;
244
+ uint32_t clkdiv1 = qtest_readl(qts, CLK_BA + CLKDIV1);
245
+ uint32_t clkdiv2 = qtest_readl(qts, CLK_BA + CLKDIV2);
246
+
247
+ switch (CPUCKSEL(clksel)) {
248
+ case 0:
249
+ pllcon = qtest_readl(qts, CLK_BA + PLLCON0);
250
+ freq = get_pll(pllcon);
251
+ break;
252
+ case 1:
253
+ pllcon = qtest_readl(qts, CLK_BA + PLLCON1);
254
+ freq = get_pll(pllcon);
255
+ break;
256
+ case 2:
257
+ break;
258
+ case 3:
259
+ break;
260
+ default:
261
+ g_assert_not_reached();
262
+ }
164
+ }
263
+
165
+
264
+ freq >>= (CLK2CKDIV(clkdiv1) + CLK4CKDIV(clkdiv1) + APB3CKDIV(clkdiv2));
166
+ /* Pulse one more bit in the bank, check that we get a one */
265
+
167
+ GPIO_PULSE(DCK);
266
+ return freq;
168
+ g_assert(qtest_get_irq(qts, 0));
267
+}
268
+
269
+static uint32_t pwm_selector(uint32_t csr)
270
+{
271
+ switch (csr) {
272
+ case 0:
273
+ return 2;
274
+ case 1:
275
+ return 4;
276
+ case 2:
277
+ return 8;
278
+ case 3:
279
+ return 16;
280
+ case 4:
281
+ return 1;
282
+ default:
283
+ g_assert_not_reached();
284
+ }
285
+}
286
+
287
+static uint64_t pwm_compute_freq(QTestState *qts, uint32_t ppr, uint32_t csr,
288
+ uint32_t cnr)
289
+{
290
+ return read_pclk(qts) / ((ppr + 1) * pwm_selector(csr) * (cnr + 1));
291
+}
292
+
293
+static uint64_t pwm_compute_duty(uint32_t cnr, uint32_t cmr, bool inverted)
294
+{
295
+ uint64_t duty;
296
+
297
+ if (cnr == 0) {
298
+ /* PWM is stopped. */
299
+ duty = 0;
300
+ } else if (cmr >= cnr) {
301
+ duty = MAX_DUTY;
302
+ } else {
303
+ duty = MAX_DUTY * (cmr + 1) / (cnr + 1);
304
+ }
305
+
306
+ if (inverted) {
307
+ duty = MAX_DUTY - duty;
308
+ }
309
+
310
+ return duty;
311
+}
312
+
313
+static uint32_t pwm_read(QTestState *qts, const TestData *td, unsigned offset)
314
+{
315
+ return qtest_readl(qts, td->module->base_addr + offset);
316
+}
317
+
318
+static void pwm_write(QTestState *qts, const TestData *td, unsigned offset,
319
+ uint32_t value)
320
+{
321
+ qtest_writel(qts, td->module->base_addr + offset, value);
322
+}
323
+
324
+static uint32_t pwm_read_ppr(QTestState *qts, const TestData *td)
325
+{
326
+ return extract32(pwm_read(qts, td, PPR), ppr_base[pwm_index(td->pwm)], 8);
327
+}
328
+
329
+static void pwm_write_ppr(QTestState *qts, const TestData *td, uint32_t value)
330
+{
331
+ pwm_write(qts, td, PPR, value << ppr_base[pwm_index(td->pwm)]);
332
+}
333
+
334
+static uint32_t pwm_read_csr(QTestState *qts, const TestData *td)
335
+{
336
+ return extract32(pwm_read(qts, td, CSR), csr_base[pwm_index(td->pwm)], 3);
337
+}
338
+
339
+static void pwm_write_csr(QTestState *qts, const TestData *td, uint32_t value)
340
+{
341
+ pwm_write(qts, td, CSR, value << csr_base[pwm_index(td->pwm)]);
342
+}
343
+
344
+static uint32_t pwm_read_pcr(QTestState *qts, const TestData *td)
345
+{
346
+ return extract32(pwm_read(qts, td, PCR), pcr_base[pwm_index(td->pwm)], 4);
347
+}
348
+
349
+static void pwm_write_pcr(QTestState *qts, const TestData *td, uint32_t value)
350
+{
351
+ pwm_write(qts, td, PCR, value << pcr_base[pwm_index(td->pwm)]);
352
+}
353
+
354
+static uint32_t pwm_read_cnr(QTestState *qts, const TestData *td)
355
+{
356
+ return pwm_read(qts, td, td->pwm->cnr_offset);
357
+}
358
+
359
+static void pwm_write_cnr(QTestState *qts, const TestData *td, uint32_t value)
360
+{
361
+ pwm_write(qts, td, td->pwm->cnr_offset, value);
362
+}
363
+
364
+static uint32_t pwm_read_cmr(QTestState *qts, const TestData *td)
365
+{
366
+ return pwm_read(qts, td, td->pwm->cmr_offset);
367
+}
368
+
369
+static void pwm_write_cmr(QTestState *qts, const TestData *td, uint32_t value)
370
+{
371
+ pwm_write(qts, td, td->pwm->cmr_offset, value);
372
+}
373
+
374
+/* Check pwm registers can be reset to default value */
375
+static void test_init(gconstpointer test_data)
376
+{
377
+ const TestData *td = test_data;
378
+ QTestState *qts = qtest_init("-machine quanta-gsj");
379
+ int module = pwm_module_index(td->module);
380
+ int pwm = pwm_index(td->pwm);
381
+
382
+ g_assert_cmpuint(pwm_get_freq(qts, module, pwm), ==, 0);
383
+ g_assert_cmpuint(pwm_get_duty(qts, module, pwm), ==, 0);
384
+
169
+
385
+ qtest_quit(qts);
170
+ qtest_quit(qts);
386
+}
171
+}
387
+
172
+
388
+/* One-shot mode should not change frequency and duty cycle. */
173
+static void test_dm163_gpio_connection(void)
389
+static void test_oneshot(gconstpointer test_data)
174
+{
390
+{
175
+ QTestState *qts = qtest_init("-M b-l475e-iot01a");
391
+ const TestData *td = test_data;
176
+ qtest_irq_intercept_in(qts, DEVICE_NAME);
392
+ QTestState *qts = qtest_init("-machine quanta-gsj");
177
+
393
+ int module = pwm_module_index(td->module);
178
+ g_assert_false(qtest_get_irq(qts, SIN));
394
+ int pwm = pwm_index(td->pwm);
179
+ g_assert_false(qtest_get_irq(qts, DCK));
395
+ uint32_t ppr, csr, pcr;
180
+ g_assert_false(qtest_get_irq(qts, RST_B));
396
+ int i, j;
181
+ g_assert_false(qtest_get_irq(qts, LAT_B));
397
+
182
+ g_assert_false(qtest_get_irq(qts, SELBK));
398
+ pcr = CH_EN;
183
+
399
+ for (i = 0; i < ARRAY_SIZE(ppr_list); ++i) {
184
+ rise_gpio_pin_dck(qts);
400
+ ppr = ppr_list[i];
185
+ g_assert_true(qtest_get_irq(qts, DCK));
401
+ pwm_write_ppr(qts, td, ppr);
186
+ lower_gpio_pin_dck(qts);
402
+
187
+ g_assert_false(qtest_get_irq(qts, DCK));
403
+ for (j = 0; j < ARRAY_SIZE(csr_list); ++j) {
188
+
404
+ csr = csr_list[j];
189
+ rise_gpio_pin_lat_b(qts);
405
+ pwm_write_csr(qts, td, csr);
190
+ g_assert_true(qtest_get_irq(qts, LAT_B));
406
+ pwm_write_pcr(qts, td, pcr);
191
+ lower_gpio_pin_lat_b(qts);
407
+
192
+ g_assert_false(qtest_get_irq(qts, LAT_B));
408
+ g_assert_cmpuint(pwm_read_ppr(qts, td), ==, ppr);
193
+
409
+ g_assert_cmpuint(pwm_read_csr(qts, td), ==, csr);
194
+ rise_gpio_pin_selbk(qts);
410
+ g_assert_cmpuint(pwm_read_pcr(qts, td), ==, pcr);
195
+ g_assert_true(qtest_get_irq(qts, SELBK));
411
+ g_assert_cmpuint(pwm_get_freq(qts, module, pwm), ==, 0);
196
+ lower_gpio_pin_selbk(qts);
412
+ g_assert_cmpuint(pwm_get_duty(qts, module, pwm), ==, 0);
197
+ g_assert_false(qtest_get_irq(qts, SELBK));
413
+ }
198
+
414
+ }
199
+ rise_gpio_pin_rst_b(qts);
415
+
200
+ g_assert_true(qtest_get_irq(qts, RST_B));
416
+ qtest_quit(qts);
201
+ lower_gpio_pin_rst_b(qts);
417
+}
202
+ g_assert_false(qtest_get_irq(qts, RST_B));
418
+
203
+
419
+/* In toggle mode, the PWM generates correct outputs. */
204
+ rise_gpio_pin_sin(qts);
420
+static void test_toggle(gconstpointer test_data)
205
+ g_assert_true(qtest_get_irq(qts, SIN));
421
+{
206
+ lower_gpio_pin_sin(qts);
422
+ const TestData *td = test_data;
207
+ g_assert_false(qtest_get_irq(qts, SIN));
423
+ QTestState *qts = qtest_init("-machine quanta-gsj");
208
+
424
+ int module = pwm_module_index(td->module);
209
+ g_assert_false(qtest_get_irq(qts, DCK));
425
+ int pwm = pwm_index(td->pwm);
210
+ g_assert_false(qtest_get_irq(qts, LAT_B));
426
+ uint32_t ppr, csr, pcr, cnr, cmr;
211
+ g_assert_false(qtest_get_irq(qts, SELBK));
427
+ int i, j, k, l;
212
+ g_assert_false(qtest_get_irq(qts, RST_B));
428
+ uint64_t expected_freq, expected_duty;
213
+}
429
+
430
+ pcr = CH_EN | CH_MOD;
431
+ for (i = 0; i < ARRAY_SIZE(ppr_list); ++i) {
432
+ ppr = ppr_list[i];
433
+ pwm_write_ppr(qts, td, ppr);
434
+
435
+ for (j = 0; j < ARRAY_SIZE(csr_list); ++j) {
436
+ csr = csr_list[j];
437
+ pwm_write_csr(qts, td, csr);
438
+
439
+ for (k = 0; k < ARRAY_SIZE(cnr_list); ++k) {
440
+ cnr = cnr_list[k];
441
+ pwm_write_cnr(qts, td, cnr);
442
+
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
+
214
+
493
+int main(int argc, char **argv)
215
+int main(int argc, char **argv)
494
+{
216
+{
495
+ TestData test_data_list[ARRAY_SIZE(pwm_module_list) * ARRAY_SIZE(pwm_list)];
496
+
497
+ g_test_init(&argc, &argv, NULL);
217
+ g_test_init(&argc, &argv, NULL);
498
+
218
+ qtest_add_data_func("/dm163/bank0", (void *)0, test_dm163_bank);
499
+ for (int i = 0; i < ARRAY_SIZE(pwm_module_list); ++i) {
219
+ qtest_add_data_func("/dm163/bank1", (void *)1, test_dm163_bank);
500
+ for (int j = 0; j < ARRAY_SIZE(pwm_list); ++j) {
220
+ qtest_add_func("/dm163/gpio_connection", test_dm163_gpio_connection);
501
+ TestData *td = &test_data_list[i * ARRAY_SIZE(pwm_list) + j];
502
+
503
+ td->module = &pwm_module_list[i];
504
+ td->pwm = &pwm_list[j];
505
+
506
+ add_test(init, td);
507
+ add_test(oneshot, td);
508
+ add_test(toggle, td);
509
+ }
510
+ }
511
+
512
+ return g_test_run();
221
+ return g_test_run();
513
+}
222
+}
514
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
223
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
515
index XXXXXXX..XXXXXXX 100644
224
index XXXXXXX..XXXXXXX 100644
516
--- a/tests/qtest/meson.build
225
--- a/tests/qtest/meson.build
517
+++ b/tests/qtest/meson.build
226
+++ b/tests/qtest/meson.build
518
@@ -XXX,XX +XXX,XX @@ qtests_sparc64 = \
227
@@ -XXX,XX +XXX,XX @@ qtests_arm = \
519
qtests_npcm7xx = \
228
(config_all_devices.has_key('CONFIG_MICROBIT') ? ['microbit-test'] : []) + \
520
['npcm7xx_adc-test',
229
(config_all_devices.has_key('CONFIG_STM32L4X5_SOC') ? qtests_stm32l4x5 : []) + \
521
'npcm7xx_gpio-test',
230
(config_all_devices.has_key('CONFIG_FSI_APB2OPB_ASPEED') ? ['aspeed_fsi-test'] : []) + \
522
+ 'npcm7xx_pwm-test',
231
+ (config_all_devices.has_key('CONFIG_STM32L4X5_SOC') and
523
'npcm7xx_rng-test',
232
+ config_all_devices.has_key('CONFIG_DM163')? ['dm163-test'] : []) + \
524
'npcm7xx_timer-test',
233
['arm-cpu-features',
525
'npcm7xx_watchdog_timer-test']
234
'boot-serial-test']
235
526
--
236
--
527
2.20.1
237
2.34.1
528
238
529
239
diff view generated by jsdifflib