1
First arm pullreq of 5.0!
1
Arm queue; not huge but I figured I might as well send it out since
2
I've been doing code review today and there's no queue of unprocessed
3
pullreqs...
2
4
3
The following changes since commit 084a398bf8aa7634738e6c6c0103236ee1b3b72f:
5
thanks
6
-- PMM
4
7
5
Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging (2019-12-13 18:14:07 +0000)
8
The following changes since commit b3f846c59d8405bb87c551187721fc92ff2f1b92:
9
10
Merge remote-tracking branch 'remotes/huth-gitlab/tags/pull-request-2021-01-11v2' into staging (2021-01-11 15:15:35 +0000)
6
11
7
are available in the Git repository at:
12
are available in the Git repository at:
8
13
9
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20191216-1
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210112
10
15
11
for you to fetch changes up to f80741d107673f162e3b097fc76a1590036cc9d1:
16
for you to fetch changes up to 19d131395ccaf503db21dadd8257e6dc9fc1d7de:
12
17
13
target/arm: ensure we use current exception state after SCR update (2019-12-16 10:52:58 +0000)
18
ui/cocoa: Fix openFile: deprecation on Big Sur (2021-01-12 11:38:37 +0000)
14
19
15
----------------------------------------------------------------
20
----------------------------------------------------------------
16
target-arm queue:
21
target-arm queue:
17
* Add support for Cortex-M7 CPU
22
* arm: Support emulation of ARMv8.4-TTST extension
18
* exynos4210_gic: Suppress gcc9 format-truncation warnings
23
* arm: Update cpu.h ID register field definitions
19
* aspeed: Various minor bug fixes and improvements
24
* arm: Fix breakage of XScale instruction emulation
20
* aspeed: Add support for the tacoma-bmc board
25
* hw/net/lan9118: Fix RX Status FIFO PEEK value
21
* Honour HCR_EL32.TID1 and .TID2 trapping requirements
26
* npcm7xx: Add ADC and PWM emulation
22
* Handle trapping to EL2 of AArch32 VMRS instructions
27
* ui/cocoa: Make "open docs" help menu entry work again when binary
23
* Handle AArch32 CP15 trapping via HSTR_EL2
28
is run from the build tree
24
* Add support for missing Jazelle system registers
29
* ui/cocoa: Fix openFile: deprecation on Big Sur
25
* arm/arm-powerctl: set NSACR.{CP11, CP10} bits in arm_set_cpu_on
30
* docs: Add qemu-storage-daemon(1) manpage to meson.build
26
* Add support for DC CVAP & DC CVADP instructions
31
* docs: Build and install all the docs in a single manual
27
* Fix assertion when SCR.NS is changed in Secure-SVC &c
28
* enable SHPC native hot plug in arm ACPI
29
32
30
----------------------------------------------------------------
33
----------------------------------------------------------------
31
Alex Bennée (1):
34
Hao Wu (6):
32
target/arm: ensure we use current exception state after SCR update
35
hw/misc: Add clock converter in NPCM7XX CLK module
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
33
41
34
Beata Michalska (4):
42
Leif Lindholm (6):
35
tcg: cputlb: Add probe_read
43
target/arm: fix typo in cpu.h ID_AA64PFR1 field name
36
Memory: Enable writeback for given memory region
44
target/arm: make ARMCPU.clidr 64-bit
37
migration: ram: Switch to ram block writeback
45
target/arm: make ARMCPU.ctr 64-bit
38
target/arm: Add support for DC CVAP & DC CVADP ins
46
target/arm: add descriptions of CLIDR_EL1, CCSIDR_EL1, CTR_EL0 to cpu.h
47
target/arm: add aarch64 ID register fields to cpu.h
48
target/arm: add aarch32 ID register fields to cpu.h
39
49
40
Christophe Lyon (1):
50
Peter Maydell (5):
41
target/arm: Add support for cortex-m7 CPU
51
docs: Add qemu-storage-daemon(1) manpage to meson.build
52
docs: Build and install all the docs in a single manual
53
target/arm: Don't decode insns in the XScale/iWMMXt space as cp insns
54
hw/net/lan9118: Fix RX Status FIFO PEEK value
55
hw/net/lan9118: Add symbolic constants for register offsets
42
56
43
Cédric Le Goater (12):
57
Roman Bolshakov (2):
44
aspeed/i2c: Add support for pool buffer transfers
58
ui/cocoa: Update path to docs in build tree
45
aspeed/i2c: Check SRAM enablement on AST2500
59
ui/cocoa: Fix openFile: deprecation on Big Sur
46
aspeed: Add a DRAM memory region at the SoC level
47
aspeed/i2c: Add support for DMA transfers
48
aspeed/i2c: Add trace events
49
aspeed/smc: Restore default AHB window mapping at reset
50
aspeed/smc: Do not map disabled segment on the AST2600
51
aspeed/smc: Add AST2600 timings registers
52
aspeed: Remove AspeedBoardConfig array and use AspeedMachineClass
53
aspeed: Add support for the tacoma-bmc board
54
aspeed: Change the "scu" property definition
55
aspeed: Change the "nic" property definition
56
60
57
David Gibson (1):
61
Rémi Denis-Courmont (2):
58
exynos4210_gic: Suppress gcc9 format-truncation warnings
62
target/arm: ARMv8.4-TTST extension
63
target/arm: enable Small Translation tables in max CPU
59
64
60
Heyi Guo (2):
65
docs/conf.py | 46 ++-
61
hw/arm/acpi: simplify AML bit and/or statement
66
docs/devel/conf.py | 15 -
62
hw/arm/acpi: enable SHPC native hot plug
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
63
122
64
Joel Stanley (4):
65
aspeed/sdmc: Make ast2600 default 1G
66
aspeed/scu: Fix W1C behavior
67
watchdog/aspeed: Improve watchdog timeout message
68
watchdog/aspeed: Fix AST2600 frequency behaviour
69
70
Marc Zyngier (5):
71
target/arm: Honor HCR_EL2.TID2 trapping requirements
72
target/arm: Honor HCR_EL2.TID1 trapping requirements
73
target/arm: Handle trapping to EL2 of AArch32 VMRS instructions
74
target/arm: Handle AArch32 CP15 trapping via HSTR_EL2
75
target/arm: Add support for missing Jazelle system registers
76
77
Niek Linnenbank (1):
78
arm/arm-powerctl: set NSACR.{CP11, CP10} bits in arm_set_cpu_on()
79
80
PanNengyuan (1):
81
gpio: fix memory leak in aspeed_gpio_init()
82
83
Philippe Mathieu-Daudé (2):
84
hw/arm/sbsa-ref: Simplify by moving the gic in the machine state
85
hw/arm/virt: Simplify by moving the gic in the machine state
86
87
include/exec/exec-all.h | 6 +
88
include/exec/memory.h | 6 +
89
include/exec/ram_addr.h | 8 +
90
include/hw/arm/aspeed.h | 24 +--
91
include/hw/arm/aspeed_soc.h | 1 +
92
include/hw/arm/virt.h | 1 +
93
include/hw/i2c/aspeed_i2c.h | 16 ++
94
include/hw/ssi/aspeed_smc.h | 1 +
95
include/hw/watchdog/wdt_aspeed.h | 1 +
96
include/qemu/cutils.h | 1 +
97
target/arm/cpu.h | 20 +-
98
target/arm/helper.h | 3 +
99
target/arm/translate.h | 2 +
100
exec.c | 36 ++++
101
hw/arm/aspeed.c | 271 +++++++++++++----------
102
hw/arm/aspeed_ast2600.c | 25 ++-
103
hw/arm/aspeed_soc.c | 22 +-
104
hw/arm/sbsa-ref.c | 86 ++++----
105
hw/arm/virt-acpi-build.c | 21 +-
106
hw/arm/virt.c | 109 +++++-----
107
hw/gpio/aspeed_gpio.c | 1 +
108
hw/i2c/aspeed_i2c.c | 439 +++++++++++++++++++++++++++++++++++---
109
hw/intc/exynos4210_gic.c | 9 +-
110
hw/misc/aspeed_scu.c | 19 +-
111
hw/misc/aspeed_sdmc.c | 6 +-
112
hw/net/ftgmac100.c | 19 +-
113
hw/ssi/aspeed_smc.c | 63 ++++--
114
hw/timer/aspeed_timer.c | 17 +-
115
hw/watchdog/wdt_aspeed.c | 41 ++--
116
linux-user/elfload.c | 2 +
117
memory.c | 12 ++
118
migration/ram.c | 5 +-
119
target/arm/arm-powerctl.c | 3 +
120
target/arm/cpu.c | 33 +++
121
target/arm/cpu64.c | 1 +
122
target/arm/helper.c | 170 ++++++++++++++-
123
target/arm/op_helper.c | 22 ++
124
target/arm/translate-vfp.inc.c | 20 +-
125
target/arm/translate.c | 9 +-
126
target/arm/vfp_helper.c | 29 +++
127
util/cutils.c | 38 ++++
128
hw/i2c/trace-events | 9 +
129
tests/data/acpi/virt/DSDT | Bin 18470 -> 18462 bytes
130
tests/data/acpi/virt/DSDT.memhp | Bin 19807 -> 19799 bytes
131
tests/data/acpi/virt/DSDT.numamem | Bin 18470 -> 18462 bytes
132
45 files changed, 1273 insertions(+), 354 deletions(-)
133
diff view generated by jsdifflib
Deleted patch
1
From: Christophe Lyon <christophe.lyon@linaro.org>
2
1
3
This is derived from cortex-m4 description, adding DP support and FPv5
4
instructions with the corresponding flags in isar and mvfr2.
5
6
Checked that it could successfully execute
7
vrinta.f32 s15, s15
8
while cortex-m4 emulation rejects it with "illegal instruction".
9
10
Signed-off-by: Christophe Lyon <christophe.lyon@linaro.org>
11
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Message-id: 20191025090841.10299-1-christophe.lyon@linaro.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
target/arm/cpu.c | 33 +++++++++++++++++++++++++++++++++
17
1 file changed, 33 insertions(+)
18
19
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu.c
22
+++ b/target/arm/cpu.c
23
@@ -XXX,XX +XXX,XX @@ static void cortex_m4_initfn(Object *obj)
24
cpu->isar.id_isar6 = 0x00000000;
25
}
26
27
+static void cortex_m7_initfn(Object *obj)
28
+{
29
+ ARMCPU *cpu = ARM_CPU(obj);
30
+
31
+ set_feature(&cpu->env, ARM_FEATURE_V7);
32
+ set_feature(&cpu->env, ARM_FEATURE_M);
33
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
34
+ set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
35
+ set_feature(&cpu->env, ARM_FEATURE_VFP4);
36
+ cpu->midr = 0x411fc272; /* r1p2 */
37
+ cpu->pmsav7_dregion = 8;
38
+ cpu->isar.mvfr0 = 0x10110221;
39
+ cpu->isar.mvfr1 = 0x12000011;
40
+ cpu->isar.mvfr2 = 0x00000040;
41
+ cpu->id_pfr0 = 0x00000030;
42
+ cpu->id_pfr1 = 0x00000200;
43
+ cpu->id_dfr0 = 0x00100000;
44
+ cpu->id_afr0 = 0x00000000;
45
+ cpu->id_mmfr0 = 0x00100030;
46
+ cpu->id_mmfr1 = 0x00000000;
47
+ cpu->id_mmfr2 = 0x01000000;
48
+ cpu->id_mmfr3 = 0x00000000;
49
+ cpu->isar.id_isar0 = 0x01101110;
50
+ cpu->isar.id_isar1 = 0x02112000;
51
+ cpu->isar.id_isar2 = 0x20232231;
52
+ cpu->isar.id_isar3 = 0x01111131;
53
+ cpu->isar.id_isar4 = 0x01310132;
54
+ cpu->isar.id_isar5 = 0x00000000;
55
+ cpu->isar.id_isar6 = 0x00000000;
56
+}
57
+
58
static void cortex_m33_initfn(Object *obj)
59
{
60
ARMCPU *cpu = ARM_CPU(obj);
61
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_cpus[] = {
62
.class_init = arm_v7m_class_init },
63
{ .name = "cortex-m4", .initfn = cortex_m4_initfn,
64
.class_init = arm_v7m_class_init },
65
+ { .name = "cortex-m7", .initfn = cortex_m7_initfn,
66
+ .class_init = arm_v7m_class_init },
67
{ .name = "cortex-m33", .initfn = cortex_m33_initfn,
68
.class_init = arm_v7m_class_init },
69
{ .name = "cortex-r5", .initfn = cortex_r5_initfn },
70
--
71
2.20.1
72
73
diff view generated by jsdifflib
Deleted patch
1
From: David Gibson <david@gibson.dropbear.id.au>
2
1
3
exynos4210_gic_realize() prints the number of cpus into some temporary
4
buffers, but it only allows 3 bytes space for it. That's plenty:
5
existing machines will only ever set this value to EXYNOS4210_NCPUS
6
(2). But the compiler can't always figure that out, so some[*] gcc9
7
versions emit -Wformat-truncation warnings.
8
9
We can fix that by hinting the constraint to the compiler with a
10
suitably placed assert().
11
12
[*] The bizarre thing here, is that I've long gotten these warnings
13
compiling in a 32-bit x86 container as host - Fedora 30 with
14
gcc-9.2.1-1.fc30.i686 - but it compiles just fine on my normal
15
x86_64 host - Fedora 30 with and gcc-9.2.1-1.fc30.x86_64.
16
17
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
18
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
[PMM: deleted stray blank line]
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
23
hw/intc/exynos4210_gic.c | 9 ++++++++-
24
1 file changed, 8 insertions(+), 1 deletion(-)
25
26
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/intc/exynos4210_gic.c
29
+++ b/hw/intc/exynos4210_gic.c
30
@@ -XXX,XX +XXX,XX @@ static void exynos4210_gic_realize(DeviceState *dev, Error **errp)
31
char cpu_alias_name[sizeof(cpu_prefix) + 3];
32
char dist_alias_name[sizeof(cpu_prefix) + 3];
33
SysBusDevice *gicbusdev;
34
+ uint32_t n = s->num_cpu;
35
uint32_t i;
36
37
s->gic = qdev_create(NULL, "arm_gic");
38
@@ -XXX,XX +XXX,XX @@ static void exynos4210_gic_realize(DeviceState *dev, Error **errp)
39
memory_region_init(&s->dist_container, obj, "exynos4210-dist-container",
40
EXYNOS4210_EXT_GIC_DIST_REGION_SIZE);
41
42
- for (i = 0; i < s->num_cpu; i++) {
43
+ /*
44
+ * This clues in gcc that our on-stack buffers do, in fact have
45
+ * enough room for the cpu numbers. gcc 9.2.1 on 32-bit x86
46
+ * doesn't figure this out, otherwise and gives spurious warnings.
47
+ */
48
+ assert(n <= EXYNOS4210_NCPUS);
49
+ for (i = 0; i < n; i++) {
50
/* Map CPU interface per SMP Core */
51
sprintf(cpu_alias_name, "%s%x", cpu_prefix, i);
52
memory_region_init_alias(&s->cpu_alias[i], obj,
53
--
54
2.20.1
55
56
diff view generated by jsdifflib
1
From: Beata Michalska <beata.michalska@linaro.org>
1
From: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
2
2
3
ARMv8.2 introduced support for Data Cache Clean instructions
3
This adds for the Small Translation tables extension in AArch64 state.
4
to PoP (point-of-persistence) - DC CVAP and PoDP (point-of-deep-persistence)
5
- DV CVADP. Both specify conceptual points in a memory system where all writes
6
that are to reach them are considered persistent.
7
The support provided considers both to be actually the same so there is no
8
distinction between the two. If none is available (there is no backing store
9
for given memory) both will result in Data Cache Clean up to the point of
10
coherency. Otherwise sync for the specified range shall be performed.
11
4
12
Signed-off-by: Beata Michalska <beata.michalska@linaro.org>
5
Signed-off-by: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20191121000843.24844-5-beata.michalska@linaro.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
8
---
17
target/arm/cpu.h | 10 ++++++++
9
target/arm/cpu.h | 5 +++++
18
linux-user/elfload.c | 2 ++
10
target/arm/helper.c | 15 +++++++++++++--
19
target/arm/cpu64.c | 1 +
11
2 files changed, 18 insertions(+), 2 deletions(-)
20
target/arm/helper.c | 56 ++++++++++++++++++++++++++++++++++++++++++++
21
4 files changed, 69 insertions(+)
22
12
23
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
24
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/cpu.h
15
--- a/target/arm/cpu.h
26
+++ b/target/arm/cpu.h
16
+++ b/target/arm/cpu.h
27
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_frint(const ARMISARegisters *id)
17
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_uao(const ARMISARegisters *id)
28
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FRINTTS) != 0;
18
return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0;
29
}
19
}
30
20
31
+static inline bool isar_feature_aa64_dcpop(const ARMISARegisters *id)
21
+static inline bool isar_feature_aa64_st(const ARMISARegisters *id)
32
+{
22
+{
33
+ return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) != 0;
23
+ return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, ST) != 0;
34
+}
24
+}
35
+
25
+
36
+static inline bool isar_feature_aa64_dcpodp(const ARMISARegisters *id)
26
static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
37
+{
38
+ return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) >= 2;
39
+}
40
+
41
static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id)
42
{
27
{
43
/* We always set the AdvSIMD and FP fields identically wrt FP16. */
28
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;
44
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/linux-user/elfload.c
47
+++ b/linux-user/elfload.c
48
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
49
GET_FEATURE_ID(aa64_jscvt, ARM_HWCAP_A64_JSCVT);
50
GET_FEATURE_ID(aa64_sb, ARM_HWCAP_A64_SB);
51
GET_FEATURE_ID(aa64_condm_4, ARM_HWCAP_A64_FLAGM);
52
+ GET_FEATURE_ID(aa64_dcpop, ARM_HWCAP_A64_DCPOP);
53
54
return hwcaps;
55
}
56
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap2(void)
57
ARMCPU *cpu = ARM_CPU(thread_cpu);
58
uint32_t hwcaps = 0;
59
60
+ GET_FEATURE_ID(aa64_dcpodp, ARM_HWCAP2_A64_DCPODP);
61
GET_FEATURE_ID(aa64_condm_5, ARM_HWCAP2_A64_FLAGM2);
62
GET_FEATURE_ID(aa64_frint, ARM_HWCAP2_A64_FRINT);
63
64
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/cpu64.c
67
+++ b/target/arm/cpu64.c
68
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
69
cpu->isar.id_aa64isar0 = t;
70
71
t = cpu->isar.id_aa64isar1;
72
+ t = FIELD_DP64(t, ID_AA64ISAR1, DPB, 2);
73
t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1);
74
t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1);
75
t = FIELD_DP64(t, ID_AA64ISAR1, APA, 1); /* PAuth, architected only */
76
diff --git a/target/arm/helper.c b/target/arm/helper.c
29
diff --git a/target/arm/helper.c b/target/arm/helper.c
77
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
78
--- a/target/arm/helper.c
31
--- a/target/arm/helper.c
79
+++ b/target/arm/helper.c
32
+++ b/target/arm/helper.c
80
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo rndr_reginfo[] = {
33
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
81
.access = PL0_R, .readfn = rndr_readfn },
34
{
82
REGINFO_SENTINEL
35
uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
83
};
36
bool epd, hpd, using16k, using64k;
37
- int select, tsz, tbi;
38
+ int select, tsz, tbi, max_tsz;
39
40
if (!regime_has_2_ranges(mmu_idx)) {
41
select = 0;
42
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
43
hpd = extract64(tcr, 42, 1);
44
}
45
}
46
- tsz = MIN(tsz, 39); /* TODO: ARMv8.4-TTST */
84
+
47
+
85
+#ifndef CONFIG_USER_ONLY
48
+ if (cpu_isar_feature(aa64_st, env_archcpu(env))) {
86
+static void dccvap_writefn(CPUARMState *env, const ARMCPRegInfo *opaque,
49
+ max_tsz = 48 - using64k;
87
+ uint64_t value)
50
+ } else {
88
+{
51
+ max_tsz = 39;
89
+ ARMCPU *cpu = env_archcpu(env);
52
+ }
90
+ /* CTR_EL0 System register -> DminLine, bits [19:16] */
91
+ uint64_t dline_size = 4 << ((cpu->ctr >> 16) & 0xF);
92
+ uint64_t vaddr_in = (uint64_t) value;
93
+ uint64_t vaddr = vaddr_in & ~(dline_size - 1);
94
+ void *haddr;
95
+ int mem_idx = cpu_mmu_index(env, false);
96
+
53
+
97
+ /* This won't be crossing page boundaries */
54
+ tsz = MIN(tsz, max_tsz);
98
+ haddr = probe_read(env, vaddr, dline_size, mem_idx, GETPC());
55
tsz = MAX(tsz, 16); /* TODO: ARMv8.2-LVA */
99
+ if (haddr) {
56
57
/* Present TBI as a composite with TBID. */
58
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
59
if (!aarch64 || stride == 9) {
60
/* AArch32 or 4KB pages */
61
startlevel = 2 - sl0;
100
+
62
+
101
+ ram_addr_t offset;
63
+ if (cpu_isar_feature(aa64_st, cpu)) {
102
+ MemoryRegion *mr;
64
+ startlevel &= 3;
103
+
65
+ }
104
+ /* RCU lock is already being held */
66
} else {
105
+ mr = memory_region_from_host(haddr, &offset);
67
/* 16KB or 64KB pages */
106
+
68
startlevel = 3 - sl0;
107
+ if (mr) {
108
+ memory_region_do_writeback(mr, offset, dline_size);
109
+ }
110
+ }
111
+}
112
+
113
+static const ARMCPRegInfo dcpop_reg[] = {
114
+ { .name = "DC_CVAP", .state = ARM_CP_STATE_AA64,
115
+ .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 12, .opc2 = 1,
116
+ .access = PL0_W, .type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END,
117
+ .accessfn = aa64_cacheop_access, .writefn = dccvap_writefn },
118
+ REGINFO_SENTINEL
119
+};
120
+
121
+static const ARMCPRegInfo dcpodp_reg[] = {
122
+ { .name = "DC_CVADP", .state = ARM_CP_STATE_AA64,
123
+ .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 13, .opc2 = 1,
124
+ .access = PL0_W, .type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END,
125
+ .accessfn = aa64_cacheop_access, .writefn = dccvap_writefn },
126
+ REGINFO_SENTINEL
127
+};
128
+#endif /*CONFIG_USER_ONLY*/
129
+
130
#endif
131
132
static CPAccessResult access_predinv(CPUARMState *env, const ARMCPRegInfo *ri,
133
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
134
if (cpu_isar_feature(aa64_rndr, cpu)) {
135
define_arm_cp_regs(cpu, rndr_reginfo);
136
}
137
+#ifndef CONFIG_USER_ONLY
138
+ /* Data Cache clean instructions up to PoP */
139
+ if (cpu_isar_feature(aa64_dcpop, cpu)) {
140
+ define_one_arm_cp_reg(cpu, dcpop_reg);
141
+
142
+ if (cpu_isar_feature(aa64_dcpodp, cpu)) {
143
+ define_one_arm_cp_reg(cpu, dcpodp_reg);
144
+ }
145
+ }
146
+#endif /*CONFIG_USER_ONLY*/
147
#endif
148
149
/*
150
--
69
--
151
2.20.1
70
2.20.1
152
71
153
72
diff view generated by jsdifflib
1
From: Heyi Guo <guoheyi@huawei.com>
1
From: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
2
2
3
After the introduction of generic PCIe root port and PCIe-PCI bridge,
3
Signed-off-by: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
4
we will also have SHPC controller on ARM, so just enable SHPC native
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
hot plug.
6
7
Also update tests/data/acpi/virt/DSDT* to pass "make check".
8
9
Cc: Shannon Zhao <shannon.zhaosl@gmail.com>
10
Cc: Peter Maydell <peter.maydell@linaro.org>
11
Cc: "Michael S. Tsirkin" <mst@redhat.com>
12
Cc: Igor Mammedov <imammedo@redhat.com>
13
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
14
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
15
Signed-off-by: Heyi Guo <guoheyi@huawei.com>
16
Message-id: 20191209063719.23086-3-guoheyi@huawei.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
6
---
19
hw/arm/virt-acpi-build.c | 7 ++++++-
7
target/arm/cpu64.c | 1 +
20
tests/data/acpi/virt/DSDT | Bin 18462 -> 18462 bytes
8
1 file changed, 1 insertion(+)
21
tests/data/acpi/virt/DSDT.memhp | Bin 19799 -> 19799 bytes
22
tests/data/acpi/virt/DSDT.numamem | Bin 18462 -> 18462 bytes
23
4 files changed, 6 insertions(+), 1 deletion(-)
24
9
25
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
10
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
26
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/virt-acpi-build.c
12
--- a/target/arm/cpu64.c
28
+++ b/hw/arm/virt-acpi-build.c
13
+++ b/target/arm/cpu64.c
29
@@ -XXX,XX +XXX,XX @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
14
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
30
aml_create_dword_field(aml_arg(3), aml_int(8), "CDW3"));
15
t = cpu->isar.id_aa64mmfr2;
31
aml_append(ifctx, aml_store(aml_name("CDW2"), aml_name("SUPP")));
16
t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1);
32
aml_append(ifctx, aml_store(aml_name("CDW3"), aml_name("CTRL")));
17
t = FIELD_DP64(t, ID_AA64MMFR2, CNP, 1); /* TTCNP */
33
- aml_append(ifctx, aml_and(aml_name("CTRL"), aml_int(0x1D),
18
+ t = FIELD_DP64(t, ID_AA64MMFR2, ST, 1); /* TTST */
34
+
19
cpu->isar.id_aa64mmfr2 = t;
35
+ /*
20
36
+ * Allow OS control for all 5 features:
21
/* Replicate the same data to the 32-bit id registers. */
37
+ * PCIeHotplug SHPCHotplug PME AER PCIeCapability.
38
+ */
39
+ aml_append(ifctx, aml_and(aml_name("CTRL"), aml_int(0x1F),
40
aml_name("CTRL")));
41
42
ifctx1 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(0x1))));
43
diff --git a/tests/data/acpi/virt/DSDT b/tests/data/acpi/virt/DSDT
44
index XXXXXXX..XXXXXXX 100644
45
GIT binary patch
46
delta 28
47
kcmbO?fpOjhMlP3Nmk>D*1_q{tja=*8809zbbW3Ff0C~9xM*si-
48
49
delta 28
50
kcmbO?fpOjhMlP3Nmk>D*1_q|2ja=*87-cu_bW3Ff0C~j-M*si-
51
52
diff --git a/tests/data/acpi/virt/DSDT.memhp b/tests/data/acpi/virt/DSDT.memhp
53
index XXXXXXX..XXXXXXX 100644
54
GIT binary patch
55
delta 28
56
kcmcaUi}Cs_MlP3NmymE@1_mbija=*8809zbbeqQp0Eq|*2mk;8
57
58
delta 28
59
kcmcaUi}Cs_MlP3NmymE@1_ma@ja=*87-cu_beqQp0ErX{2mk;8
60
61
diff --git a/tests/data/acpi/virt/DSDT.numamem b/tests/data/acpi/virt/DSDT.numamem
62
index XXXXXXX..XXXXXXX 100644
63
GIT binary patch
64
delta 28
65
kcmbO?fpOjhMlP3Nmk>D*1_q{tja=*8809zbbW3Ff0C~9xM*si-
66
67
delta 28
68
kcmbO?fpOjhMlP3Nmk>D*1_q|2ja=*87-cu_bW3Ff0C~j-M*si-
69
70
--
22
--
71
2.20.1
23
2.20.1
72
24
73
25
diff view generated by jsdifflib
1
From: Cédric Le Goater <clg@kaod.org>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
Currently, we link the DRAM memory region to the FMC model (for DMAs)
3
SBSS -> SSBS
4
through a property alias at the SoC level. The I2C model will need a
5
similar region for DMA support, add a DRAM region property at the SoC
6
level for both model to use.
7
4
8
Signed-off-by: Cédric Le Goater <clg@kaod.org>
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
9
Reviewed-by: Joel Stanley <joel@jms.id.au>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Tested-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Cédric Le Goater <clg@kaod.org>
8
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
12
Message-id: 20191119141211.25716-4-clg@kaod.org
9
Message-id: 20210108185154.8108-2-leif@nuviainc.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
11
---
15
include/hw/arm/aspeed_soc.h | 1 +
12
target/arm/cpu.h | 2 +-
16
hw/arm/aspeed_ast2600.c | 7 +++++--
13
1 file changed, 1 insertion(+), 1 deletion(-)
17
hw/arm/aspeed_soc.c | 9 +++++++--
18
3 files changed, 13 insertions(+), 4 deletions(-)
19
14
20
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
21
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/arm/aspeed_soc.h
17
--- a/target/arm/cpu.h
23
+++ b/include/hw/arm/aspeed_soc.h
18
+++ b/target/arm/cpu.h
24
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSoCState {
19
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64PFR0, RAS, 28, 4)
25
ARMCPU cpu[ASPEED_CPUS_NUM];
20
FIELD(ID_AA64PFR0, SVE, 32, 4)
26
uint32_t num_cpus;
21
27
A15MPPrivState a7mpcore;
22
FIELD(ID_AA64PFR1, BT, 0, 4)
28
+ MemoryRegion *dram_mr;
23
-FIELD(ID_AA64PFR1, SBSS, 4, 4)
29
MemoryRegion sram;
24
+FIELD(ID_AA64PFR1, SSBS, 4, 4)
30
AspeedVICState vic;
25
FIELD(ID_AA64PFR1, MTE, 8, 4)
31
AspeedRtcState rtc;
26
FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4)
32
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/arm/aspeed_ast2600.c
35
+++ b/hw/arm/aspeed_ast2600.c
36
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2600_init(Object *obj)
37
typename);
38
object_property_add_alias(obj, "num-cs", OBJECT(&s->fmc), "num-cs",
39
&error_abort);
40
- object_property_add_alias(obj, "dram", OBJECT(&s->fmc), "dram",
41
- &error_abort);
42
43
for (i = 0; i < sc->spis_num; i++) {
44
snprintf(typename, sizeof(typename), "aspeed.spi%d-%s", i + 1, socname);
45
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
46
}
47
48
/* FMC, The number of CS is set at the board level */
49
+ object_property_set_link(OBJECT(&s->fmc), OBJECT(s->dram_mr), "dram", &err);
50
+ if (err) {
51
+ error_propagate(errp, err);
52
+ return;
53
+ }
54
object_property_set_int(OBJECT(&s->fmc), sc->memmap[ASPEED_SDRAM],
55
"sdram-base", &err);
56
if (err) {
57
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/hw/arm/aspeed_soc.c
60
+++ b/hw/arm/aspeed_soc.c
61
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj)
62
typename);
63
object_property_add_alias(obj, "num-cs", OBJECT(&s->fmc), "num-cs",
64
&error_abort);
65
- object_property_add_alias(obj, "dram", OBJECT(&s->fmc), "dram",
66
- &error_abort);
67
68
for (i = 0; i < sc->spis_num; i++) {
69
snprintf(typename, sizeof(typename), "aspeed.spi%d-%s", i + 1, socname);
70
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
71
aspeed_soc_get_irq(s, ASPEED_I2C));
72
73
/* FMC, The number of CS is set at the board level */
74
+ object_property_set_link(OBJECT(&s->fmc), OBJECT(s->dram_mr), "dram", &err);
75
+ if (err) {
76
+ error_propagate(errp, err);
77
+ return;
78
+ }
79
object_property_set_int(OBJECT(&s->fmc), sc->memmap[ASPEED_SDRAM],
80
"sdram-base", &err);
81
if (err) {
82
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
83
}
84
static Property aspeed_soc_properties[] = {
85
DEFINE_PROP_UINT32("num-cpus", AspeedSoCState, num_cpus, 0),
86
+ DEFINE_PROP_LINK("dram", AspeedSoCState, dram_mr, TYPE_MEMORY_REGION,
87
+ MemoryRegion *),
88
DEFINE_PROP_END_OF_LIST(),
89
};
90
27
91
--
28
--
92
2.20.1
29
2.20.1
93
30
94
31
diff view generated by jsdifflib
1
From: Alex Bennée <alex.bennee@linaro.org>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
A write to the SCR can change the effective EL by droppping the system
3
The AArch64 view of CLIDR_EL1 extends the ICB field to include also bit
4
from secure to non-secure mode. However if we use a cached current_el
4
32, as well as adding a Ttype<n> field when FEAT_MTE is implemented.
5
from before the change we'll rebuild the flags incorrectly. To fix
5
Extend the clidr field to be able to hold this context.
6
this we introduce the ARM_CP_NEWEL CP flag to indicate the new EL
7
should be used when recomputing the flags.
8
6
9
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
7
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
10
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Message-id: 20191212114734.6962-1-alex.bennee@linaro.org
10
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
13
Cc: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20210108185154.8108-3-leif@nuviainc.com
14
Message-Id: <20191209143723.6368-1-alex.bennee@linaro.org>
15
Cc: qemu-stable@nongnu.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
13
---
18
target/arm/cpu.h | 8 ++++++--
14
target/arm/cpu.h | 2 +-
19
target/arm/helper.h | 1 +
15
1 file changed, 1 insertion(+), 1 deletion(-)
20
target/arm/helper.c | 14 +++++++++++++-
21
target/arm/translate.c | 6 +++++-
22
4 files changed, 25 insertions(+), 4 deletions(-)
23
16
24
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
25
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/cpu.h
19
--- a/target/arm/cpu.h
27
+++ b/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
28
@@ -XXX,XX +XXX,XX @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid)
21
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
29
* RAISES_EXC is for when the read or write hook might raise an exception;
22
uint32_t id_afr0;
30
* the generated code will synchronize the CPU state before calling the hook
23
uint64_t id_aa64afr0;
31
* so that it is safe for the hook to call raise_exception().
24
uint64_t id_aa64afr1;
32
+ * NEWEL is for writes to registers that might change the exception
25
- uint32_t clidr;
33
+ * level - typically on older ARM chips. For those cases we need to
26
+ uint64_t clidr;
34
+ * re-read the new el when recomputing the translation flags.
27
uint64_t mp_affinity; /* MP ID without feature bits */
35
*/
28
/* The elements of this array are the CCSIDR values for each cache,
36
#define ARM_CP_SPECIAL 0x0001
29
* in the order L1DCache, L1ICache, L2DCache, L2ICache, etc.
37
#define ARM_CP_CONST 0x0002
38
@@ -XXX,XX +XXX,XX @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid)
39
#define ARM_CP_SVE 0x2000
40
#define ARM_CP_NO_GDB 0x4000
41
#define ARM_CP_RAISES_EXC 0x8000
42
+#define ARM_CP_NEWEL 0x10000
43
/* Used only as a terminator for ARMCPRegInfo lists */
44
-#define ARM_CP_SENTINEL 0xffff
45
+#define ARM_CP_SENTINEL 0xfffff
46
/* Mask of only the flag bits in a type field */
47
-#define ARM_CP_FLAG_MASK 0xf0ff
48
+#define ARM_CP_FLAG_MASK 0x1f0ff
49
50
/* Valid values for ARMCPRegInfo state field, indicating which of
51
* the AArch32 and AArch64 execution states this register is visible in.
52
diff --git a/target/arm/helper.h b/target/arm/helper.h
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/helper.h
55
+++ b/target/arm/helper.h
56
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(get_user_reg, i32, env, i32)
57
DEF_HELPER_3(set_user_reg, void, env, i32, i32)
58
59
DEF_HELPER_FLAGS_2(rebuild_hflags_m32, TCG_CALL_NO_RWG, void, env, int)
60
+DEF_HELPER_FLAGS_1(rebuild_hflags_a32_newel, TCG_CALL_NO_RWG, void, env)
61
DEF_HELPER_FLAGS_2(rebuild_hflags_a32, TCG_CALL_NO_RWG, void, env, int)
62
DEF_HELPER_FLAGS_2(rebuild_hflags_a64, TCG_CALL_NO_RWG, void, env, int)
63
64
diff --git a/target/arm/helper.c b/target/arm/helper.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/helper.c
67
+++ b/target/arm/helper.c
68
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
69
.opc0 = 3, .opc1 = 6, .crn = 1, .crm = 1, .opc2 = 0,
70
.access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.scr_el3),
71
.resetvalue = 0, .writefn = scr_write },
72
- { .name = "SCR", .type = ARM_CP_ALIAS,
73
+ { .name = "SCR", .type = ARM_CP_ALIAS | ARM_CP_NEWEL,
74
.cp = 15, .opc1 = 0, .crn = 1, .crm = 1, .opc2 = 0,
75
.access = PL1_RW, .accessfn = access_trap_aa32s_el1,
76
.fieldoffset = offsetoflow32(CPUARMState, cp15.scr_el3),
77
@@ -XXX,XX +XXX,XX @@ void HELPER(rebuild_hflags_m32)(CPUARMState *env, int el)
78
env->hflags = rebuild_hflags_m32(env, fp_el, mmu_idx);
79
}
80
81
+/*
82
+ * If we have triggered a EL state change we can't rely on the
83
+ * translator having passed it too us, we need to recompute.
84
+ */
85
+void HELPER(rebuild_hflags_a32_newel)(CPUARMState *env)
86
+{
87
+ int el = arm_current_el(env);
88
+ int fp_el = fp_exception_el(env, el);
89
+ ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
90
+ env->hflags = rebuild_hflags_a32(env, fp_el, mmu_idx);
91
+}
92
+
93
void HELPER(rebuild_hflags_a32)(CPUARMState *env, int el)
94
{
95
int fp_el = fp_exception_el(env, el);
96
diff --git a/target/arm/translate.c b/target/arm/translate.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/target/arm/translate.c
99
+++ b/target/arm/translate.c
100
@@ -XXX,XX +XXX,XX @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
101
if (arm_dc_feature(s, ARM_FEATURE_M)) {
102
gen_helper_rebuild_hflags_m32(cpu_env, tcg_el);
103
} else {
104
- gen_helper_rebuild_hflags_a32(cpu_env, tcg_el);
105
+ if (ri->type & ARM_CP_NEWEL) {
106
+ gen_helper_rebuild_hflags_a32_newel(cpu_env);
107
+ } else {
108
+ gen_helper_rebuild_hflags_a32(cpu_env, tcg_el);
109
+ }
110
}
111
tcg_temp_free_i32(tcg_el);
112
/*
113
--
30
--
114
2.20.1
31
2.20.1
115
32
116
33
diff view generated by jsdifflib
1
From: Heyi Guo <guoheyi@huawei.com>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
The last argument of AML bit and/or statement is the target variable,
3
When FEAT_MTE is implemented, the AArch64 view of CTR_EL0 adds the
4
so we don't need to use a NULL target and then an additional store
4
TminLine field in bits [37:32].
5
operation; using just aml_and() or aml_or() statement is enough.
5
Extend the ctr field to be able to hold this context.
6
6
7
Also update tests/data/acpi/virt/DSDT* to pass "make check".
7
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
8
8
Reviewed-by: Hao Wu <wuhaotsh@google.com>
9
Cc: Shannon Zhao <shannon.zhaosl@gmail.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Cc: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
11
Cc: "Michael S. Tsirkin" <mst@redhat.com>
11
Message-id: 20210108185154.8108-4-leif@nuviainc.com
12
Cc: Igor Mammedov <imammedo@redhat.com>
13
Suggested-by: Igor Mammedov <imammedo@redhat.com>
14
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
15
Signed-off-by: Heyi Guo <guoheyi@huawei.com>
16
Message-id: 20191209063719.23086-2-guoheyi@huawei.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
13
---
19
hw/arm/virt-acpi-build.c | 16 ++++++++--------
14
target/arm/cpu.h | 2 +-
20
tests/data/acpi/virt/DSDT | Bin 18470 -> 18462 bytes
15
1 file changed, 1 insertion(+), 1 deletion(-)
21
tests/data/acpi/virt/DSDT.memhp | Bin 19807 -> 19799 bytes
22
tests/data/acpi/virt/DSDT.numamem | Bin 18470 -> 18462 bytes
23
4 files changed, 8 insertions(+), 8 deletions(-)
24
16
25
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
26
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/arm/virt-acpi-build.c
19
--- a/target/arm/cpu.h
28
+++ b/hw/arm/virt-acpi-build.c
20
+++ b/target/arm/cpu.h
29
@@ -XXX,XX +XXX,XX @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
21
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
30
aml_create_dword_field(aml_arg(3), aml_int(8), "CDW3"));
22
uint64_t midr;
31
aml_append(ifctx, aml_store(aml_name("CDW2"), aml_name("SUPP")));
23
uint32_t revidr;
32
aml_append(ifctx, aml_store(aml_name("CDW3"), aml_name("CTRL")));
24
uint32_t reset_fpsid;
33
- aml_append(ifctx, aml_store(aml_and(aml_name("CTRL"), aml_int(0x1D), NULL),
25
- uint32_t ctr;
34
- aml_name("CTRL")));
26
+ uint64_t ctr;
35
+ aml_append(ifctx, aml_and(aml_name("CTRL"), aml_int(0x1D),
27
uint32_t reset_sctlr;
36
+ aml_name("CTRL")));
28
uint64_t pmceid0;
37
29
uint64_t pmceid1;
38
ifctx1 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(0x1))));
39
- aml_append(ifctx1, aml_store(aml_or(aml_name("CDW1"), aml_int(0x08), NULL),
40
- aml_name("CDW1")));
41
+ aml_append(ifctx1, aml_or(aml_name("CDW1"), aml_int(0x08),
42
+ aml_name("CDW1")));
43
aml_append(ifctx, ifctx1);
44
45
ifctx1 = aml_if(aml_lnot(aml_equal(aml_name("CDW3"), aml_name("CTRL"))));
46
- aml_append(ifctx1, aml_store(aml_or(aml_name("CDW1"), aml_int(0x10), NULL),
47
- aml_name("CDW1")));
48
+ aml_append(ifctx1, aml_or(aml_name("CDW1"), aml_int(0x10),
49
+ aml_name("CDW1")));
50
aml_append(ifctx, ifctx1);
51
52
aml_append(ifctx, aml_store(aml_name("CTRL"), aml_name("CDW3")));
53
@@ -XXX,XX +XXX,XX @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
54
aml_append(method, ifctx);
55
56
elsectx = aml_else();
57
- aml_append(elsectx, aml_store(aml_or(aml_name("CDW1"), aml_int(4), NULL),
58
- aml_name("CDW1")));
59
+ aml_append(elsectx, aml_or(aml_name("CDW1"), aml_int(4),
60
+ aml_name("CDW1")));
61
aml_append(elsectx, aml_return(aml_arg(3)));
62
aml_append(method, elsectx);
63
aml_append(dev, method);
64
diff --git a/tests/data/acpi/virt/DSDT b/tests/data/acpi/virt/DSDT
65
index XXXXXXX..XXXXXXX 100644
66
GIT binary patch
67
delta 133
68
zcmZ2BfpOjhMlP3Nmk>D*1_q|2iCof5o%I{lJ2{y;?{412x!p#<jWgaq*qNm(o59&7
69
z+;D-%<VrV7_iE>mARjJS5V=5L(&S9WT970c2Uv;Nq{%?q7$gZ1761tsfcPNsCD{x4
70
MAmS{W8QoPG0j8@bzW@LL
71
72
delta 141
73
zcmbO?fpOUcMlP3Nmk>1%1_q`n6S<_B8XGpMcXBc{-rKy1bGwazA7{LOuro_nHiNTE
74
zxZwi7$(3%F{sq;}AwfP|vJ4<<fzYJMnT!RsAbBnhh%$*ulYv}gkTg_604z}e5&_99
75
R$zCV`m0@An{L@X95dZ+BD!u>!
76
77
diff --git a/tests/data/acpi/virt/DSDT.memhp b/tests/data/acpi/virt/DSDT.memhp
78
index XXXXXXX..XXXXXXX 100644
79
GIT binary patch
80
delta 132
81
zcmcaVi}Cs_MlP3NmymE@1_ma@iCof*O&is^IGH-{Zr;SX-A2HTGu}VgnWZb6!PzC;
82
zaDm6<N;gaQYUhw3A1+xCxj<mj<V?m|kR%reSc%xA$w1l|Bnc4~00|d>_#p8m*$ep~
83
L;w+mP-Q(B*s{AMU
84
85
delta 140
86
zcmcaUi}C&}MlP3Nmymd01_maViCof*T^rT9IGGynZQjJW-A2HVGu}VgnWZb6!PzC;
87
zaDm_CN;gaYf@<fGARjJS1`xGCXwu|N#)4XqJQoK<nZ%^YK&~-J8Y&?GmM8#;fMk|r
88
QFBE{vurO@?=@!QZ00dYn_y7O^
89
90
diff --git a/tests/data/acpi/virt/DSDT.numamem b/tests/data/acpi/virt/DSDT.numamem
91
index XXXXXXX..XXXXXXX 100644
92
GIT binary patch
93
delta 133
94
zcmZ2BfpOjhMlP3Nmk>D*1_q|2iCof5o%I{lJ2{y;?{412x!p#<jWgaq*qNm(o59&7
95
z+;D-%<VrV7_iE>mARjJS5V=5L(&S9WT970c2Uv;Nq{%?q7$gZ1761tsfcPNsCD{x4
96
MAmS{W8QoPG0j8@bzW@LL
97
98
delta 141
99
zcmbO?fpOUcMlP3Nmk>1%1_q`n6S<_B8XGpMcXBc{-rKy1bGwazA7{LOuro_nHiNTE
100
zxZwi7$(3%F{sq;}AwfP|vJ4<<fzYJMnT!RsAbBnhh%$*ulYv}gkTg_604z}e5&_99
101
R$zCV`m0@An{L@X95dZ+BD!u>!
102
103
--
30
--
104
2.20.1
31
2.20.1
105
32
106
33
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
Make the gic a field in the machine state, and instead of filling
3
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
4
an array of qemu_irq and passing it around, directly call
4
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
5
qdev_get_gpio_in() on the gic field.
5
Message-id: 20210108185154.8108-5-leif@nuviainc.com
6
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Message-id: 20191206162303.30338-1-philmd@redhat.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
7
---
12
hw/arm/sbsa-ref.c | 86 +++++++++++++++++++++++------------------------
8
target/arm/cpu.h | 31 +++++++++++++++++++++++++++++++
13
1 file changed, 42 insertions(+), 44 deletions(-)
9
1 file changed, 31 insertions(+)
14
10
15
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
11
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/sbsa-ref.c
13
--- a/target/arm/cpu.h
18
+++ b/hw/arm/sbsa-ref.c
14
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@ typedef struct {
15
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_FPCCR, ASPEN, 31, 1)
20
void *fdt;
16
/*
21
int fdt_size;
17
* System register ID fields.
22
int psci_conduit;
18
*/
23
+ DeviceState *gic;
19
+FIELD(CLIDR_EL1, CTYPE1, 0, 3)
24
PFlashCFI01 *flash[2];
20
+FIELD(CLIDR_EL1, CTYPE2, 3, 3)
25
} SBSAMachineState;
21
+FIELD(CLIDR_EL1, CTYPE3, 6, 3)
26
22
+FIELD(CLIDR_EL1, CTYPE4, 9, 3)
27
@@ -XXX,XX +XXX,XX @@ static void create_secure_ram(SBSAMachineState *sms,
23
+FIELD(CLIDR_EL1, CTYPE5, 12, 3)
28
memory_region_add_subregion(secure_sysmem, base, secram);
24
+FIELD(CLIDR_EL1, CTYPE6, 15, 3)
29
}
25
+FIELD(CLIDR_EL1, CTYPE7, 18, 3)
30
26
+FIELD(CLIDR_EL1, LOUIS, 21, 3)
31
-static void create_gic(SBSAMachineState *sms, qemu_irq *pic)
27
+FIELD(CLIDR_EL1, LOC, 24, 3)
32
+static void create_gic(SBSAMachineState *sms)
28
+FIELD(CLIDR_EL1, LOUU, 27, 3)
33
{
29
+FIELD(CLIDR_EL1, ICB, 30, 3)
34
unsigned int smp_cpus = MACHINE(sms)->smp.cpus;
30
+
35
- DeviceState *gicdev;
31
+/* When FEAT_CCIDX is implemented */
36
SysBusDevice *gicbusdev;
32
+FIELD(CCSIDR_EL1, CCIDX_LINESIZE, 0, 3)
37
const char *gictype;
33
+FIELD(CCSIDR_EL1, CCIDX_ASSOCIATIVITY, 3, 21)
38
uint32_t redist0_capacity, redist0_count;
34
+FIELD(CCSIDR_EL1, CCIDX_NUMSETS, 32, 24)
39
@@ -XXX,XX +XXX,XX @@ static void create_gic(SBSAMachineState *sms, qemu_irq *pic)
35
+
40
36
+/* When FEAT_CCIDX is not implemented */
41
gictype = gicv3_class_name();
37
+FIELD(CCSIDR_EL1, LINESIZE, 0, 3)
42
38
+FIELD(CCSIDR_EL1, ASSOCIATIVITY, 3, 10)
43
- gicdev = qdev_create(NULL, gictype);
39
+FIELD(CCSIDR_EL1, NUMSETS, 13, 15)
44
- qdev_prop_set_uint32(gicdev, "revision", 3);
40
+
45
- qdev_prop_set_uint32(gicdev, "num-cpu", smp_cpus);
41
+FIELD(CTR_EL0, IMINLINE, 0, 4)
46
+ sms->gic = qdev_create(NULL, gictype);
42
+FIELD(CTR_EL0, L1IP, 14, 2)
47
+ qdev_prop_set_uint32(sms->gic, "revision", 3);
43
+FIELD(CTR_EL0, DMINLINE, 16, 4)
48
+ qdev_prop_set_uint32(sms->gic, "num-cpu", smp_cpus);
44
+FIELD(CTR_EL0, ERG, 20, 4)
49
/*
45
+FIELD(CTR_EL0, CWG, 24, 4)
50
* Note that the num-irq property counts both internal and external
46
+FIELD(CTR_EL0, IDC, 28, 1)
51
* interrupts; there are always 32 of the former (mandated by GIC spec).
47
+FIELD(CTR_EL0, DIC, 29, 1)
52
*/
48
+FIELD(CTR_EL0, TMINLINE, 32, 6)
53
- qdev_prop_set_uint32(gicdev, "num-irq", NUM_IRQS + 32);
49
+
54
- qdev_prop_set_bit(gicdev, "has-security-extensions", true);
50
FIELD(MIDR_EL1, REVISION, 0, 4)
55
+ qdev_prop_set_uint32(sms->gic, "num-irq", NUM_IRQS + 32);
51
FIELD(MIDR_EL1, PARTNUM, 4, 12)
56
+ qdev_prop_set_bit(sms->gic, "has-security-extensions", true);
52
FIELD(MIDR_EL1, ARCHITECTURE, 16, 4)
57
58
redist0_capacity =
59
sbsa_ref_memmap[SBSA_GIC_REDIST].size / GICV3_REDIST_SIZE;
60
redist0_count = MIN(smp_cpus, redist0_capacity);
61
62
- qdev_prop_set_uint32(gicdev, "len-redist-region-count", 1);
63
- qdev_prop_set_uint32(gicdev, "redist-region-count[0]", redist0_count);
64
+ qdev_prop_set_uint32(sms->gic, "len-redist-region-count", 1);
65
+ qdev_prop_set_uint32(sms->gic, "redist-region-count[0]", redist0_count);
66
67
- qdev_init_nofail(gicdev);
68
- gicbusdev = SYS_BUS_DEVICE(gicdev);
69
+ qdev_init_nofail(sms->gic);
70
+ gicbusdev = SYS_BUS_DEVICE(sms->gic);
71
sysbus_mmio_map(gicbusdev, 0, sbsa_ref_memmap[SBSA_GIC_DIST].base);
72
sysbus_mmio_map(gicbusdev, 1, sbsa_ref_memmap[SBSA_GIC_REDIST].base);
73
74
@@ -XXX,XX +XXX,XX @@ static void create_gic(SBSAMachineState *sms, qemu_irq *pic)
75
76
for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
77
qdev_connect_gpio_out(cpudev, irq,
78
- qdev_get_gpio_in(gicdev,
79
+ qdev_get_gpio_in(sms->gic,
80
ppibase + timer_irq[irq]));
81
}
82
83
qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", 0,
84
- qdev_get_gpio_in(gicdev, ppibase
85
+ qdev_get_gpio_in(sms->gic, ppibase
86
+ ARCH_GIC_MAINT_IRQ));
87
qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
88
- qdev_get_gpio_in(gicdev, ppibase
89
+ qdev_get_gpio_in(sms->gic, ppibase
90
+ VIRTUAL_PMU_IRQ));
91
92
sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
93
@@ -XXX,XX +XXX,XX @@ static void create_gic(SBSAMachineState *sms, qemu_irq *pic)
94
sysbus_connect_irq(gicbusdev, i + 3 * smp_cpus,
95
qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
96
}
97
-
98
- for (i = 0; i < NUM_IRQS; i++) {
99
- pic[i] = qdev_get_gpio_in(gicdev, i);
100
- }
101
}
102
103
-static void create_uart(const SBSAMachineState *sms, qemu_irq *pic, int uart,
104
+static void create_uart(const SBSAMachineState *sms, int uart,
105
MemoryRegion *mem, Chardev *chr)
106
{
107
hwaddr base = sbsa_ref_memmap[uart].base;
108
@@ -XXX,XX +XXX,XX @@ static void create_uart(const SBSAMachineState *sms, qemu_irq *pic, int uart,
109
qdev_init_nofail(dev);
110
memory_region_add_subregion(mem, base,
111
sysbus_mmio_get_region(s, 0));
112
- sysbus_connect_irq(s, 0, pic[irq]);
113
+ sysbus_connect_irq(s, 0, qdev_get_gpio_in(sms->gic, irq));
114
}
115
116
-static void create_rtc(const SBSAMachineState *sms, qemu_irq *pic)
117
+static void create_rtc(const SBSAMachineState *sms)
118
{
119
hwaddr base = sbsa_ref_memmap[SBSA_RTC].base;
120
int irq = sbsa_ref_irqmap[SBSA_RTC];
121
122
- sysbus_create_simple("pl031", base, pic[irq]);
123
+ sysbus_create_simple("pl031", base, qdev_get_gpio_in(sms->gic, irq));
124
}
125
126
static DeviceState *gpio_key_dev;
127
@@ -XXX,XX +XXX,XX @@ static Notifier sbsa_ref_powerdown_notifier = {
128
.notify = sbsa_ref_powerdown_req
129
};
130
131
-static void create_gpio(const SBSAMachineState *sms, qemu_irq *pic)
132
+static void create_gpio(const SBSAMachineState *sms)
133
{
134
DeviceState *pl061_dev;
135
hwaddr base = sbsa_ref_memmap[SBSA_GPIO].base;
136
int irq = sbsa_ref_irqmap[SBSA_GPIO];
137
138
- pl061_dev = sysbus_create_simple("pl061", base, pic[irq]);
139
+ pl061_dev = sysbus_create_simple("pl061", base,
140
+ qdev_get_gpio_in(sms->gic, irq));
141
142
gpio_key_dev = sysbus_create_simple("gpio-key", -1,
143
qdev_get_gpio_in(pl061_dev, 3));
144
@@ -XXX,XX +XXX,XX @@ static void create_gpio(const SBSAMachineState *sms, qemu_irq *pic)
145
qemu_register_powerdown_notifier(&sbsa_ref_powerdown_notifier);
146
}
147
148
-static void create_ahci(const SBSAMachineState *sms, qemu_irq *pic)
149
+static void create_ahci(const SBSAMachineState *sms)
150
{
151
hwaddr base = sbsa_ref_memmap[SBSA_AHCI].base;
152
int irq = sbsa_ref_irqmap[SBSA_AHCI];
153
@@ -XXX,XX +XXX,XX @@ static void create_ahci(const SBSAMachineState *sms, qemu_irq *pic)
154
qdev_prop_set_uint32(dev, "num-ports", NUM_SATA_PORTS);
155
qdev_init_nofail(dev);
156
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
157
- sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irq]);
158
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(sms->gic, irq));
159
160
sysahci = SYSBUS_AHCI(dev);
161
ahci = &sysahci->ahci;
162
@@ -XXX,XX +XXX,XX @@ static void create_ahci(const SBSAMachineState *sms, qemu_irq *pic)
163
}
164
}
165
166
-static void create_ehci(const SBSAMachineState *sms, qemu_irq *pic)
167
+static void create_ehci(const SBSAMachineState *sms)
168
{
169
hwaddr base = sbsa_ref_memmap[SBSA_EHCI].base;
170
int irq = sbsa_ref_irqmap[SBSA_EHCI];
171
172
- sysbus_create_simple("platform-ehci-usb", base, pic[irq]);
173
+ sysbus_create_simple("platform-ehci-usb", base,
174
+ qdev_get_gpio_in(sms->gic, irq));
175
}
176
177
-static void create_smmu(const SBSAMachineState *sms, qemu_irq *pic,
178
- PCIBus *bus)
179
+static void create_smmu(const SBSAMachineState *sms, PCIBus *bus)
180
{
181
hwaddr base = sbsa_ref_memmap[SBSA_SMMU].base;
182
int irq = sbsa_ref_irqmap[SBSA_SMMU];
183
@@ -XXX,XX +XXX,XX @@ static void create_smmu(const SBSAMachineState *sms, qemu_irq *pic,
184
qdev_init_nofail(dev);
185
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
186
for (i = 0; i < NUM_SMMU_IRQS; i++) {
187
- sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]);
188
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
189
+ qdev_get_gpio_in(sms->gic, irq + 1));
190
}
191
}
192
193
-static void create_pcie(SBSAMachineState *sms, qemu_irq *pic)
194
+static void create_pcie(SBSAMachineState *sms)
195
{
196
hwaddr base_ecam = sbsa_ref_memmap[SBSA_PCIE_ECAM].base;
197
hwaddr size_ecam = sbsa_ref_memmap[SBSA_PCIE_ECAM].size;
198
@@ -XXX,XX +XXX,XX @@ static void create_pcie(SBSAMachineState *sms, qemu_irq *pic)
199
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, base_pio);
200
201
for (i = 0; i < GPEX_NUM_IRQS; i++) {
202
- sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]);
203
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
204
+ qdev_get_gpio_in(sms->gic, irq + 1));
205
gpex_set_irq_num(GPEX_HOST(dev), i, irq + i);
206
}
207
208
@@ -XXX,XX +XXX,XX @@ static void create_pcie(SBSAMachineState *sms, qemu_irq *pic)
209
210
pci_create_simple(pci->bus, -1, "VGA");
211
212
- create_smmu(sms, pic, pci->bus);
213
+ create_smmu(sms, pci->bus);
214
}
215
216
static void *sbsa_ref_dtb(const struct arm_boot_info *binfo, int *fdt_size)
217
@@ -XXX,XX +XXX,XX @@ static void sbsa_ref_init(MachineState *machine)
218
bool firmware_loaded;
219
const CPUArchIdList *possible_cpus;
220
int n, sbsa_max_cpus;
221
- qemu_irq pic[NUM_IRQS];
222
223
if (strcmp(machine->cpu_type, ARM_CPU_TYPE_NAME("cortex-a57"))) {
224
error_report("sbsa-ref: CPU type other than the built-in "
225
@@ -XXX,XX +XXX,XX @@ static void sbsa_ref_init(MachineState *machine)
226
227
create_secure_ram(sms, secure_sysmem);
228
229
- create_gic(sms, pic);
230
+ create_gic(sms);
231
232
- create_uart(sms, pic, SBSA_UART, sysmem, serial_hd(0));
233
- create_uart(sms, pic, SBSA_SECURE_UART, secure_sysmem, serial_hd(1));
234
+ create_uart(sms, SBSA_UART, sysmem, serial_hd(0));
235
+ create_uart(sms, SBSA_SECURE_UART, secure_sysmem, serial_hd(1));
236
/* Second secure UART for RAS and MM from EL0 */
237
- create_uart(sms, pic, SBSA_SECURE_UART_MM, secure_sysmem, serial_hd(2));
238
+ create_uart(sms, SBSA_SECURE_UART_MM, secure_sysmem, serial_hd(2));
239
240
- create_rtc(sms, pic);
241
+ create_rtc(sms);
242
243
- create_gpio(sms, pic);
244
+ create_gpio(sms);
245
246
- create_ahci(sms, pic);
247
+ create_ahci(sms);
248
249
- create_ehci(sms, pic);
250
+ create_ehci(sms);
251
252
- create_pcie(sms, pic);
253
+ create_pcie(sms);
254
255
sms->bootinfo.ram_size = machine->ram_size;
256
sms->bootinfo.nb_cpus = smp_cpus;
257
--
53
--
258
2.20.1
54
2.20.1
259
55
260
56
diff view generated by jsdifflib
1
From: Marc Zyngier <maz@kernel.org>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
HSTR_EL2 offers a way to trap ranges of CP15 system register
3
Add entries present in ARM DDI 0487F.c (August 2020).
4
accesses to EL2, and it looks like this register is completely
5
ignored by QEMU.
6
4
7
To avoid adding extra .accessfn filters all over the place (which
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
8
would have a direct performance impact), let's add a new TB flag
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
that gets set whenever HSTR_EL2 is non-zero and that QEMU translates
7
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
10
a context where this trap has a chance to apply, and only generate
8
Message-id: 20210108185154.8108-6-leif@nuviainc.com
11
the extra access check if the hypervisor is actively using this feature.
12
13
Tested with a hand-crafted KVM guest accessing CBAR.
14
15
Signed-off-by: Marc Zyngier <maz@kernel.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20191201122018.25808-5-maz@kernel.org
18
[PMM: use is_a64(); fix comment syntax]
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
10
---
21
target/arm/cpu.h | 2 ++
11
target/arm/cpu.h | 15 +++++++++++++++
22
target/arm/translate.h | 2 ++
12
1 file changed, 15 insertions(+)
23
target/arm/helper.c | 6 ++++++
24
target/arm/op_helper.c | 22 ++++++++++++++++++++++
25
target/arm/translate.c | 3 ++-
26
5 files changed, 34 insertions(+), 1 deletion(-)
27
13
28
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
29
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/cpu.h
16
--- a/target/arm/cpu.h
31
+++ b/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
32
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, NS, 6, 1)
18
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64ISAR1, GPI, 28, 4)
33
FIELD(TBFLAG_A32, VFPEN, 7, 1) /* Partially cached, minus FPEXC. */
19
FIELD(ID_AA64ISAR1, FRINTTS, 32, 4)
34
FIELD(TBFLAG_A32, CONDEXEC, 8, 8) /* Not cached. */
20
FIELD(ID_AA64ISAR1, SB, 36, 4)
35
FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
21
FIELD(ID_AA64ISAR1, SPECRES, 40, 4)
36
+FIELD(TBFLAG_A32, HSTR_ACTIVE, 17, 1)
22
+FIELD(ID_AA64ISAR1, BF16, 44, 4)
37
+
23
+FIELD(ID_AA64ISAR1, DGH, 48, 4)
38
/* For M profile only, set if FPCCR.LSPACT is set */
24
+FIELD(ID_AA64ISAR1, I8MM, 52, 4)
39
FIELD(TBFLAG_A32, LSPACT, 18, 1) /* Not cached. */
25
40
/* For M profile only, set if we must create a new FP context */
26
FIELD(ID_AA64PFR0, EL0, 0, 4)
41
diff --git a/target/arm/translate.h b/target/arm/translate.h
27
FIELD(ID_AA64PFR0, EL1, 4, 4)
42
index XXXXXXX..XXXXXXX 100644
28
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64PFR0, ADVSIMD, 20, 4)
43
--- a/target/arm/translate.h
29
FIELD(ID_AA64PFR0, GIC, 24, 4)
44
+++ b/target/arm/translate.h
30
FIELD(ID_AA64PFR0, RAS, 28, 4)
45
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
31
FIELD(ID_AA64PFR0, SVE, 32, 4)
46
bool pauth_active;
32
+FIELD(ID_AA64PFR0, SEL2, 36, 4)
47
/* True with v8.5-BTI and SCTLR_ELx.BT* set. */
33
+FIELD(ID_AA64PFR0, MPAM, 40, 4)
48
bool bt;
34
+FIELD(ID_AA64PFR0, AMU, 44, 4)
49
+ /* True if any CP15 access is trapped by HSTR_EL2 */
35
+FIELD(ID_AA64PFR0, DIT, 48, 4)
50
+ bool hstr_active;
36
+FIELD(ID_AA64PFR0, CSV2, 56, 4)
51
/*
37
+FIELD(ID_AA64PFR0, CSV3, 60, 4)
52
* >= 0, a copy of PSTATE.BTYPE, which will be 0 without v8.5-BTI.
38
53
* < 0, set by the current instruction.
39
FIELD(ID_AA64PFR1, BT, 0, 4)
54
diff --git a/target/arm/helper.c b/target/arm/helper.c
40
FIELD(ID_AA64PFR1, SSBS, 4, 4)
55
index XXXXXXX..XXXXXXX 100644
41
FIELD(ID_AA64PFR1, MTE, 8, 4)
56
--- a/target/arm/helper.c
42
FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4)
57
+++ b/target/arm/helper.c
43
+FIELD(ID_AA64PFR1, MPAM_FRAC, 16, 4)
58
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_a32(CPUARMState *env, int fp_el,
44
59
if (arm_el_is_aa64(env, 1)) {
45
FIELD(ID_AA64MMFR0, PARANGE, 0, 4)
60
flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
46
FIELD(ID_AA64MMFR0, ASIDBITS, 4, 4)
61
}
47
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64MMFR0, TGRAN16_2, 32, 4)
62
+
48
FIELD(ID_AA64MMFR0, TGRAN64_2, 36, 4)
63
+ if (arm_current_el(env) < 2 && env->cp15.hstr_el2 &&
49
FIELD(ID_AA64MMFR0, TGRAN4_2, 40, 4)
64
+ (arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
50
FIELD(ID_AA64MMFR0, EXS, 44, 4)
65
+ flags = FIELD_DP32(flags, TBFLAG_A32, HSTR_ACTIVE, 1);
51
+FIELD(ID_AA64MMFR0, FGT, 56, 4)
66
+ }
52
+FIELD(ID_AA64MMFR0, ECV, 60, 4)
67
+
53
68
return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
54
FIELD(ID_AA64MMFR1, HAFDBS, 0, 4)
69
}
55
FIELD(ID_AA64MMFR1, VMIDBITS, 4, 4)
70
56
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64MMFR1, LO, 16, 4)
71
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
57
FIELD(ID_AA64MMFR1, PAN, 20, 4)
72
index XXXXXXX..XXXXXXX 100644
58
FIELD(ID_AA64MMFR1, SPECSEI, 24, 4)
73
--- a/target/arm/op_helper.c
59
FIELD(ID_AA64MMFR1, XNX, 28, 4)
74
+++ b/target/arm/op_helper.c
60
+FIELD(ID_AA64MMFR1, TWED, 32, 4)
75
@@ -XXX,XX +XXX,XX @@ void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome,
61
+FIELD(ID_AA64MMFR1, ETS, 36, 4)
76
raise_exception(env, EXCP_UDEF, syndrome, exception_target_el(env));
62
77
}
63
FIELD(ID_AA64MMFR2, CNP, 0, 4)
78
64
FIELD(ID_AA64MMFR2, UAO, 4, 4)
79
+ /*
65
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64DFR0, CTX_CMPS, 28, 4)
80
+ * Check for an EL2 trap due to HSTR_EL2. We expect EL0 accesses
66
FIELD(ID_AA64DFR0, PMSVER, 32, 4)
81
+ * to sysregs non accessible at EL0 to have UNDEF-ed already.
67
FIELD(ID_AA64DFR0, DOUBLELOCK, 36, 4)
82
+ */
68
FIELD(ID_AA64DFR0, TRACEFILT, 40, 4)
83
+ if (!is_a64(env) && arm_current_el(env) < 2 && ri->cp == 15 &&
69
+FIELD(ID_AA64DFR0, MTPMU, 48, 4)
84
+ (arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE)) {
70
85
+ uint32_t mask = 1 << ri->crn;
71
FIELD(ID_DFR0, COPDBG, 0, 4)
86
+
72
FIELD(ID_DFR0, COPSDBG, 4, 4)
87
+ if (ri->type & ARM_CP_64BIT) {
88
+ mask = 1 << ri->crm;
89
+ }
90
+
91
+ /* T4 and T14 are RES0 */
92
+ mask &= ~((1 << 4) | (1 << 14));
93
+
94
+ if (env->cp15.hstr_el2 & mask) {
95
+ target_el = 2;
96
+ goto exept;
97
+ }
98
+ }
99
+
100
if (!ri->accessfn) {
101
return;
102
}
103
@@ -XXX,XX +XXX,XX @@ void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome,
104
g_assert_not_reached();
105
}
106
107
+exept:
108
raise_exception(env, EXCP_UDEF, syndrome, target_el);
109
}
110
111
diff --git a/target/arm/translate.c b/target/arm/translate.c
112
index XXXXXXX..XXXXXXX 100644
113
--- a/target/arm/translate.c
114
+++ b/target/arm/translate.c
115
@@ -XXX,XX +XXX,XX @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
116
return 1;
117
}
118
119
- if (ri->accessfn ||
120
+ if (s->hstr_active || ri->accessfn ||
121
(arm_dc_feature(s, ARM_FEATURE_XSCALE) && cpnum < 14)) {
122
/* Emit code to perform further access permissions checks at
123
* runtime; this may result in an exception.
124
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
125
!arm_el_is_aa64(env, 3);
126
dc->thumb = FIELD_EX32(tb_flags, TBFLAG_A32, THUMB);
127
dc->sctlr_b = FIELD_EX32(tb_flags, TBFLAG_A32, SCTLR_B);
128
+ dc->hstr_active = FIELD_EX32(tb_flags, TBFLAG_A32, HSTR_ACTIVE);
129
dc->be_data = FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
130
condexec = FIELD_EX32(tb_flags, TBFLAG_A32, CONDEXEC);
131
dc->condexec_mask = (condexec & 0xf) << 1;
132
--
73
--
133
2.20.1
74
2.20.1
134
75
135
76
diff view generated by jsdifflib
1
From: Cédric Le Goater <clg@kaod.org>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
The Tacoma BMC board is replacement board for the BMC of the OpenPOWER
3
Add entries present in ARM DDI 0487F.c (August 2020).
4
Witherspoon system. It uses a AST2600 SoC instead of a AST2500 and the
5
I2C layout is the same as it controls the same main board. Used for HW
6
bringup.
7
4
8
Signed-off-by: Cédric Le Goater <clg@kaod.org>
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
9
Reviewed-by: Joel Stanley <joel@jms.id.au>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Cédric Le Goater <clg@kaod.org>
7
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
11
Message-id: 20191119141211.25716-15-clg@kaod.org
8
Message-id: 20210108185154.8108-7-leif@nuviainc.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
10
---
14
hw/arm/aspeed.c | 28 ++++++++++++++++++++++++++++
11
target/arm/cpu.h | 28 ++++++++++++++++++++++++++++
15
1 file changed, 28 insertions(+)
12
1 file changed, 28 insertions(+)
16
13
17
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/aspeed.c
16
--- a/target/arm/cpu.h
20
+++ b/hw/arm/aspeed.c
17
+++ b/target/arm/cpu.h
21
@@ -XXX,XX +XXX,XX @@ struct AspeedBoardState {
18
@@ -XXX,XX +XXX,XX @@ FIELD(ID_ISAR6, DP, 4, 4)
22
#define AST2600_EVB_HW_STRAP1 0x000000C0
19
FIELD(ID_ISAR6, FHM, 8, 4)
23
#define AST2600_EVB_HW_STRAP2 0x00000003
20
FIELD(ID_ISAR6, SB, 12, 4)
24
21
FIELD(ID_ISAR6, SPECRES, 16, 4)
25
+/* Tacoma hardware value */
22
+FIELD(ID_ISAR6, BF16, 20, 4)
26
+#define TACOMA_BMC_HW_STRAP1 0x00000000
23
+FIELD(ID_ISAR6, I8MM, 24, 4)
27
+#define TACOMA_BMC_HW_STRAP2 0x00000000
24
25
FIELD(ID_MMFR0, VMSA, 0, 4)
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)
28
+
39
+
29
/*
40
+FIELD(ID_MMFR2, L1HVDFG, 0, 4)
30
* The max ram region is for firmwares that scan the address space
41
+FIELD(ID_MMFR2, L1HVDBG, 4, 4)
31
* with load/store to guess how much RAM the SoC has.
42
+FIELD(ID_MMFR2, L1HVDRNG, 8, 4)
32
@@ -XXX,XX +XXX,XX @@ static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
43
+FIELD(ID_MMFR2, HVDTLB, 12, 4)
33
AspeedSoCState *soc = &bmc->soc;
44
+FIELD(ID_MMFR2, UNITLB, 16, 4)
34
uint8_t *eeprom_buf = g_malloc0(8 * 1024);
45
+FIELD(ID_MMFR2, MEMBARR, 20, 4)
35
46
+FIELD(ID_MMFR2, WFISTALL, 24, 4)
36
+ /* Bus 3: TODO bmp280@77 */
47
+FIELD(ID_MMFR2, HWACCFLG, 28, 4)
37
+ /* Bus 3: TODO max31785@52 */
38
+ /* Bus 3: TODO dps310@76 */
39
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 3), TYPE_PCA9552,
40
0x60);
41
42
@@ -XXX,XX +XXX,XX @@ static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
43
eeprom_buf);
44
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), TYPE_PCA9552,
45
0x60);
46
+ /* Bus 11: TODO ucd90160@64 */
47
}
48
49
static void aspeed_machine_class_init(ObjectClass *oc, void *data)
50
@@ -XXX,XX +XXX,XX @@ static void aspeed_machine_ast2600_evb_class_init(ObjectClass *oc, void *data)
51
mc->default_ram_size = 1 * GiB;
52
};
53
54
+static void aspeed_machine_tacoma_class_init(ObjectClass *oc, void *data)
55
+{
56
+ MachineClass *mc = MACHINE_CLASS(oc);
57
+ AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
58
+
48
+
59
+ mc->desc = "Aspeed AST2600 EVB (Cortex A7)";
49
FIELD(ID_MMFR3, CMAINTVA, 0, 4)
60
+ amc->soc_name = "ast2600-a0";
50
FIELD(ID_MMFR3, CMAINTSW, 4, 4)
61
+ amc->hw_strap1 = TACOMA_BMC_HW_STRAP1;
51
FIELD(ID_MMFR3, BPMAINT, 8, 4)
62
+ amc->hw_strap2 = TACOMA_BMC_HW_STRAP2;
52
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR4, LSM, 20, 4)
63
+ amc->fmc_model = "mx66l1g45g";
53
FIELD(ID_MMFR4, CCIDX, 24, 4)
64
+ amc->spi_model = "mx66l1g45g";
54
FIELD(ID_MMFR4, EVT, 28, 4)
65
+ amc->num_cs = 2;
55
66
+ amc->i2c_init = witherspoon_bmc_i2c_init; /* Same board layout */
56
+FIELD(ID_MMFR5, ETS, 0, 4)
67
+ mc->default_ram_size = 1 * GiB;
68
+};
69
+
57
+
70
static const TypeInfo aspeed_machine_types[] = {
58
FIELD(ID_PFR0, STATE0, 0, 4)
71
{
59
FIELD(ID_PFR0, STATE1, 4, 4)
72
.name = MACHINE_TYPE_NAME("palmetto-bmc"),
60
FIELD(ID_PFR0, STATE2, 8, 4)
73
@@ -XXX,XX +XXX,XX @@ static const TypeInfo aspeed_machine_types[] = {
61
@@ -XXX,XX +XXX,XX @@ FIELD(ID_PFR1, SEC_FRAC, 20, 4)
74
.name = MACHINE_TYPE_NAME("ast2600-evb"),
62
FIELD(ID_PFR1, VIRT_FRAC, 24, 4)
75
.parent = TYPE_ASPEED_MACHINE,
63
FIELD(ID_PFR1, GIC, 28, 4)
76
.class_init = aspeed_machine_ast2600_evb_class_init,
64
77
+ }, {
65
+FIELD(ID_PFR2, CSV3, 0, 4)
78
+ .name = MACHINE_TYPE_NAME("tacoma-bmc"),
66
+FIELD(ID_PFR2, SSBS, 4, 4)
79
+ .parent = TYPE_ASPEED_MACHINE,
67
+FIELD(ID_PFR2, RAS_FRAC, 8, 4)
80
+ .class_init = aspeed_machine_tacoma_class_init,
68
+
81
}, {
69
FIELD(ID_AA64ISAR0, AES, 4, 4)
82
.name = TYPE_ASPEED_MACHINE,
70
FIELD(ID_AA64ISAR0, SHA1, 8, 4)
83
.parent = TYPE_MACHINE,
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)
84
--
81
--
85
2.20.1
82
2.20.1
86
83
87
84
diff view generated by jsdifflib
1
From: Niek Linnenbank <nieklinnenbank@gmail.com>
1
From: Roman Bolshakov <r.bolshakov@yadro.com>
2
2
3
This change ensures that the FPU can be accessed in Non-Secure mode
3
QEMU documentation can't be opened if QEMU is run from build tree
4
when the CPU core is reset using the arm_set_cpu_on() function call.
4
because executables are placed in the top of build tree after conversion
5
The NSACR.{CP11,CP10} bits define the exception level required to
5
to meson.
6
access the FPU in Non-Secure mode. Without these bits set, the CPU
7
will give an undefined exception trap on the first FPU access for the
8
secondary cores under Linux.
9
6
10
This is necessary because in this power-control codepath QEMU
7
Signed-off-by: Roman Bolshakov <r.bolshakov@yadro.com>
11
is effectively emulating a bit of EL3 firmware, and has to set
8
Reported-by: Peter Maydell <peter.maydell@linaro.org>
12
the CPU up as the EL3 firmware would.
9
Message-id: 20210108213815.64678-1-r.bolshakov@yadro.com
13
14
Fixes: fc1120a7f5
15
Cc: qemu-stable@nongnu.org
16
Signed-off-by: Niek Linnenbank <nieklinnenbank@gmail.com>
17
[PMM: added clarifying para to commit message]
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
12
---
21
target/arm/arm-powerctl.c | 3 +++
13
ui/cocoa.m | 2 +-
22
1 file changed, 3 insertions(+)
14
1 file changed, 1 insertion(+), 1 deletion(-)
23
15
24
diff --git a/target/arm/arm-powerctl.c b/target/arm/arm-powerctl.c
16
diff --git a/ui/cocoa.m b/ui/cocoa.m
25
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/arm-powerctl.c
18
--- a/ui/cocoa.m
27
+++ b/target/arm/arm-powerctl.c
19
+++ b/ui/cocoa.m
28
@@ -XXX,XX +XXX,XX @@ static void arm_set_cpu_on_async_work(CPUState *target_cpu_state,
20
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
29
/* Processor is not in secure mode */
21
- (void) openDocumentation: (NSString *) filename
30
target_cpu->env.cp15.scr_el3 |= SCR_NS;
22
{
31
23
/* Where to look for local files */
32
+ /* Set NSACR.{CP11,CP10} so NS can access the FPU */
24
- NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"../docs/"};
33
+ target_cpu->env.cp15.nsacr |= 3 << 10;
25
+ NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"docs/"};
34
+
26
NSString *full_file_path;
35
/*
27
36
* If QEMU is providing the equivalent of EL3 firmware, then we need
28
/* iterate thru the possible paths until the file is found */
37
* to make sure a CPU targeting EL2 comes out of reset with a
38
--
29
--
39
2.20.1
30
2.20.1
40
31
41
32
diff view generated by jsdifflib
1
From: PanNengyuan <pannengyuan@huawei.com>
1
In commit 1982e1602d15 we added a new qemu-storage-daemon(1) manpage.
2
At the moment new manpages have to be listed both in the conf.py for
3
Sphinx and also in docs/meson.build for Meson. We forgot the second
4
of those -- correct the omission.
2
5
3
Address Sanitizer shows memory leak in hw/gpio/aspeed_gpio.c:875
4
5
Reported-by: Euler Robot <euler.robot@huawei.com>
6
Signed-off-by: PanNengyuan <pannengyuan@huawei.com>
7
Reviewed-by: Cédric Le Goater <clg@kaod.org>
8
Signed-off-by: Cédric Le Goater <clg@kaod.org>
9
Message-id: 20191119141211.25716-16-clg@kaod.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Message-id: 20210108161416.21129-2-peter.maydell@linaro.org
11
---
10
---
12
hw/gpio/aspeed_gpio.c | 1 +
11
docs/meson.build | 1 +
13
1 file changed, 1 insertion(+)
12
1 file changed, 1 insertion(+)
14
13
15
diff --git a/hw/gpio/aspeed_gpio.c b/hw/gpio/aspeed_gpio.c
14
diff --git a/docs/meson.build b/docs/meson.build
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/gpio/aspeed_gpio.c
16
--- a/docs/meson.build
18
+++ b/hw/gpio/aspeed_gpio.c
17
+++ b/docs/meson.build
19
@@ -XXX,XX +XXX,XX @@ static void aspeed_gpio_init(Object *obj)
18
@@ -XXX,XX +XXX,XX @@ if build_docs
20
pin_idx % GPIOS_PER_GROUP);
19
'qemu-img.1': (have_tools ? 'man1' : ''),
21
object_property_add(obj, name, "bool", aspeed_gpio_get_pin,
20
'qemu-nbd.8': (have_tools ? 'man8' : ''),
22
aspeed_gpio_set_pin, NULL, NULL, NULL);
21
'qemu-pr-helper.8': (have_tools ? 'man8' : ''),
23
+ g_free(name);
22
+ 'qemu-storage-daemon.1': (have_tools ? 'man1' : ''),
24
}
23
'qemu-trace-stap.1': (config_host.has_key('CONFIG_TRACE_SYSTEMTAP') ? 'man1' : ''),
25
}
24
'virtfs-proxy-helper.1': (have_virtfs_proxy_helper ? 'man1' : ''),
26
25
'virtiofsd.1': (have_virtiofsd ? 'man1' : ''),
27
--
26
--
28
2.20.1
27
2.20.1
29
28
30
29
diff view generated by jsdifflib
1
From: Beata Michalska <beata.michalska@linaro.org>
1
When we first converted our documentation to Sphinx, we split it into
2
2
multiple manuals (system, interop, tools, etc), which are all built
3
Switch to ram block writeback for pmem migration.
3
separately. The primary driver for this was wanting to be able to
4
4
avoid shipping the 'devel' manual to end-users. However, this is
5
Signed-off-by: Beata Michalska <beata.michalska@linaro.org>
5
working against the grain of the way Sphinx wants to be used and
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
causes some annoyances:
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
* Cross-references between documents become much harder or
8
Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
8
possibly impossible
9
Message-id: 20191121000843.24844-4-beata.michalska@linaro.org
9
* There is no single index to the whole documentation
10
* Within one manual there's no links or table-of-contents info
11
that lets you easily navigate to the others
12
* The devel manual doesn't get published on the QEMU website
13
(it would be nice to able to refer to it there)
14
15
Merely hiding our developer documentation from end users seems like
16
it's not enough benefit for these costs. Combine all the
17
documentation into a single manual (the same way that the readthedocs
18
site builds it) and install the whole thing. The previous manual
19
divisions remain as the new top level sections in the manual.
20
21
* The per-manual conf.py files are no longer needed
22
* The man_pages[] specifications previously in each per-manual
23
conf.py move to the top level conf.py
24
* docs/meson.build logic is simplified as we now only need to run
25
Sphinx once for the HTML and then once for the manpages5B
26
* The old index.html.in that produced the top-level page with
27
links to each manual is no longer needed
28
29
Unfortunately this means that we now have to build the HTML
30
documentation into docs/manual in the build tree rather than directly
31
into docs/; otherwise it is too awkward to ensure we install only the
32
built manual and not also the dependency info, stamp file, etc. The
33
manual still ends up in the same place in the final installed
34
directory, but anybody who was consulting documentation from within
35
the build tree will have to adjust where they're looking.
36
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
37
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
38
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
39
Message-id: 20210108161416.21129-3-peter.maydell@linaro.org
11
---
40
---
12
migration/ram.c | 5 +----
41
docs/conf.py | 46 ++++++++++++++++++++++++++++++-
13
1 file changed, 1 insertion(+), 4 deletions(-)
42
docs/devel/conf.py | 15 -----------
14
43
docs/index.html.in | 17 ------------
15
diff --git a/migration/ram.c b/migration/ram.c
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
59
diff --git a/docs/conf.py b/docs/conf.py
16
index XXXXXXX..XXXXXXX 100644
60
index XXXXXXX..XXXXXXX 100644
17
--- a/migration/ram.c
61
--- a/docs/conf.py
18
+++ b/migration/ram.c
62
+++ b/docs/conf.py
19
@@ -XXX,XX +XXX,XX @@
63
@@ -XXX,XX +XXX,XX @@ latex_documents = [
20
#include "qemu/bitops.h"
64
21
#include "qemu/bitmap.h"
65
# -- Options for manual page output ---------------------------------------
22
#include "qemu/main-loop.h"
66
# Individual manual/conf.py can override this to create man pages
23
-#include "qemu/pmem.h"
67
-man_pages = []
24
#include "xbzrle.h"
68
+man_pages = [
25
#include "ram.h"
69
+ ('interop/qemu-ga', 'qemu-ga',
26
#include "migration.h"
70
+ 'QEMU Guest Agent',
27
@@ -XXX,XX +XXX,XX @@ static int ram_load_cleanup(void *opaque)
71
+ ['Michael Roth <mdroth@linux.vnet.ibm.com>'], 8),
28
RAMBlock *rb;
72
+ ('interop/qemu-ga-ref', 'qemu-ga-ref',
29
73
+ 'QEMU Guest Agent Protocol Reference',
30
RAMBLOCK_FOREACH_NOT_IGNORED(rb) {
74
+ [], 7),
31
- if (ramblock_is_pmem(rb)) {
75
+ ('interop/qemu-qmp-ref', 'qemu-qmp-ref',
32
- pmem_persist(rb->host, rb->used_length);
76
+ 'QEMU QMP Reference Manual',
33
- }
77
+ [], 7),
34
+ qemu_ram_block_writeback(rb);
78
+ ('interop/qemu-storage-daemon-qmp-ref', 'qemu-storage-daemon-qmp-ref',
35
}
79
+ 'QEMU Storage Daemon QMP Reference Manual',
36
80
+ [], 7),
37
xbzrle_load_cleanup();
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
196
--- a/docs/meson.build
197
+++ b/docs/meson.build
198
@@ -XXX,XX +XXX,XX @@ if build_docs
199
meson.source_root() / 'docs/sphinx/qmp_lexer.py',
200
qapi_gen_depends ]
201
202
- configure_file(output: 'index.html',
203
- input: files('index.html.in'),
204
- configuration: {'VERSION': meson.project_version()},
205
- install_dir: qemu_docdir)
206
- manuals = [ 'devel', 'interop', 'tools', 'specs', 'system', 'user' ]
207
man_pages = {
208
- 'interop' : {
209
'qemu-ga.8': (have_tools ? 'man8' : ''),
210
'qemu-ga-ref.7': 'man7',
211
'qemu-qmp-ref.7': 'man7',
212
'qemu-storage-daemon-qmp-ref.7': (have_tools ? 'man7' : ''),
213
- },
214
- 'tools': {
215
'qemu-img.1': (have_tools ? 'man1' : ''),
216
'qemu-nbd.8': (have_tools ? 'man8' : ''),
217
'qemu-pr-helper.8': (have_tools ? 'man8' : ''),
218
@@ -XXX,XX +XXX,XX @@ if build_docs
219
'qemu-trace-stap.1': (config_host.has_key('CONFIG_TRACE_SYSTEMTAP') ? 'man1' : ''),
220
'virtfs-proxy-helper.1': (have_virtfs_proxy_helper ? 'man1' : ''),
221
'virtiofsd.1': (have_virtiofsd ? 'man1' : ''),
222
- },
223
- 'system': {
224
'qemu.1': 'man1',
225
'qemu-block-drivers.7': 'man7',
226
'qemu-cpu-models.7': 'man7'
227
- },
228
}
229
230
sphinxdocs = []
231
sphinxmans = []
232
- foreach manual : manuals
233
- private_dir = meson.current_build_dir() / (manual + '.p')
234
- output_dir = meson.current_build_dir() / manual
235
- input_dir = meson.current_source_dir() / manual
236
237
- this_manual = custom_target(manual + ' manual',
238
+ private_dir = meson.current_build_dir() / 'manual.p'
239
+ output_dir = meson.current_build_dir() / 'manual'
240
+ input_dir = meson.current_source_dir()
241
+
242
+ this_manual = custom_target('QEMU manual',
243
build_by_default: build_docs,
244
- output: [manual + '.stamp'],
245
- input: [files('conf.py'), files(manual / 'conf.py')],
246
- depfile: manual + '.d',
247
+ output: 'docs.stamp',
248
+ input: files('conf.py'),
249
+ depfile: 'docs.d',
250
depend_files: sphinx_extn_depends,
251
command: [SPHINX_ARGS, '-Ddepfile=@DEPFILE@',
252
'-Ddepfile_stamp=@OUTPUT0@',
253
'-b', 'html', '-d', private_dir,
254
input_dir, output_dir])
255
- sphinxdocs += this_manual
256
- if build_docs and manual != 'devel'
257
- install_subdir(output_dir, install_dir: qemu_docdir)
258
- endif
259
+ sphinxdocs += this_manual
260
+ install_subdir(output_dir, install_dir: qemu_docdir, strip_directory: true)
261
262
- these_man_pages = []
263
- install_dirs = []
264
- foreach page, section : man_pages.get(manual, {})
265
- these_man_pages += page
266
- install_dirs += section == '' ? false : get_option('mandir') / section
267
- endforeach
268
- if these_man_pages.length() > 0
269
- sphinxmans += custom_target(manual + ' man pages',
270
- build_by_default: build_docs,
271
- output: these_man_pages,
272
- input: this_manual,
273
- install: build_docs,
274
- install_dir: install_dirs,
275
- command: [SPHINX_ARGS, '-b', 'man', '-d', private_dir,
276
- input_dir, meson.current_build_dir()])
277
- endif
278
+ these_man_pages = []
279
+ install_dirs = []
280
+ foreach page, section : man_pages
281
+ these_man_pages += page
282
+ install_dirs += section == '' ? false : get_option('mandir') / section
283
endforeach
284
+
285
+ sphinxmans += custom_target('QEMU man pages',
286
+ build_by_default: build_docs,
287
+ output: these_man_pages,
288
+ input: this_manual,
289
+ install: build_docs,
290
+ install_dir: install_dirs,
291
+ command: [SPHINX_ARGS, '-b', 'man', '-d', private_dir,
292
+ input_dir, meson.current_build_dir()])
293
+
294
alias_target('sphinxdocs', sphinxdocs)
295
alias_target('html', sphinxdocs)
296
alias_target('man', sphinxmans)
297
diff --git a/docs/specs/conf.py b/docs/specs/conf.py
298
deleted file mode 100644
299
index XXXXXXX..XXXXXXX
300
--- a/docs/specs/conf.py
301
+++ /dev/null
302
@@ -XXX,XX +XXX,XX @@
303
-# -*- coding: utf-8 -*-
304
-#
305
-# QEMU documentation build configuration file for the 'specs' manual.
306
-#
307
-# This includes the top level conf file and then makes any necessary tweaks.
308
-import sys
309
-import os
310
-
311
-qemu_docdir = os.path.abspath("..")
312
-parent_config = os.path.join(qemu_docdir, "conf.py")
313
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
314
-
315
-# This slightly misuses the 'description', but is the best way to get
316
-# the manual title to appear in the sidebar.
317
-html_theme_options['description'] = \
318
- u'System Emulation Guest Hardware Specifications'
319
diff --git a/docs/system/conf.py b/docs/system/conf.py
320
deleted file mode 100644
321
index XXXXXXX..XXXXXXX
322
--- a/docs/system/conf.py
323
+++ /dev/null
324
@@ -XXX,XX +XXX,XX @@
325
-# -*- coding: utf-8 -*-
326
-#
327
-# QEMU documentation build configuration file for the 'system' manual.
328
-#
329
-# This includes the top level conf file and then makes any necessary tweaks.
330
-import sys
331
-import os
332
-
333
-qemu_docdir = os.path.abspath("..")
334
-parent_config = os.path.join(qemu_docdir, "conf.py")
335
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
336
-
337
-# This slightly misuses the 'description', but is the best way to get
338
-# the manual title to appear in the sidebar.
339
-html_theme_options['description'] = u'System Emulation User''s Guide'
340
-
341
-# One entry per manual page. List of tuples
342
-# (source start file, name, description, authors, manual section).
343
-man_pages = [
344
- ('qemu-manpage', 'qemu', u'QEMU User Documentation',
345
- ['Fabrice Bellard'], 1),
346
- ('qemu-block-drivers', 'qemu-block-drivers',
347
- u'QEMU block drivers reference',
348
- ['Fabrice Bellard and the QEMU Project developers'], 7),
349
- ('qemu-cpu-models', 'qemu-cpu-models',
350
- u'QEMU CPU Models',
351
- ['The QEMU Project developers'], 7)
352
-]
353
diff --git a/docs/tools/conf.py b/docs/tools/conf.py
354
deleted file mode 100644
355
index XXXXXXX..XXXXXXX
356
--- a/docs/tools/conf.py
357
+++ /dev/null
358
@@ -XXX,XX +XXX,XX @@
359
-# -*- coding: utf-8 -*-
360
-#
361
-# QEMU documentation build configuration file for the 'tools' manual.
362
-#
363
-# This includes the top level conf file and then makes any necessary tweaks.
364
-import sys
365
-import os
366
-
367
-qemu_docdir = os.path.abspath("..")
368
-parent_config = os.path.join(qemu_docdir, "conf.py")
369
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
370
-
371
-# This slightly misuses the 'description', but is the best way to get
372
-# the manual title to appear in the sidebar.
373
-html_theme_options['description'] = \
374
- u'Tools Guide'
375
-
376
-# One entry per manual page. List of tuples
377
-# (source start file, name, description, authors, manual section).
378
-man_pages = [
379
- ('qemu-img', 'qemu-img', u'QEMU disk image utility',
380
- ['Fabrice Bellard'], 1),
381
- ('qemu-storage-daemon', 'qemu-storage-daemon', u'QEMU storage daemon',
382
- [], 1),
383
- ('qemu-nbd', 'qemu-nbd', u'QEMU Disk Network Block Device Server',
384
- ['Anthony Liguori <anthony@codemonkey.ws>'], 8),
385
- ('qemu-pr-helper', 'qemu-pr-helper', 'QEMU persistent reservation helper',
386
- [], 8),
387
- ('qemu-trace-stap', 'qemu-trace-stap', u'QEMU SystemTap trace tool',
388
- [], 1),
389
- ('virtfs-proxy-helper', 'virtfs-proxy-helper',
390
- u'QEMU 9p virtfs proxy filesystem helper',
391
- ['M. Mohan Kumar'], 1),
392
- ('virtiofsd', 'virtiofsd', u'QEMU virtio-fs shared file system daemon',
393
- ['Stefan Hajnoczi <stefanha@redhat.com>',
394
- 'Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>'], 1),
395
-]
396
diff --git a/docs/user/conf.py b/docs/user/conf.py
397
deleted file mode 100644
398
index XXXXXXX..XXXXXXX
399
--- a/docs/user/conf.py
400
+++ /dev/null
401
@@ -XXX,XX +XXX,XX @@
402
-# -*- coding: utf-8 -*-
403
-#
404
-# QEMU documentation build configuration file for the 'user' manual.
405
-#
406
-# This includes the top level conf file and then makes any necessary tweaks.
407
-import sys
408
-import os
409
-
410
-qemu_docdir = os.path.abspath("..")
411
-parent_config = os.path.join(qemu_docdir, "conf.py")
412
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
413
-
414
-# This slightly misuses the 'description', but is the best way to get
415
-# the manual title to appear in the sidebar.
416
-html_theme_options['description'] = u'User Mode Emulation User''s Guide'
38
--
417
--
39
2.20.1
418
2.20.1
40
419
41
420
diff view generated by jsdifflib
1
From: Cédric Le Goater <clg@kaod.org>
1
In commit cd8be50e58f63413c0 we converted the A32 coprocessor
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.
2
7
3
The SRAM must be enabled before using the Buffer Pool mode or the DMA
8
Update valid_cp() so that it knows that on XScale cp 0 and 1
4
mode. This is not required on other SoCs.
9
are not standard coprocessor instructions; this will cause
10
the decodetree trans_ functions to ignore them, so that
11
execution will correctly get through to the legacy decode again.
5
12
6
Signed-off-by: Cédric Le Goater <clg@kaod.org>
13
Cc: qemu-stable@nongnu.org
7
Reviewed-by: Joel Stanley <joel@jms.id.au>
14
Reported-by: Guenter Roeck <linux@roeck-us.net>
8
Tested-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>
9
Signed-off-by: Cédric Le Goater <clg@kaod.org>
10
Message-id: 20191119141211.25716-3-clg@kaod.org
11
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
12
---
19
---
13
include/hw/i2c/aspeed_i2c.h | 3 +++
20
target/arm/translate.c | 7 +++++++
14
hw/i2c/aspeed_i2c.c | 37 +++++++++++++++++++++++++++++++++++++
21
1 file changed, 7 insertions(+)
15
2 files changed, 40 insertions(+)
16
22
17
diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h
23
diff --git a/target/arm/translate.c b/target/arm/translate.c
18
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/i2c/aspeed_i2c.h
25
--- a/target/arm/translate.c
20
+++ b/include/hw/i2c/aspeed_i2c.h
26
+++ b/target/arm/translate.c
21
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedI2CState {
27
@@ -XXX,XX +XXX,XX @@ static bool valid_cp(DisasContext *s, int cp)
22
qemu_irq irq;
28
* only cp14 and cp15 are valid, and other values aren't considered
23
29
* to be in the coprocessor-instruction space at all. v8M still
24
uint32_t intr_status;
30
* permits coprocessors 0..7.
25
+ uint32_t ctrl_global;
31
+ * For XScale, we must not decode the XScale cp0, cp1 space as
26
MemoryRegion pool_iomem;
32
+ * a standard coprocessor insn, because we want to fall through to
27
uint8_t pool[ASPEED_I2C_MAX_POOL_SIZE];
33
+ * the legacy disas_xscale_insn() decoder after decodetree is done.
28
34
*/
29
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedI2CClass {
35
+ if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cp == 0 || cp == 1)) {
30
uint64_t pool_size;
31
hwaddr pool_base;
32
uint8_t *(*bus_pool_base)(AspeedI2CBus *);
33
+ bool check_sram;
34
+
35
} AspeedI2CClass;
36
37
I2CBus *aspeed_i2c_get_bus(DeviceState *dev, int busnr);
38
diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/hw/i2c/aspeed_i2c.c
41
+++ b/hw/i2c/aspeed_i2c.c
42
@@ -XXX,XX +XXX,XX @@
43
#define I2C_CTRL_STATUS 0x00 /* Device Interrupt Status */
44
#define I2C_CTRL_ASSIGN 0x08 /* Device Interrupt Target
45
Assignment */
46
+#define I2C_CTRL_GLOBAL 0x0C /* Global Control Register */
47
+#define I2C_CTRL_SRAM_EN BIT(0)
48
49
/* I2C Device (Bus) Register */
50
51
@@ -XXX,XX +XXX,XX @@ static uint8_t aspeed_i2c_get_addr(AspeedI2CBus *bus)
52
}
53
}
54
55
+static bool aspeed_i2c_check_sram(AspeedI2CBus *bus)
56
+{
57
+ AspeedI2CState *s = bus->controller;
58
+ AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(s);
59
+
60
+ if (!aic->check_sram) {
61
+ return true;
62
+ }
63
+
64
+ /*
65
+ * AST2500: SRAM must be enabled before using the Buffer Pool or
66
+ * DMA mode.
67
+ */
68
+ if (!(s->ctrl_global & I2C_CTRL_SRAM_EN) &&
69
+ (bus->cmd & (I2CD_RX_DMA_ENABLE | I2CD_TX_DMA_ENABLE |
70
+ I2CD_RX_BUFF_ENABLE | I2CD_TX_BUFF_ENABLE))) {
71
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: SRAM is not enabled\n", __func__);
72
+ return false;
36
+ return false;
73
+ }
37
+ }
74
+
38
+
75
+ return true;
39
if (arm_dc_feature(s, ARM_FEATURE_V8) &&
76
+}
40
!arm_dc_feature(s, ARM_FEATURE_M)) {
77
+
41
return cp >= 14;
78
/*
79
* The state machine needs some refinement. It is only used to track
80
* invalid STOP commands for the moment.
81
@@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_bus_handle_cmd(AspeedI2CBus *bus, uint64_t value)
82
bus->cmd &= ~0xFFFF;
83
bus->cmd |= value & 0xFFFF;
84
85
+ if (!aspeed_i2c_check_sram(bus)) {
86
+ return;
87
+ }
88
+
89
if (bus->cmd & I2CD_M_START_CMD) {
90
uint8_t state = aspeed_i2c_get_state(bus) & I2CD_MACTIVE ?
91
I2CD_MSTARTR : I2CD_MSTART;
92
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_i2c_ctrl_read(void *opaque, hwaddr offset,
93
switch (offset) {
94
case I2C_CTRL_STATUS:
95
return s->intr_status;
96
+ case I2C_CTRL_GLOBAL:
97
+ return s->ctrl_global;
98
default:
99
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
100
__func__, offset);
101
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_i2c_ctrl_read(void *opaque, hwaddr offset,
102
static void aspeed_i2c_ctrl_write(void *opaque, hwaddr offset,
103
uint64_t value, unsigned size)
104
{
105
+ AspeedI2CState *s = opaque;
106
+
107
switch (offset) {
108
+ case I2C_CTRL_GLOBAL:
109
+ s->ctrl_global = value;
110
+ break;
111
case I2C_CTRL_STATUS:
112
default:
113
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
114
@@ -XXX,XX +XXX,XX @@ static void aspeed_2500_i2c_class_init(ObjectClass *klass, void *data)
115
aic->pool_size = 0x100;
116
aic->pool_base = 0x200;
117
aic->bus_pool_base = aspeed_2500_i2c_bus_pool_base;
118
+ aic->check_sram = true;
119
}
120
121
static const TypeInfo aspeed_2500_i2c_info = {
122
--
42
--
123
2.20.1
43
2.20.1
124
44
125
45
diff view generated by jsdifflib
1
From: Beata Michalska <beata.michalska@linaro.org>
1
A copy-and-paste error meant that the return value for register offset 0x44
2
(the RX Status FIFO PEEK register) returned a byte from a bogus offset in
3
the rx status FIFO. Fix the typo.
2
4
3
Add probe_read alongside the write probing equivalent.
5
Cc: qemu-stable@nongnu.org
6
Fixes: https://bugs.launchpad.net/qemu/+bug/1904954
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20210108180401.2263-2-peter.maydell@linaro.org
10
---
11
hw/net/lan9118.c | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
4
13
5
Signed-off-by: Beata Michalska <beata.michalska@linaro.org>
14
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20191121000843.24844-2-beata.michalska@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/exec/exec-all.h | 6 ++++++
12
1 file changed, 6 insertions(+)
13
14
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/exec/exec-all.h
16
--- a/hw/net/lan9118.c
17
+++ b/include/exec/exec-all.h
17
+++ b/hw/net/lan9118.c
18
@@ -XXX,XX +XXX,XX @@ static inline void *probe_write(CPUArchState *env, target_ulong addr, int size,
18
@@ -XXX,XX +XXX,XX @@ static uint64_t lan9118_readl(void *opaque, hwaddr offset,
19
return probe_access(env, addr, size, MMU_DATA_STORE, mmu_idx, retaddr);
19
case 0x40:
20
}
20
return rx_status_fifo_pop(s);
21
21
case 0x44:
22
+static inline void *probe_read(CPUArchState *env, target_ulong addr, int size,
22
- return s->rx_status_fifo[s->tx_status_fifo_head];
23
+ int mmu_idx, uintptr_t retaddr)
23
+ return s->rx_status_fifo[s->rx_status_fifo_head];
24
+{
24
case 0x48:
25
+ return probe_access(env, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
25
return tx_status_fifo_pop(s);
26
+}
26
case 0x4c:
27
+
28
#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
29
30
/* Estimated block size for TB allocation. */
31
--
27
--
32
2.20.1
28
2.20.1
33
29
34
30
diff view generated by jsdifflib
1
From: Marc Zyngier <maz@kernel.org>
1
The lan9118 code mostly uses symbolic constants for register offsets;
2
the exceptions are those which the datasheet doesn't give an official
3
symbolic name to.
2
4
3
QEMU lacks the minimum Jazelle implementation that is required
5
Add some names for the registers which don't already have them, based
4
by the architecture (everything is RAZ or RAZ/WI). Add it
6
on the longer names they are given in the memory map.
5
together with the HCR_EL2.TID0 trapping that goes with it.
6
7
7
Signed-off-by: Marc Zyngier <maz@kernel.org>
8
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20191201122018.25808-6-maz@kernel.org
11
[PMM: moved ARMCPRegInfo array to file scope, marked it
12
'static global', moved new condition down in
13
register_cp_regs_for_features() to go with other feature
14
things rather than up with the v6/v7/v8 stuff]
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20210108180401.2263-3-peter.maydell@linaro.org
16
---
11
---
17
target/arm/helper.c | 27 +++++++++++++++++++++++++++
12
hw/net/lan9118.c | 24 ++++++++++++++++++------
18
1 file changed, 27 insertions(+)
13
1 file changed, 18 insertions(+), 6 deletions(-)
19
14
20
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
21
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/helper.c
17
--- a/hw/net/lan9118.c
23
+++ b/target/arm/helper.c
18
+++ b/hw/net/lan9118.c
24
@@ -XXX,XX +XXX,XX @@ static CPAccessResult access_aa32_tid3(CPUARMState *env, const ARMCPRegInfo *ri,
19
@@ -XXX,XX +XXX,XX @@ do { hw_error("lan9118: error: " fmt , ## __VA_ARGS__);} while (0)
25
return CP_ACCESS_OK;
20
do { fprintf(stderr, "lan9118: error: " fmt , ## __VA_ARGS__);} while (0)
26
}
21
#endif
27
22
28
+static CPAccessResult access_jazelle(CPUARMState *env, const ARMCPRegInfo *ri,
23
+/* The tx and rx fifo ports are a range of aliased 32-bit registers */
29
+ bool isread)
24
+#define RX_DATA_FIFO_PORT_FIRST 0x00
30
+{
25
+#define RX_DATA_FIFO_PORT_LAST 0x1f
31
+ if (arm_current_el(env) == 1 && (arm_hcr_el2_eff(env) & HCR_TID0)) {
26
+#define TX_DATA_FIFO_PORT_FIRST 0x20
32
+ return CP_ACCESS_TRAP_EL2;
27
+#define TX_DATA_FIFO_PORT_LAST 0x3f
33
+ }
34
+
28
+
35
+ return CP_ACCESS_OK;
29
+#define RX_STATUS_FIFO_PORT 0x40
36
+}
30
+#define RX_STATUS_FIFO_PEEK 0x44
31
+#define TX_STATUS_FIFO_PORT 0x48
32
+#define TX_STATUS_FIFO_PEEK 0x4c
37
+
33
+
38
+static const ARMCPRegInfo jazelle_regs[] = {
34
#define CSR_ID_REV 0x50
39
+ { .name = "JIDR",
35
#define CSR_IRQ_CFG 0x54
40
+ .cp = 14, .crn = 0, .crm = 0, .opc1 = 7, .opc2 = 0,
36
#define CSR_INT_STS 0x58
41
+ .access = PL1_R, .accessfn = access_jazelle,
37
@@ -XXX,XX +XXX,XX @@ static void lan9118_writel(void *opaque, hwaddr offset,
42
+ .type = ARM_CP_CONST, .resetvalue = 0 },
38
offset &= 0xff;
43
+ { .name = "JOSCR",
39
44
+ .cp = 14, .crn = 1, .crm = 0, .opc1 = 7, .opc2 = 0,
40
//DPRINTF("Write reg 0x%02x = 0x%08x\n", (int)offset, val);
45
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
41
- if (offset >= 0x20 && offset < 0x40) {
46
+ { .name = "JMCR",
42
+ if (offset >= TX_DATA_FIFO_PORT_FIRST &&
47
+ .cp = 14, .crn = 2, .crm = 0, .opc1 = 7, .opc2 = 0,
43
+ offset <= TX_DATA_FIFO_PORT_LAST) {
48
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
44
/* TX FIFO */
49
+ REGINFO_SENTINEL
45
tx_fifo_push(s, val);
50
+};
46
return;
51
+
47
@@ -XXX,XX +XXX,XX @@ static uint64_t lan9118_readl(void *opaque, hwaddr offset,
52
void register_cp_regs_for_features(ARMCPU *cpu)
48
lan9118_state *s = (lan9118_state *)opaque;
53
{
49
54
/* Register all the coprocessor registers based on feature bits */
50
//DPRINTF("Read reg 0x%02x\n", (int)offset);
55
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
51
- if (offset < 0x20) {
56
if (arm_feature(env, ARM_FEATURE_LPAE)) {
52
+ if (offset <= RX_DATA_FIFO_PORT_LAST) {
57
define_arm_cp_regs(cpu, lpae_cp_reginfo);
53
/* RX FIFO */
54
return rx_fifo_pop(s);
58
}
55
}
59
+ if (cpu_isar_feature(jazelle, cpu)) {
56
switch (offset) {
60
+ define_arm_cp_regs(cpu, jazelle_regs);
57
- case 0x40:
61
+ }
58
+ case RX_STATUS_FIFO_PORT:
62
/* Slightly awkwardly, the OMAP and StrongARM cores need all of
59
return rx_status_fifo_pop(s);
63
* cp15 crn=0 to be writes-ignored, whereas for other cores they should
60
- case 0x44:
64
* be read-only (ie write causes UNDEF exception).
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;
65
--
71
--
66
2.20.1
72
2.20.1
67
73
68
74
diff view generated by jsdifflib
1
From: Cédric Le Goater <clg@kaod.org>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
The I2C controller of the Aspeed AST2500 and AST2600 SoCs supports DMA
3
This patch allows NPCM7XX CLK module to compute clocks that are used by
4
transfers to and from DRAM.
4
other NPCM7XX modules.
5
5
6
A pair of registers defines the buffer address and the length of the
6
Add a new struct NPCM7xxClockConverterState which represents a
7
DMA transfer. The address should be aligned on 4 bytes and the maximum
7
single converter. Each clock converter in CLK module represents one
8
length should not exceed 4K. The receive or transmit DMA transfer can
8
converter in NPCM7XX CLK Module(PLL, SEL or Divider). Each converter
9
then be initiated with specific bits in the Command/Status register of
9
takes one or more input clocks and converts them into one output clock.
10
the controller.
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.
11
12
12
Signed-off-by: Cédric Le Goater <clg@kaod.org>
13
Each converter has a function pointer called "convert" which represents
13
Reviewed-by: Joel Stanley <joel@jms.id.au>
14
the unique logic for that converter.
14
Tested-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>
15
15
Signed-off-by: Cédric Le Goater <clg@kaod.org>
16
The clock contains two initialization information: ConverterInitInfo and
16
Message-id: 20191119141211.25716-5-clg@kaod.org
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
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
26
---
19
include/hw/i2c/aspeed_i2c.h | 5 ++
27
include/hw/misc/npcm7xx_clk.h | 140 +++++-
20
hw/arm/aspeed_ast2600.c | 5 ++
28
hw/misc/npcm7xx_clk.c | 805 +++++++++++++++++++++++++++++++++-
21
hw/arm/aspeed_soc.c | 5 ++
29
2 files changed, 932 insertions(+), 13 deletions(-)
22
hw/i2c/aspeed_i2c.c | 126 +++++++++++++++++++++++++++++++++++-
23
4 files changed, 138 insertions(+), 3 deletions(-)
24
30
25
diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h
31
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
26
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
27
--- a/include/hw/i2c/aspeed_i2c.h
33
--- a/include/hw/misc/npcm7xx_clk.h
28
+++ b/include/hw/i2c/aspeed_i2c.h
34
+++ b/include/hw/misc/npcm7xx_clk.h
29
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedI2CBus {
35
@@ -XXX,XX +XXX,XX @@
30
uint32_t cmd;
36
#define NPCM7XX_CLK_H
31
uint32_t buf;
37
32
uint32_t pool_ctrl;
38
#include "exec/memory.h"
33
+ uint32_t dma_addr;
39
+#include "hw/clock.h"
34
+ uint32_t dma_len;
40
#include "hw/sysbus.h"
35
} AspeedI2CBus;
41
36
42
/*
37
typedef struct AspeedI2CState {
43
@@ -XXX,XX +XXX,XX @@
38
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedI2CState {
44
39
uint8_t pool[ASPEED_I2C_MAX_POOL_SIZE];
45
#define NPCM7XX_WATCHDOG_RESET_GPIO_IN "npcm7xx-clk-watchdog-reset-gpio-in"
40
46
41
AspeedI2CBus busses[ASPEED_I2C_NR_BUSSES];
47
-typedef struct NPCM7xxCLKState {
42
+ MemoryRegion *dram_mr;
48
+/* Maximum amount of clock inputs in a SEL module. */
43
+ AddressSpace dram_as;
49
+#define NPCM7XX_CLK_SEL_MAX_INPUT 5
44
} AspeedI2CState;
50
+
45
51
+/* PLLs in CLK module. */
46
#define ASPEED_I2C_CLASS(klass) \
52
+typedef enum NPCM7xxClockPLL {
47
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedI2CClass {
53
+ NPCM7XX_CLOCK_PLL0,
48
hwaddr pool_base;
54
+ NPCM7XX_CLOCK_PLL1,
49
uint8_t *(*bus_pool_base)(AspeedI2CBus *);
55
+ NPCM7XX_CLOCK_PLL2,
50
bool check_sram;
56
+ NPCM7XX_CLOCK_PLLG,
51
+ bool has_dma;
57
+ NPCM7XX_CLOCK_NR_PLLS,
52
58
+} NPCM7xxClockPLL;
53
} AspeedI2CClass;
59
+
54
60
+/* SEL/MUX in CLK module. */
55
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
61
+typedef enum NPCM7xxClockSEL {
62
+ NPCM7XX_CLOCK_PIXCKSEL,
63
+ NPCM7XX_CLOCK_MCCKSEL,
64
+ NPCM7XX_CLOCK_CPUCKSEL,
65
+ NPCM7XX_CLOCK_CLKOUTSEL,
66
+ NPCM7XX_CLOCK_UARTCKSEL,
67
+ NPCM7XX_CLOCK_TIMCKSEL,
68
+ NPCM7XX_CLOCK_SDCKSEL,
69
+ NPCM7XX_CLOCK_GFXMSEL,
70
+ NPCM7XX_CLOCK_SUCKSEL,
71
+ NPCM7XX_CLOCK_NR_SELS,
72
+} NPCM7xxClockSEL;
73
+
74
+/* Dividers in CLK module. */
75
+typedef enum NPCM7xxClockDivider {
76
+ NPCM7XX_CLOCK_PLL1D2, /* PLL1/2 */
77
+ NPCM7XX_CLOCK_PLL2D2, /* PLL2/2 */
78
+ NPCM7XX_CLOCK_MC_DIVIDER,
79
+ NPCM7XX_CLOCK_AXI_DIVIDER,
80
+ NPCM7XX_CLOCK_AHB_DIVIDER,
81
+ NPCM7XX_CLOCK_AHB3_DIVIDER,
82
+ NPCM7XX_CLOCK_SPI0_DIVIDER,
83
+ NPCM7XX_CLOCK_SPIX_DIVIDER,
84
+ NPCM7XX_CLOCK_APB1_DIVIDER,
85
+ NPCM7XX_CLOCK_APB2_DIVIDER,
86
+ NPCM7XX_CLOCK_APB3_DIVIDER,
87
+ NPCM7XX_CLOCK_APB4_DIVIDER,
88
+ NPCM7XX_CLOCK_APB5_DIVIDER,
89
+ NPCM7XX_CLOCK_CLKOUT_DIVIDER,
90
+ NPCM7XX_CLOCK_UART_DIVIDER,
91
+ NPCM7XX_CLOCK_TIMER_DIVIDER,
92
+ NPCM7XX_CLOCK_ADC_DIVIDER,
93
+ NPCM7XX_CLOCK_MMC_DIVIDER,
94
+ NPCM7XX_CLOCK_SDHC_DIVIDER,
95
+ NPCM7XX_CLOCK_GFXM_DIVIDER, /* divide by 3 */
96
+ NPCM7XX_CLOCK_UTMI_DIVIDER,
97
+ NPCM7XX_CLOCK_NR_DIVIDERS,
98
+} NPCM7xxClockConverter;
99
+
100
+typedef struct NPCM7xxCLKState NPCM7xxCLKState;
101
+
102
+/**
103
+ * struct NPCM7xxClockPLLState - A PLL module in CLK module.
104
+ * @name: The name of the module.
105
+ * @clk: The CLK module that owns this module.
106
+ * @clock_in: The input clock of this module.
107
+ * @clock_out: The output clock of this module.
108
+ * @reg: The control registers for this PLL module.
109
+ */
110
+typedef struct NPCM7xxClockPLLState {
111
+ DeviceState parent;
112
+
113
+ const char *name;
114
+ NPCM7xxCLKState *clk;
115
+ Clock *clock_in;
116
+ Clock *clock_out;
117
+
118
+ int reg;
119
+} NPCM7xxClockPLLState;
120
+
121
+/**
122
+ * struct NPCM7xxClockSELState - A SEL module in CLK module.
123
+ * @name: The name of the module.
124
+ * @clk: The CLK module that owns this module.
125
+ * @input_size: The size of inputs of this module.
126
+ * @clock_in: The input clocks of this module.
127
+ * @clock_out: The output clocks of this module.
128
+ * @offset: The offset of this module in the control register.
129
+ * @len: The length of this module in the control register.
130
+ */
131
+typedef struct NPCM7xxClockSELState {
132
+ DeviceState parent;
133
+
134
+ const char *name;
135
+ NPCM7xxCLKState *clk;
136
+ uint8_t input_size;
137
+ Clock *clock_in[NPCM7XX_CLK_SEL_MAX_INPUT];
138
+ Clock *clock_out;
139
+
140
+ int offset;
141
+ int len;
142
+} NPCM7xxClockSELState;
143
+
144
+/**
145
+ * struct NPCM7xxClockDividerState - A Divider module in CLK module.
146
+ * @name: The name of the module.
147
+ * @clk: The CLK module that owns this module.
148
+ * @clock_in: The input clock of this module.
149
+ * @clock_out: The output clock of this module.
150
+ * @divide: The function the divider uses to divide the input.
151
+ * @reg: The index of the control register that contains the divisor.
152
+ * @offset: The offset of the divisor in the control register.
153
+ * @len: The length of the divisor in the control register.
154
+ * @divisor: The divisor for a constant divisor
155
+ */
156
+typedef struct NPCM7xxClockDividerState {
157
+ DeviceState parent;
158
+
159
+ const char *name;
160
+ NPCM7xxCLKState *clk;
161
+ Clock *clock_in;
162
+ Clock *clock_out;
163
+
164
+ uint32_t (*divide)(struct NPCM7xxClockDividerState *s);
165
+ union {
166
+ struct {
167
+ int reg;
168
+ int offset;
169
+ int len;
170
+ };
171
+ int divisor;
172
+ };
173
+} NPCM7xxClockDividerState;
174
+
175
+struct NPCM7xxCLKState {
176
SysBusDevice parent;
177
178
MemoryRegion iomem;
179
180
+ /* Clock converters */
181
+ NPCM7xxClockPLLState plls[NPCM7XX_CLOCK_NR_PLLS];
182
+ NPCM7xxClockSELState sels[NPCM7XX_CLOCK_NR_SELS];
183
+ NPCM7xxClockDividerState dividers[NPCM7XX_CLOCK_NR_DIVIDERS];
184
+
185
uint32_t regs[NPCM7XX_CLK_NR_REGS];
186
187
/* Time reference for SECCNT and CNTR25M, initialized by power on reset */
188
int64_t ref_ns;
189
-} NPCM7xxCLKState;
190
+
191
+ /* The incoming reference clock. */
192
+ Clock *clkref;
193
+};
194
195
#define TYPE_NPCM7XX_CLK "npcm7xx-clk"
196
#define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), TYPE_NPCM7XX_CLK)
197
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
56
index XXXXXXX..XXXXXXX 100644
198
index XXXXXXX..XXXXXXX 100644
57
--- a/hw/arm/aspeed_ast2600.c
199
--- a/hw/misc/npcm7xx_clk.c
58
+++ b/hw/arm/aspeed_ast2600.c
200
+++ b/hw/misc/npcm7xx_clk.c
59
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
60
}
61
62
/* I2C */
63
+ object_property_set_link(OBJECT(&s->i2c), OBJECT(s->dram_mr), "dram", &err);
64
+ if (err) {
65
+ error_propagate(errp, err);
66
+ return;
67
+ }
68
object_property_set_bool(OBJECT(&s->i2c), true, "realized", &err);
69
if (err) {
70
error_propagate(errp, err);
71
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/hw/arm/aspeed_soc.c
74
+++ b/hw/arm/aspeed_soc.c
75
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
76
}
77
78
/* I2C */
79
+ object_property_set_link(OBJECT(&s->i2c), OBJECT(s->dram_mr), "dram", &err);
80
+ if (err) {
81
+ error_propagate(errp, err);
82
+ return;
83
+ }
84
object_property_set_bool(OBJECT(&s->i2c), true, "realized", &err);
85
if (err) {
86
error_propagate(errp, err);
87
diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/hw/i2c/aspeed_i2c.c
90
+++ b/hw/i2c/aspeed_i2c.c
91
@@ -XXX,XX +XXX,XX @@
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"
92
#include "migration/vmstate.h"
206
#include "migration/vmstate.h"
207
#include "qemu/error-report.h"
93
#include "qemu/log.h"
208
#include "qemu/log.h"
94
#include "qemu/module.h"
95
+#include "qemu/error-report.h"
96
+#include "qapi/error.h"
97
#include "hw/i2c/aspeed_i2c.h"
98
#include "hw/irq.h"
99
+#include "hw/qdev-properties.h"
100
101
/* I2C Global Register */
102
103
@@ -XXX,XX +XXX,XX @@
209
@@ -XXX,XX +XXX,XX @@
104
#define I2CD_BYTE_BUF_TX_MASK 0xff
210
#include "trace.h"
105
#define I2CD_BYTE_BUF_RX_SHIFT 8
211
#include "sysemu/watchdog.h"
106
#define I2CD_BYTE_BUF_RX_MASK 0xff
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 */
107
-
238
-
108
+#define I2CD_DMA_ADDR 0x24 /* DMA Buffer Address */
239
/* The number of watchdogs that can trigger a reset. */
109
+#define I2CD_DMA_LEN 0x28 /* DMA Transfer Length < 4KB */
240
#define NPCM7XX_NR_WATCHDOGS (3)
110
241
111
static inline bool aspeed_i2c_bus_is_master(AspeedI2CBus *bus)
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
+ }
834
+ }
835
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
836
+ src = npcm7xx_get_clock(clk, divider_init_info_list[i].src_type,
837
+ divider_init_info_list[i].src_index);
838
+ clock_set_source(clk->dividers[i].clock_in, src);
839
+ }
840
+}
841
+
842
static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size)
112
{
843
{
113
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_i2c_bus_read(void *opaque, hwaddr offset,
844
uint32_t reg = offset / sizeof(uint32_t);
114
unsigned size)
845
@@ -XXX,XX +XXX,XX @@ static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size)
115
{
846
*
116
AspeedI2CBus *bus = opaque;
847
* The 4 LSBs are always zero: (1e9 / 640) << 4 = 25000000.
117
+ AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(bus->controller);
848
*/
118
849
- value = (((now_ns - s->ref_ns) / 640) << 4) % NPCM7XX_TIMER_REF_HZ;
119
switch (offset) {
850
+ value = (((now_ns - s->ref_ns) / 640) << 4) % NPCM7XX_CLOCK_REF_HZ;
120
case I2CD_FUN_CTRL_REG:
851
break;
121
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_i2c_bus_read(void *opaque, hwaddr offset,
852
122
return bus->buf;
123
case I2CD_CMD_REG:
124
return bus->cmd | (i2c_bus_busy(bus->bus) << 16);
125
+ case I2CD_DMA_ADDR:
126
+ if (!aic->has_dma) {
127
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: No DMA support\n", __func__);
128
+ return -1;
129
+ }
130
+ return bus->dma_addr;
131
+ case I2CD_DMA_LEN:
132
+ if (!aic->has_dma) {
133
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: No DMA support\n", __func__);
134
+ return -1;
135
+ }
136
+ return bus->dma_len;
137
default:
853
default:
138
qemu_log_mask(LOG_GUEST_ERROR,
854
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_write(void *opaque, hwaddr offset,
139
"%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, offset);
855
value |= (value & PLLCON_LOKS);
140
@@ -XXX,XX +XXX,XX @@ static uint8_t aspeed_i2c_get_state(AspeedI2CBus *bus)
141
return (bus->cmd >> I2CD_TX_STATE_SHIFT) & I2CD_TX_STATE_MASK;
142
}
143
144
+static int aspeed_i2c_dma_read(AspeedI2CBus *bus, uint8_t *data)
145
+{
146
+ MemTxResult result;
147
+ AspeedI2CState *s = bus->controller;
148
+
149
+ result = address_space_read(&s->dram_as, bus->dma_addr,
150
+ MEMTXATTRS_UNSPECIFIED, data, 1);
151
+ if (result != MEMTX_OK) {
152
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: DRAM read failed @%08x\n",
153
+ __func__, bus->dma_addr);
154
+ return -1;
155
+ }
156
+
157
+ bus->dma_addr++;
158
+ bus->dma_len--;
159
+ return 0;
160
+}
161
+
162
static int aspeed_i2c_bus_send(AspeedI2CBus *bus, uint8_t pool_start)
163
{
164
AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(bus->controller);
165
@@ -XXX,XX +XXX,XX @@ static int aspeed_i2c_bus_send(AspeedI2CBus *bus, uint8_t pool_start)
166
}
856
}
167
}
857
}
168
bus->cmd &= ~I2CD_TX_BUFF_ENABLE;
858
+ /* Only update PLL when it is locked. */
169
+ } else if (bus->cmd & I2CD_TX_DMA_ENABLE) {
859
+ if (value & PLLCON_LOKI) {
170
+ while (bus->dma_len) {
860
+ npcm7xx_clk_update_pll(&s->plls[find_pll_by_reg(reg)]);
171
+ uint8_t data;
172
+ aspeed_i2c_dma_read(bus, &data);
173
+ ret = i2c_send(bus->bus, data);
174
+ if (ret) {
175
+ break;
176
+ }
177
+ }
178
+ bus->cmd &= ~I2CD_TX_DMA_ENABLE;
179
} else {
180
ret = i2c_send(bus->bus, bus->buf);
181
}
182
@@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_bus_recv(AspeedI2CBus *bus)
183
bus->pool_ctrl &= ~(0xff << 24);
184
bus->pool_ctrl |= (i & 0xff) << 24;
185
bus->cmd &= ~I2CD_RX_BUFF_ENABLE;
186
+ } else if (bus->cmd & I2CD_RX_DMA_ENABLE) {
187
+ uint8_t data;
188
+
189
+ while (bus->dma_len) {
190
+ MemTxResult result;
191
+
192
+ data = i2c_recv(bus->bus);
193
+ result = address_space_write(&s->dram_as, bus->dma_addr,
194
+ MEMTXATTRS_UNSPECIFIED, &data, 1);
195
+ if (result != MEMTX_OK) {
196
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: DRAM write failed @%08x\n",
197
+ __func__, bus->dma_addr);
198
+ return;
199
+ }
200
+ bus->dma_addr++;
201
+ bus->dma_len--;
202
+ }
203
+ bus->cmd &= ~I2CD_RX_DMA_ENABLE;
204
} else {
205
data = i2c_recv(bus->bus);
206
bus->buf = (data & I2CD_BYTE_BUF_RX_MASK) << I2CD_BYTE_BUF_RX_SHIFT;
207
@@ -XXX,XX +XXX,XX @@ static uint8_t aspeed_i2c_get_addr(AspeedI2CBus *bus)
208
uint8_t *pool_base = aic->bus_pool_base(bus);
209
210
return pool_base[0];
211
+ } else if (bus->cmd & I2CD_TX_DMA_ENABLE) {
212
+ uint8_t data;
213
+
214
+ aspeed_i2c_dma_read(bus, &data);
215
+ return data;
216
} else {
217
return bus->buf;
218
}
219
@@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_bus_handle_cmd(AspeedI2CBus *bus, uint64_t value)
220
*/
221
pool_start++;
222
}
223
+ } else if (bus->cmd & I2CD_TX_DMA_ENABLE) {
224
+ if (bus->dma_len == 0) {
225
+ bus->cmd &= ~I2CD_M_TX_CMD;
226
+ }
227
} else {
228
bus->cmd &= ~I2CD_M_TX_CMD;
229
}
230
@@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_bus_write(void *opaque, hwaddr offset,
231
break;
232
}
233
234
+ if (!aic->has_dma &&
235
+ value & (I2CD_RX_DMA_ENABLE | I2CD_TX_DMA_ENABLE)) {
236
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: No DMA support\n", __func__);
237
+ break;
238
+ }
239
+
240
aspeed_i2c_bus_handle_cmd(bus, value);
241
aspeed_i2c_bus_raise_interrupt(bus);
242
break;
243
+ case I2CD_DMA_ADDR:
244
+ if (!aic->has_dma) {
245
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: No DMA support\n", __func__);
246
+ break;
247
+ }
248
+
249
+ bus->dma_addr = value & 0xfffffffc;
250
+ break;
251
+
252
+ case I2CD_DMA_LEN:
253
+ if (!aic->has_dma) {
254
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: No DMA support\n", __func__);
255
+ break;
256
+ }
257
+
258
+ bus->dma_len = value & 0xfff;
259
+ if (!bus->dma_len) {
260
+ qemu_log_mask(LOG_UNIMP, "%s: invalid DMA length\n", __func__);
261
+ }
861
+ }
262
+ break;
862
+ break;
263
863
+
264
default:
864
+ case NPCM7XX_CLK_CLKSEL:
265
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
865
+ npcm7xx_clk_update_all_sels(s);
266
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps aspeed_i2c_pool_ops = {
866
+ break;
267
867
+
268
static const VMStateDescription aspeed_i2c_bus_vmstate = {
868
+ case NPCM7XX_CLK_CLKDIV1:
269
.name = TYPE_ASPEED_I2C,
869
+ case NPCM7XX_CLK_CLKDIV2:
270
- .version_id = 2,
870
+ case NPCM7XX_CLK_CLKDIV3:
271
- .minimum_version_id = 2,
871
+ npcm7xx_clk_update_all_dividers(s);
272
+ .version_id = 3,
872
break;
273
+ .minimum_version_id = 3,
873
274
.fields = (VMStateField[]) {
874
case NPCM7XX_CLK_CNTR25M:
275
VMSTATE_UINT8(id, AspeedI2CBus),
875
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_enter_reset(Object *obj, ResetType type)
276
VMSTATE_UINT32(ctrl, AspeedI2CBus),
876
case RESET_TYPE_COLD:
277
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription aspeed_i2c_bus_vmstate = {
877
memcpy(s->regs, cold_reset_values, sizeof(cold_reset_values));
278
VMSTATE_UINT32(cmd, AspeedI2CBus),
878
s->ref_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
279
VMSTATE_UINT32(buf, AspeedI2CBus),
879
+ npcm7xx_clk_update_all_clocks(s);
280
VMSTATE_UINT32(pool_ctrl, AspeedI2CBus),
880
return;
281
+ VMSTATE_UINT32(dma_addr, AspeedI2CBus),
282
+ VMSTATE_UINT32(dma_len, AspeedI2CBus),
283
VMSTATE_END_OF_LIST()
284
}
881
}
285
};
882
286
@@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_reset(DeviceState *dev)
883
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_enter_reset(Object *obj, ResetType type)
287
s->busses[i].intr_status = 0;
884
__func__, type);
288
s->busses[i].cmd = 0;
289
s->busses[i].buf = 0;
290
+ s->busses[i].dma_addr = 0;
291
+ s->busses[i].dma_len = 0;
292
i2c_end_transfer(s->busses[i].bus);
293
}
294
}
885
}
295
@@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_realize(DeviceState *dev, Error **errp)
886
296
memory_region_init_io(&s->pool_iomem, OBJECT(s), &aspeed_i2c_pool_ops, s,
887
+static void npcm7xx_clk_init_clock_hierarchy(NPCM7xxCLKState *s)
297
"aspeed.i2c-pool", aic->pool_size);
888
+{
298
memory_region_add_subregion(&s->iomem, aic->pool_base, &s->pool_iomem);
889
+ int i;
299
+
890
+
300
+ if (aic->has_dma) {
891
+ s->clkref = qdev_init_clock_in(DEVICE(s), "clkref", NULL, NULL);
301
+ if (!s->dram_mr) {
892
+
302
+ error_setg(errp, TYPE_ASPEED_I2C ": 'dram' link not set");
893
+ /* First pass: init all converter modules */
894
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(pll_init_info_list) != NPCM7XX_CLOCK_NR_PLLS);
895
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(sel_init_info_list) != NPCM7XX_CLOCK_NR_SELS);
896
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(divider_init_info_list)
897
+ != NPCM7XX_CLOCK_NR_DIVIDERS);
898
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
899
+ object_initialize_child(OBJECT(s), pll_init_info_list[i].name,
900
+ &s->plls[i], TYPE_NPCM7XX_CLOCK_PLL);
901
+ npcm7xx_init_clock_pll(&s->plls[i], s,
902
+ &pll_init_info_list[i]);
903
+ }
904
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
905
+ object_initialize_child(OBJECT(s), sel_init_info_list[i].name,
906
+ &s->sels[i], TYPE_NPCM7XX_CLOCK_SEL);
907
+ npcm7xx_init_clock_sel(&s->sels[i], s,
908
+ &sel_init_info_list[i]);
909
+ }
910
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
911
+ object_initialize_child(OBJECT(s), divider_init_info_list[i].name,
912
+ &s->dividers[i], TYPE_NPCM7XX_CLOCK_DIVIDER);
913
+ npcm7xx_init_clock_divider(&s->dividers[i], s,
914
+ &divider_init_info_list[i]);
915
+ }
916
+
917
+ /* Second pass: connect converter modules */
918
+ npcm7xx_connect_clocks(s);
919
+
920
+ clock_update_hz(s->clkref, NPCM7XX_CLOCK_REF_HZ);
921
+}
922
+
923
static void npcm7xx_clk_init(Object *obj)
924
{
925
NPCM7xxCLKState *s = NPCM7XX_CLK(obj);
926
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_init(Object *obj)
927
memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s,
928
TYPE_NPCM7XX_CLK, 4 * KiB);
929
sysbus_init_mmio(&s->parent, &s->iomem);
930
- qdev_init_gpio_in_named(DEVICE(s), npcm7xx_clk_perform_watchdog_reset,
931
- NPCM7XX_WATCHDOG_RESET_GPIO_IN, NPCM7XX_NR_WATCHDOGS);
932
}
933
934
-static const VMStateDescription vmstate_npcm7xx_clk = {
935
- .name = "npcm7xx-clk",
936
+static int npcm7xx_clk_post_load(void *opaque, int version_id)
937
+{
938
+ if (version_id >= 1) {
939
+ NPCM7xxCLKState *clk = opaque;
940
+
941
+ npcm7xx_clk_update_all_clocks(clk);
942
+ }
943
+
944
+ return 0;
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)) {
303
+ return;
959
+ return;
304
+ }
960
+ }
305
+
961
+ }
306
+ address_space_init(&s->dram_as, s->dram_mr, "dma-dram");
962
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
307
+ }
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;
308
}
1054
}
309
1055
310
+static Property aspeed_i2c_properties[] = {
1056
+static const TypeInfo npcm7xx_clk_pll_info = {
311
+ DEFINE_PROP_LINK("dram", AspeedI2CState, dram_mr,
1057
+ .name = TYPE_NPCM7XX_CLOCK_PLL,
312
+ TYPE_MEMORY_REGION, MemoryRegion *),
1058
+ .parent = TYPE_DEVICE,
313
+ DEFINE_PROP_END_OF_LIST(),
1059
+ .instance_size = sizeof(NPCM7xxClockPLLState),
1060
+ .instance_init = npcm7xx_clk_pll_init,
1061
+ .class_init = npcm7xx_clk_pll_class_init,
314
+};
1062
+};
315
+
1063
+
316
static void aspeed_i2c_class_init(ObjectClass *klass, void *data)
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)
317
{
1086
{
318
DeviceClass *dc = DEVICE_CLASS(klass);
1087
+ type_register_static(&npcm7xx_clk_pll_info);
319
1088
+ type_register_static(&npcm7xx_clk_sel_info);
320
dc->vmsd = &aspeed_i2c_vmstate;
1089
+ type_register_static(&npcm7xx_clk_divider_info);
321
dc->reset = aspeed_i2c_reset;
1090
type_register_static(&npcm7xx_clk_info);
322
+ dc->props = aspeed_i2c_properties;
323
dc->realize = aspeed_i2c_realize;
324
dc->desc = "Aspeed I2C Controller";
325
}
1091
}
326
@@ -XXX,XX +XXX,XX @@ static void aspeed_2500_i2c_class_init(ObjectClass *klass, void *data)
1092
type_init(npcm7xx_clk_register_type);
327
aic->pool_base = 0x200;
328
aic->bus_pool_base = aspeed_2500_i2c_bus_pool_base;
329
aic->check_sram = true;
330
+ aic->has_dma = true;
331
}
332
333
static const TypeInfo aspeed_2500_i2c_info = {
334
@@ -XXX,XX +XXX,XX @@ static void aspeed_2600_i2c_class_init(ObjectClass *klass, void *data)
335
aic->pool_size = 0x200;
336
aic->pool_base = 0xC00;
337
aic->bus_pool_base = aspeed_2600_i2c_bus_pool_base;
338
+ aic->has_dma = true;
339
}
340
341
static const TypeInfo aspeed_2600_i2c_info = {
342
--
1093
--
343
2.20.1
1094
2.20.1
344
1095
345
1096
diff view generated by jsdifflib
1
From: Cédric Le Goater <clg@kaod.org>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
The Aspeed I2C controller can operate in different transfer modes :
3
This patch makes NPCM7XX Timer to use a the timer clock generated by the
4
CLK module instead of the magic number TIMER_REF_HZ.
4
5
5
- Byte Buffer mode, using a dedicated register to transfer a
6
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
6
byte. This is what the model supports today.
7
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
7
8
Signed-off-by: Hao Wu <wuhaotsh@google.com>
8
- Pool Buffer mode, using an internal SRAM to transfer multiple
9
Message-id: 20210108190945.949196-3-wuhaotsh@google.com
9
bytes in the same command sequence.
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
11
Each SoC has different SRAM characteristics. On the AST2400, 2048
12
bytes of SRAM are available at offset 0x800 of the controller AHB
13
window. The pool buffer can be configured from 1 to 256 bytes per bus.
14
15
On the AST2500, the SRAM is at offset 0x200 and the pool buffer is of
16
16 bytes per bus.
17
18
On the AST2600, the SRAM is at offset 0xC00 and the pool buffer is of
19
32 bytes per bus. It can be splitted in two for TX and RX but the
20
current model does not add support for it as it it unused by known
21
drivers.
22
23
Signed-off-by: Cédric Le Goater <clg@kaod.org>
24
Reviewed-by: Joel Stanley <joel@jms.id.au>
25
Tested-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>
26
Signed-off-by: Cédric Le Goater <clg@kaod.org>
27
Message-id: 20191119141211.25716-2-clg@kaod.org
28
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
---
12
---
30
include/hw/i2c/aspeed_i2c.h | 8 ++
13
include/hw/misc/npcm7xx_clk.h | 6 -----
31
hw/i2c/aspeed_i2c.c | 197 ++++++++++++++++++++++++++++++++----
14
include/hw/timer/npcm7xx_timer.h | 1 +
32
2 files changed, 186 insertions(+), 19 deletions(-)
15
hw/arm/npcm7xx.c | 5 ++++
16
hw/timer/npcm7xx_timer.c | 39 +++++++++++++++-----------------
17
4 files changed, 24 insertions(+), 27 deletions(-)
33
18
34
diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h
19
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
35
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
36
--- a/include/hw/i2c/aspeed_i2c.h
21
--- a/include/hw/misc/npcm7xx_clk.h
37
+++ b/include/hw/i2c/aspeed_i2c.h
22
+++ b/include/hw/misc/npcm7xx_clk.h
38
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@
39
OBJECT_CHECK(AspeedI2CState, (obj), TYPE_ASPEED_I2C)
24
#include "hw/clock.h"
40
25
#include "hw/sysbus.h"
41
#define ASPEED_I2C_NR_BUSSES 16
26
42
+#define ASPEED_I2C_MAX_POOL_SIZE 0x800
27
-/*
43
28
- * The reference clock frequency for the timer modules, and the SECCNT and
44
struct AspeedI2CState;
29
- * CNTR25M registers in this module, is always 25 MHz.
45
30
- */
46
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedI2CBus {
31
-#define NPCM7XX_TIMER_REF_HZ (25000000)
47
uint32_t intr_status;
32
-
48
uint32_t cmd;
33
/*
49
uint32_t buf;
34
* Number of registers in our device state structure. Don't change this without
50
+ uint32_t pool_ctrl;
35
* incrementing the version_id in the vmstate.
51
} AspeedI2CBus;
36
diff --git a/include/hw/timer/npcm7xx_timer.h b/include/hw/timer/npcm7xx_timer.h
52
37
index XXXXXXX..XXXXXXX 100644
53
typedef struct AspeedI2CState {
38
--- a/include/hw/timer/npcm7xx_timer.h
54
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedI2CState {
39
+++ b/include/hw/timer/npcm7xx_timer.h
55
qemu_irq irq;
40
@@ -XXX,XX +XXX,XX @@ struct NPCM7xxTimerCtrlState {
56
41
57
uint32_t intr_status;
42
uint32_t tisr;
58
+ MemoryRegion pool_iomem;
43
59
+ uint8_t pool[ASPEED_I2C_MAX_POOL_SIZE];
44
+ Clock *clock;
60
45
NPCM7xxTimer timer[NPCM7XX_TIMERS_PER_CTRL];
61
AspeedI2CBus busses[ASPEED_I2C_NR_BUSSES];
46
NPCM7xxWatchdogTimer watchdog_timer;
62
} AspeedI2CState;
47
};
63
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedI2CClass {
48
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
64
uint8_t reg_size;
49
index XXXXXXX..XXXXXXX 100644
65
uint8_t gap;
50
--- a/hw/arm/npcm7xx.c
66
qemu_irq (*bus_get_irq)(AspeedI2CBus *);
51
+++ b/hw/arm/npcm7xx.c
52
@@ -XXX,XX +XXX,XX @@
53
#include "hw/char/serial.h"
54
#include "hw/loader.h"
55
#include "hw/misc/unimp.h"
56
+#include "hw/qdev-clock.h"
57
#include "hw/qdev-properties.h"
58
#include "qapi/error.h"
59
#include "qemu/units.h"
60
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
61
int first_irq;
62
int j;
63
64
+ /* Connect the timer clock. */
65
+ qdev_connect_clock_in(DEVICE(&s->tim[i]), "clock", qdev_get_clock_out(
66
+ DEVICE(&s->clk), "timer-clock"));
67
+
67
+
68
+ uint64_t pool_size;
68
sysbus_realize(sbd, &error_abort);
69
+ hwaddr pool_base;
69
sysbus_mmio_map(sbd, 0, npcm7xx_tim_addr[i]);
70
+ uint8_t *(*bus_pool_base)(AspeedI2CBus *);
70
71
} AspeedI2CClass;
71
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
72
73
I2CBus *aspeed_i2c_get_bus(DeviceState *dev, int busnr);
74
diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c
75
index XXXXXXX..XXXXXXX 100644
72
index XXXXXXX..XXXXXXX 100644
76
--- a/hw/i2c/aspeed_i2c.c
73
--- a/hw/timer/npcm7xx_timer.c
77
+++ b/hw/i2c/aspeed_i2c.c
74
+++ b/hw/timer/npcm7xx_timer.c
78
@@ -XXX,XX +XXX,XX @@
75
@@ -XXX,XX +XXX,XX @@
79
/* I2C Device (Bus) Register */
76
#include "qemu/osdep.h"
80
77
81
#define I2CD_FUN_CTRL_REG 0x00 /* I2CD Function Control */
78
#include "hw/irq.h"
82
-#define I2CD_BUFF_SEL_MASK (0x7 << 20)
79
+#include "hw/qdev-clock.h"
83
-#define I2CD_BUFF_SEL(x) (x << 20)
80
#include "hw/qdev-properties.h"
84
+#define I2CD_POOL_PAGE_SEL(x) (((x) >> 20) & 0x7) /* AST2400 */
81
-#include "hw/misc/npcm7xx_clk.h"
85
#define I2CD_M_SDA_LOCK_EN (0x1 << 16)
82
#include "hw/timer/npcm7xx_timer.h"
86
#define I2CD_MULTI_MASTER_DIS (0x1 << 15)
83
#include "migration/vmstate.h"
87
#define I2CD_M_SCL_DRIVE_EN (0x1 << 14)
84
#include "qemu/bitops.h"
88
@@ -XXX,XX +XXX,XX @@
85
@@ -XXX,XX +XXX,XX @@ static uint32_t npcm7xx_tcsr_prescaler(uint32_t tcsr)
89
#define I2CD_SCL_O_OUT_DIR (0x1 << 12)
86
/* Convert a timer cycle count to a time interval in nanoseconds. */
90
#define I2CD_BUS_RECOVER_CMD_EN (0x1 << 11)
87
static int64_t npcm7xx_timer_count_to_ns(NPCM7xxTimer *t, uint32_t count)
91
#define I2CD_S_ALT_EN (0x1 << 10)
88
{
92
-#define I2CD_RX_DMA_ENABLE (0x1 << 9)
89
- int64_t ns = count;
93
-#define I2CD_TX_DMA_ENABLE (0x1 << 8)
90
+ int64_t ticks = count;
94
91
95
/* Command Bit */
92
- ns *= NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ;
96
+#define I2CD_RX_DMA_ENABLE (0x1 << 9)
93
- ns *= npcm7xx_tcsr_prescaler(t->tcsr);
97
+#define I2CD_TX_DMA_ENABLE (0x1 << 8)
94
+ ticks *= npcm7xx_tcsr_prescaler(t->tcsr);
98
+#define I2CD_RX_BUFF_ENABLE (0x1 << 7)
95
99
+#define I2CD_TX_BUFF_ENABLE (0x1 << 6)
96
- return ns;
100
#define I2CD_M_STOP_CMD (0x1 << 5)
97
+ return clock_ticks_to_ns(t->ctrl->clock, ticks);
101
#define I2CD_M_S_RX_CMD_LAST (0x1 << 4)
102
#define I2CD_M_RX_CMD (0x1 << 3)
103
@@ -XXX,XX +XXX,XX @@
104
#define I2CD_M_START_CMD (0x1)
105
106
#define I2CD_DEV_ADDR_REG 0x18 /* Slave Device Address */
107
-#define I2CD_BUF_CTRL_REG 0x1c /* Pool Buffer Control */
108
+#define I2CD_POOL_CTRL_REG 0x1c /* Pool Buffer Control */
109
+#define I2CD_POOL_RX_COUNT(x) (((x) >> 24) & 0xff)
110
+#define I2CD_POOL_RX_SIZE(x) ((((x) >> 16) & 0xff) + 1)
111
+#define I2CD_POOL_TX_COUNT(x) ((((x) >> 8) & 0xff) + 1)
112
+#define I2CD_POOL_OFFSET(x) (((x) & 0x3f) << 2) /* AST2400 */
113
#define I2CD_BYTE_BUF_REG 0x20 /* Transmit/Receive Byte Buffer */
114
#define I2CD_BYTE_BUF_TX_SHIFT 0
115
#define I2CD_BYTE_BUF_TX_MASK 0xff
116
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_i2c_bus_read(void *opaque, hwaddr offset,
117
return bus->intr_ctrl;
118
case I2CD_INTR_STS_REG:
119
return bus->intr_status;
120
+ case I2CD_POOL_CTRL_REG:
121
+ return bus->pool_ctrl;
122
case I2CD_BYTE_BUF_REG:
123
return bus->buf;
124
case I2CD_CMD_REG:
125
@@ -XXX,XX +XXX,XX @@ static uint8_t aspeed_i2c_get_state(AspeedI2CBus *bus)
126
return (bus->cmd >> I2CD_TX_STATE_SHIFT) & I2CD_TX_STATE_MASK;
127
}
98
}
128
99
129
+static int aspeed_i2c_bus_send(AspeedI2CBus *bus, uint8_t pool_start)
100
/* Convert a time interval in nanoseconds to a timer cycle count. */
130
+{
101
static uint32_t npcm7xx_timer_ns_to_count(NPCM7xxTimer *t, int64_t ns)
131
+ AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(bus->controller);
132
+ int ret = -1;
133
+ int i;
134
+
135
+ if (bus->cmd & I2CD_TX_BUFF_ENABLE) {
136
+ for (i = pool_start; i < I2CD_POOL_TX_COUNT(bus->pool_ctrl); i++) {
137
+ uint8_t *pool_base = aic->bus_pool_base(bus);
138
+
139
+ ret = i2c_send(bus->bus, pool_base[i]);
140
+ if (ret) {
141
+ break;
142
+ }
143
+ }
144
+ bus->cmd &= ~I2CD_TX_BUFF_ENABLE;
145
+ } else {
146
+ ret = i2c_send(bus->bus, bus->buf);
147
+ }
148
+
149
+ return ret;
150
+}
151
+
152
+static void aspeed_i2c_bus_recv(AspeedI2CBus *bus)
153
+{
154
+ AspeedI2CState *s = bus->controller;
155
+ AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(s);
156
+ uint8_t data;
157
+ int i;
158
+
159
+ if (bus->cmd & I2CD_RX_BUFF_ENABLE) {
160
+ uint8_t *pool_base = aic->bus_pool_base(bus);
161
+
162
+ for (i = 0; i < I2CD_POOL_RX_SIZE(bus->pool_ctrl); i++) {
163
+ pool_base[i] = i2c_recv(bus->bus);
164
+ }
165
+
166
+ /* Update RX count */
167
+ bus->pool_ctrl &= ~(0xff << 24);
168
+ bus->pool_ctrl |= (i & 0xff) << 24;
169
+ bus->cmd &= ~I2CD_RX_BUFF_ENABLE;
170
+ } else {
171
+ data = i2c_recv(bus->bus);
172
+ bus->buf = (data & I2CD_BYTE_BUF_RX_MASK) << I2CD_BYTE_BUF_RX_SHIFT;
173
+ }
174
+}
175
+
176
static void aspeed_i2c_handle_rx_cmd(AspeedI2CBus *bus)
177
{
102
{
178
- uint8_t ret;
103
- int64_t count;
179
-
104
-
180
aspeed_i2c_set_state(bus, I2CD_MRXD);
105
- count = ns / (NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ);
181
- ret = i2c_recv(bus->bus);
106
- count /= npcm7xx_tcsr_prescaler(t->tcsr);
182
+ aspeed_i2c_bus_recv(bus);
107
-
183
bus->intr_status |= I2CD_INTR_RX_DONE;
108
- return count;
184
- bus->buf = (ret & I2CD_BYTE_BUF_RX_MASK) << I2CD_BYTE_BUF_RX_SHIFT;
109
+ return ns / clock_ticks_to_ns(t->ctrl->clock,
185
if (bus->cmd & I2CD_M_S_RX_CMD_LAST) {
110
+ npcm7xx_tcsr_prescaler(t->tcsr));
186
i2c_nack(bus->bus);
187
}
188
@@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_handle_rx_cmd(AspeedI2CBus *bus)
189
aspeed_i2c_set_state(bus, I2CD_MACTIVE);
190
}
111
}
191
112
192
+static uint8_t aspeed_i2c_get_addr(AspeedI2CBus *bus)
113
static uint32_t npcm7xx_watchdog_timer_prescaler(const NPCM7xxWatchdogTimer *t)
193
+{
114
@@ -XXX,XX +XXX,XX @@ static uint32_t npcm7xx_watchdog_timer_prescaler(const NPCM7xxWatchdogTimer *t)
194
+ AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(bus->controller);
115
static void npcm7xx_watchdog_timer_reset_cycles(NPCM7xxWatchdogTimer *t,
195
+
116
int64_t cycles)
196
+ if (bus->cmd & I2CD_TX_BUFF_ENABLE) {
197
+ uint8_t *pool_base = aic->bus_pool_base(bus);
198
+
199
+ return pool_base[0];
200
+ } else {
201
+ return bus->buf;
202
+ }
203
+}
204
+
205
/*
206
* The state machine needs some refinement. It is only used to track
207
* invalid STOP commands for the moment.
208
*/
209
static void aspeed_i2c_bus_handle_cmd(AspeedI2CBus *bus, uint64_t value)
210
{
117
{
211
+ uint8_t pool_start = 0;
118
- uint32_t prescaler = npcm7xx_watchdog_timer_prescaler(t);
212
+
119
- int64_t ns = (NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ) * cycles;
213
bus->cmd &= ~0xFFFF;
120
+ int64_t ticks = cycles * npcm7xx_watchdog_timer_prescaler(t);
214
bus->cmd |= value & 0xFFFF;
121
+ int64_t ns = clock_ticks_to_ns(t->ctrl->clock, ticks);
215
122
216
if (bus->cmd & I2CD_M_START_CMD) {
123
/*
217
uint8_t state = aspeed_i2c_get_state(bus) & I2CD_MACTIVE ?
124
* The reset function always clears the current timer. The caller of the
218
I2CD_MSTARTR : I2CD_MSTART;
125
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_watchdog_timer_reset_cycles(NPCM7xxWatchdogTimer *t,
219
+ uint8_t addr;
126
*/
220
127
npcm7xx_timer_clear(&t->base_timer);
221
aspeed_i2c_set_state(bus, state);
128
222
129
- ns *= prescaler;
223
- if (i2c_start_transfer(bus->bus, extract32(bus->buf, 1, 7),
130
t->base_timer.remaining_ns = ns;
224
- extract32(bus->buf, 0, 1))) {
131
}
225
+ addr = aspeed_i2c_get_addr(bus);
132
226
+
133
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_hold_reset(Object *obj)
227
+ if (i2c_start_transfer(bus->bus, extract32(addr, 1, 7),
134
qemu_irq_lower(s->watchdog_timer.irq);
228
+ extract32(addr, 0, 1))) {
135
}
229
bus->intr_status |= I2CD_INTR_TX_NAK;
136
230
} else {
137
-static void npcm7xx_timer_realize(DeviceState *dev, Error **errp)
231
bus->intr_status |= I2CD_INTR_TX_ACK;
138
+static void npcm7xx_timer_init(Object *obj)
232
}
139
{
233
140
- NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(dev);
234
- /* START command is also a TX command, as the slave address is
141
- SysBusDevice *sbd = &s->parent;
235
- * sent on the bus */
142
+ NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(obj);
236
- bus->cmd &= ~(I2CD_M_START_CMD | I2CD_M_TX_CMD);
143
+ DeviceState *dev = DEVICE(obj);
237
+ bus->cmd &= ~I2CD_M_START_CMD;
144
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
238
+
145
int i;
239
+ /*
146
NPCM7xxWatchdogTimer *w;
240
+ * The START command is also a TX command, as the slave
147
241
+ * address is sent on the bus. Drop the TX flag if nothing
148
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_realize(DeviceState *dev, Error **errp)
242
+ * else needs to be sent in this sequence.
149
npcm7xx_watchdog_timer_expired, w);
243
+ */
150
sysbus_init_irq(sbd, &w->irq);
244
+ if (bus->cmd & I2CD_TX_BUFF_ENABLE) {
151
245
+ if (I2CD_POOL_TX_COUNT(bus->pool_ctrl) == 1) {
152
- memory_region_init_io(&s->iomem, OBJECT(s), &npcm7xx_timer_ops, s,
246
+ bus->cmd &= ~I2CD_M_TX_CMD;
153
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_timer_ops, s,
247
+ } else {
154
TYPE_NPCM7XX_TIMER, 4 * KiB);
248
+ /*
155
sysbus_init_mmio(sbd, &s->iomem);
249
+ * Increase the start index in the TX pool buffer to
156
qdev_init_gpio_out_named(dev, &w->reset_signal,
250
+ * skip the address byte.
157
NPCM7XX_WATCHDOG_RESET_GPIO_OUT, 1);
251
+ */
158
+ s->clock = qdev_init_clock_in(dev, "clock", NULL, NULL);
252
+ pool_start++;
159
}
253
+ }
160
254
+ } else {
161
static const VMStateDescription vmstate_npcm7xx_base_timer = {
255
+ bus->cmd &= ~I2CD_M_TX_CMD;
162
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_npcm7xx_watchdog_timer = {
256
+ }
163
257
164
static const VMStateDescription vmstate_npcm7xx_timer_ctrl = {
258
/* No slave found */
165
.name = "npcm7xx-timer-ctrl",
259
if (!i2c_bus_busy(bus->bus)) {
260
@@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_bus_handle_cmd(AspeedI2CBus *bus, uint64_t value)
261
262
if (bus->cmd & I2CD_M_TX_CMD) {
263
aspeed_i2c_set_state(bus, I2CD_MTXD);
264
- if (i2c_send(bus->bus, bus->buf)) {
265
+ if (aspeed_i2c_bus_send(bus, pool_start)) {
266
bus->intr_status |= (I2CD_INTR_TX_NAK);
267
i2c_end_transfer(bus->bus);
268
} else {
269
@@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_bus_write(void *opaque, hwaddr offset,
270
qemu_log_mask(LOG_UNIMP, "%s: slave mode not implemented\n",
271
__func__);
272
break;
273
+ case I2CD_POOL_CTRL_REG:
274
+ bus->pool_ctrl &= ~0xffffff;
275
+ bus->pool_ctrl |= (value & 0xffffff);
276
+ break;
277
+
278
case I2CD_BYTE_BUF_REG:
279
bus->buf = (value & I2CD_BYTE_BUF_TX_MASK) << I2CD_BYTE_BUF_TX_SHIFT;
280
break;
281
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps aspeed_i2c_ctrl_ops = {
282
.endianness = DEVICE_LITTLE_ENDIAN,
283
};
284
285
+static uint64_t aspeed_i2c_pool_read(void *opaque, hwaddr offset,
286
+ unsigned size)
287
+{
288
+ AspeedI2CState *s = opaque;
289
+ uint64_t ret = 0;
290
+ int i;
291
+
292
+ for (i = 0; i < size; i++) {
293
+ ret |= (uint64_t) s->pool[offset + i] << (8 * i);
294
+ }
295
+
296
+ return ret;
297
+}
298
+
299
+static void aspeed_i2c_pool_write(void *opaque, hwaddr offset,
300
+ uint64_t value, unsigned size)
301
+{
302
+ AspeedI2CState *s = opaque;
303
+ int i;
304
+
305
+ for (i = 0; i < size; i++) {
306
+ s->pool[offset + i] = (value >> (8 * i)) & 0xFF;
307
+ }
308
+}
309
+
310
+static const MemoryRegionOps aspeed_i2c_pool_ops = {
311
+ .read = aspeed_i2c_pool_read,
312
+ .write = aspeed_i2c_pool_write,
313
+ .endianness = DEVICE_LITTLE_ENDIAN,
314
+ .valid = {
315
+ .min_access_size = 1,
316
+ .max_access_size = 4,
317
+ },
318
+};
319
+
320
static const VMStateDescription aspeed_i2c_bus_vmstate = {
321
.name = TYPE_ASPEED_I2C,
322
- .version_id = 1,
166
- .version_id = 1,
323
- .minimum_version_id = 1,
167
- .minimum_version_id = 1,
324
+ .version_id = 2,
168
+ .version_id = 2,
325
+ .minimum_version_id = 2,
169
+ .minimum_version_id = 2,
326
.fields = (VMStateField[]) {
170
.fields = (VMStateField[]) {
327
VMSTATE_UINT8(id, AspeedI2CBus),
171
VMSTATE_UINT32(tisr, NPCM7xxTimerCtrlState),
328
VMSTATE_UINT32(ctrl, AspeedI2CBus),
172
+ VMSTATE_CLOCK(clock, NPCM7xxTimerCtrlState),
329
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription aspeed_i2c_bus_vmstate = {
173
VMSTATE_STRUCT_ARRAY(timer, NPCM7xxTimerCtrlState,
330
VMSTATE_UINT32(intr_status, AspeedI2CBus),
174
NPCM7XX_TIMERS_PER_CTRL, 0, vmstate_npcm7xx_timer,
331
VMSTATE_UINT32(cmd, AspeedI2CBus),
175
NPCM7xxTimer),
332
VMSTATE_UINT32(buf, AspeedI2CBus),
176
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_class_init(ObjectClass *klass, void *data)
333
+ VMSTATE_UINT32(pool_ctrl, AspeedI2CBus),
177
QEMU_BUILD_BUG_ON(NPCM7XX_TIMER_REGS_END > NPCM7XX_TIMER_NR_REGS);
334
VMSTATE_END_OF_LIST()
178
335
}
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,
336
};
189
};
337
190
338
static const VMStateDescription aspeed_i2c_vmstate = {
191
static void npcm7xx_timer_register_type(void)
339
.name = TYPE_ASPEED_I2C,
340
- .version_id = 1,
341
- .minimum_version_id = 1,
342
+ .version_id = 2,
343
+ .minimum_version_id = 2,
344
.fields = (VMStateField[]) {
345
VMSTATE_UINT32(intr_status, AspeedI2CState),
346
VMSTATE_STRUCT_ARRAY(busses, AspeedI2CState,
347
ASPEED_I2C_NR_BUSSES, 1, aspeed_i2c_bus_vmstate,
348
AspeedI2CBus),
349
+ VMSTATE_UINT8_ARRAY(pool, AspeedI2CState, ASPEED_I2C_MAX_POOL_SIZE),
350
VMSTATE_END_OF_LIST()
351
}
352
};
353
@@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_realize(DeviceState *dev, Error **errp)
354
memory_region_add_subregion(&s->iomem, aic->reg_size * (i + offset),
355
&s->busses[i].mr);
356
}
357
+
358
+ memory_region_init_io(&s->pool_iomem, OBJECT(s), &aspeed_i2c_pool_ops, s,
359
+ "aspeed.i2c-pool", aic->pool_size);
360
+ memory_region_add_subregion(&s->iomem, aic->pool_base, &s->pool_iomem);
361
}
362
363
static void aspeed_i2c_class_init(ObjectClass *klass, void *data)
364
@@ -XXX,XX +XXX,XX @@ static qemu_irq aspeed_2400_i2c_bus_get_irq(AspeedI2CBus *bus)
365
return bus->controller->irq;
366
}
367
368
+static uint8_t *aspeed_2400_i2c_bus_pool_base(AspeedI2CBus *bus)
369
+{
370
+ uint8_t *pool_page =
371
+ &bus->controller->pool[I2CD_POOL_PAGE_SEL(bus->ctrl) * 0x100];
372
+
373
+ return &pool_page[I2CD_POOL_OFFSET(bus->pool_ctrl)];
374
+}
375
+
376
static void aspeed_2400_i2c_class_init(ObjectClass *klass, void *data)
377
{
378
DeviceClass *dc = DEVICE_CLASS(klass);
379
@@ -XXX,XX +XXX,XX @@ static void aspeed_2400_i2c_class_init(ObjectClass *klass, void *data)
380
aic->reg_size = 0x40;
381
aic->gap = 7;
382
aic->bus_get_irq = aspeed_2400_i2c_bus_get_irq;
383
+ aic->pool_size = 0x800;
384
+ aic->pool_base = 0x800;
385
+ aic->bus_pool_base = aspeed_2400_i2c_bus_pool_base;
386
}
387
388
static const TypeInfo aspeed_2400_i2c_info = {
389
@@ -XXX,XX +XXX,XX @@ static qemu_irq aspeed_2500_i2c_bus_get_irq(AspeedI2CBus *bus)
390
return bus->controller->irq;
391
}
392
393
+static uint8_t *aspeed_2500_i2c_bus_pool_base(AspeedI2CBus *bus)
394
+{
395
+ return &bus->controller->pool[bus->id * 0x10];
396
+}
397
+
398
static void aspeed_2500_i2c_class_init(ObjectClass *klass, void *data)
399
{
400
DeviceClass *dc = DEVICE_CLASS(klass);
401
@@ -XXX,XX +XXX,XX @@ static void aspeed_2500_i2c_class_init(ObjectClass *klass, void *data)
402
aic->reg_size = 0x40;
403
aic->gap = 7;
404
aic->bus_get_irq = aspeed_2500_i2c_bus_get_irq;
405
+ aic->pool_size = 0x100;
406
+ aic->pool_base = 0x200;
407
+ aic->bus_pool_base = aspeed_2500_i2c_bus_pool_base;
408
}
409
410
static const TypeInfo aspeed_2500_i2c_info = {
411
@@ -XXX,XX +XXX,XX @@ static qemu_irq aspeed_2600_i2c_bus_get_irq(AspeedI2CBus *bus)
412
return bus->irq;
413
}
414
415
+static uint8_t *aspeed_2600_i2c_bus_pool_base(AspeedI2CBus *bus)
416
+{
417
+ return &bus->controller->pool[bus->id * 0x20];
418
+}
419
+
420
static void aspeed_2600_i2c_class_init(ObjectClass *klass, void *data)
421
{
422
DeviceClass *dc = DEVICE_CLASS(klass);
423
@@ -XXX,XX +XXX,XX @@ static void aspeed_2600_i2c_class_init(ObjectClass *klass, void *data)
424
aic->reg_size = 0x80;
425
aic->gap = -1; /* no gap */
426
aic->bus_get_irq = aspeed_2600_i2c_bus_get_irq;
427
+ aic->pool_size = 0x200;
428
+ aic->pool_base = 0xC00;
429
+ aic->bus_pool_base = aspeed_2600_i2c_bus_pool_base;
430
}
431
432
static const TypeInfo aspeed_2600_i2c_info = {
433
--
192
--
434
2.20.1
193
2.20.1
435
194
436
195
diff view generated by jsdifflib
Deleted patch
1
From: Cédric Le Goater <clg@kaod.org>
2
1
3
Signed-off-by: Cédric Le Goater <clg@kaod.org>
4
Reviewed-by: Joel Stanley <joel@jms.id.au>
5
Tested-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Signed-off-by: Cédric Le Goater <clg@kaod.org>
8
Message-id: 20191119141211.25716-6-clg@kaod.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/i2c/aspeed_i2c.c | 93 ++++++++++++++++++++++++++++++++++++++-------
12
hw/i2c/trace-events | 9 +++++
13
2 files changed, 89 insertions(+), 13 deletions(-)
14
15
diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/i2c/aspeed_i2c.c
18
+++ b/hw/i2c/aspeed_i2c.c
19
@@ -XXX,XX +XXX,XX @@
20
#include "hw/i2c/aspeed_i2c.h"
21
#include "hw/irq.h"
22
#include "hw/qdev-properties.h"
23
+#include "trace.h"
24
25
/* I2C Global Register */
26
27
@@ -XXX,XX +XXX,XX @@ static inline void aspeed_i2c_bus_raise_interrupt(AspeedI2CBus *bus)
28
{
29
AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(bus->controller);
30
31
+ trace_aspeed_i2c_bus_raise_interrupt(bus->intr_status,
32
+ bus->intr_status & I2CD_INTR_TX_NAK ? "nak|" : "",
33
+ bus->intr_status & I2CD_INTR_TX_ACK ? "ack|" : "",
34
+ bus->intr_status & I2CD_INTR_RX_DONE ? "done|" : "",
35
+ bus->intr_status & I2CD_INTR_NORMAL_STOP ? "normal|" : "",
36
+ bus->intr_status & I2CD_INTR_ABNORMAL ? "abnormal" : "");
37
+
38
bus->intr_status &= bus->intr_ctrl;
39
if (bus->intr_status) {
40
bus->controller->intr_status |= 1 << bus->id;
41
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_i2c_bus_read(void *opaque, hwaddr offset,
42
{
43
AspeedI2CBus *bus = opaque;
44
AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(bus->controller);
45
+ uint64_t value = -1;
46
47
switch (offset) {
48
case I2CD_FUN_CTRL_REG:
49
- return bus->ctrl;
50
+ value = bus->ctrl;
51
+ break;
52
case I2CD_AC_TIMING_REG1:
53
- return bus->timing[0];
54
+ value = bus->timing[0];
55
+ break;
56
case I2CD_AC_TIMING_REG2:
57
- return bus->timing[1];
58
+ value = bus->timing[1];
59
+ break;
60
case I2CD_INTR_CTRL_REG:
61
- return bus->intr_ctrl;
62
+ value = bus->intr_ctrl;
63
+ break;
64
case I2CD_INTR_STS_REG:
65
- return bus->intr_status;
66
+ value = bus->intr_status;
67
+ break;
68
case I2CD_POOL_CTRL_REG:
69
- return bus->pool_ctrl;
70
+ value = bus->pool_ctrl;
71
+ break;
72
case I2CD_BYTE_BUF_REG:
73
- return bus->buf;
74
+ value = bus->buf;
75
+ break;
76
case I2CD_CMD_REG:
77
- return bus->cmd | (i2c_bus_busy(bus->bus) << 16);
78
+ value = bus->cmd | (i2c_bus_busy(bus->bus) << 16);
79
+ break;
80
case I2CD_DMA_ADDR:
81
if (!aic->has_dma) {
82
qemu_log_mask(LOG_GUEST_ERROR, "%s: No DMA support\n", __func__);
83
- return -1;
84
+ break;
85
}
86
- return bus->dma_addr;
87
+ value = bus->dma_addr;
88
+ break;
89
case I2CD_DMA_LEN:
90
if (!aic->has_dma) {
91
qemu_log_mask(LOG_GUEST_ERROR, "%s: No DMA support\n", __func__);
92
- return -1;
93
+ break;
94
}
95
- return bus->dma_len;
96
+ value = bus->dma_len;
97
+ break;
98
+
99
default:
100
qemu_log_mask(LOG_GUEST_ERROR,
101
"%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, offset);
102
- return -1;
103
+ value = -1;
104
+ break;
105
}
106
+
107
+ trace_aspeed_i2c_bus_read(bus->id, offset, size, value);
108
+ return value;
109
}
110
111
static void aspeed_i2c_set_state(AspeedI2CBus *bus, uint8_t state)
112
@@ -XXX,XX +XXX,XX @@ static int aspeed_i2c_bus_send(AspeedI2CBus *bus, uint8_t pool_start)
113
for (i = pool_start; i < I2CD_POOL_TX_COUNT(bus->pool_ctrl); i++) {
114
uint8_t *pool_base = aic->bus_pool_base(bus);
115
116
+ trace_aspeed_i2c_bus_send("BUF", i + 1,
117
+ I2CD_POOL_TX_COUNT(bus->pool_ctrl),
118
+ pool_base[i]);
119
ret = i2c_send(bus->bus, pool_base[i]);
120
if (ret) {
121
break;
122
@@ -XXX,XX +XXX,XX @@ static int aspeed_i2c_bus_send(AspeedI2CBus *bus, uint8_t pool_start)
123
while (bus->dma_len) {
124
uint8_t data;
125
aspeed_i2c_dma_read(bus, &data);
126
+ trace_aspeed_i2c_bus_send("DMA", bus->dma_len, bus->dma_len, data);
127
ret = i2c_send(bus->bus, data);
128
if (ret) {
129
break;
130
@@ -XXX,XX +XXX,XX @@ static int aspeed_i2c_bus_send(AspeedI2CBus *bus, uint8_t pool_start)
131
}
132
bus->cmd &= ~I2CD_TX_DMA_ENABLE;
133
} else {
134
+ trace_aspeed_i2c_bus_send("BYTE", pool_start, 1, bus->buf);
135
ret = i2c_send(bus->bus, bus->buf);
136
}
137
138
@@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_bus_recv(AspeedI2CBus *bus)
139
140
for (i = 0; i < I2CD_POOL_RX_SIZE(bus->pool_ctrl); i++) {
141
pool_base[i] = i2c_recv(bus->bus);
142
+ trace_aspeed_i2c_bus_recv("BUF", i + 1,
143
+ I2CD_POOL_RX_SIZE(bus->pool_ctrl),
144
+ pool_base[i]);
145
}
146
147
/* Update RX count */
148
@@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_bus_recv(AspeedI2CBus *bus)
149
MemTxResult result;
150
151
data = i2c_recv(bus->bus);
152
+ trace_aspeed_i2c_bus_recv("DMA", bus->dma_len, bus->dma_len, data);
153
result = address_space_write(&s->dram_as, bus->dma_addr,
154
MEMTXATTRS_UNSPECIFIED, &data, 1);
155
if (result != MEMTX_OK) {
156
@@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_bus_recv(AspeedI2CBus *bus)
157
bus->cmd &= ~I2CD_RX_DMA_ENABLE;
158
} else {
159
data = i2c_recv(bus->bus);
160
+ trace_aspeed_i2c_bus_recv("BYTE", 1, 1, bus->buf);
161
bus->buf = (data & I2CD_BYTE_BUF_RX_MASK) << I2CD_BYTE_BUF_RX_SHIFT;
162
}
163
}
164
@@ -XXX,XX +XXX,XX @@ static bool aspeed_i2c_check_sram(AspeedI2CBus *bus)
165
return true;
166
}
167
168
+static void aspeed_i2c_bus_cmd_dump(AspeedI2CBus *bus)
169
+{
170
+ g_autofree char *cmd_flags;
171
+ uint32_t count;
172
+
173
+ if (bus->cmd & (I2CD_RX_BUFF_ENABLE | I2CD_RX_BUFF_ENABLE)) {
174
+ count = I2CD_POOL_TX_COUNT(bus->pool_ctrl);
175
+ } else if (bus->cmd & (I2CD_RX_DMA_ENABLE | I2CD_RX_DMA_ENABLE)) {
176
+ count = bus->dma_len;
177
+ } else { /* BYTE mode */
178
+ count = 1;
179
+ }
180
+
181
+ cmd_flags = g_strdup_printf("%s%s%s%s%s%s%s%s%s",
182
+ bus->cmd & I2CD_M_START_CMD ? "start|" : "",
183
+ bus->cmd & I2CD_RX_DMA_ENABLE ? "rxdma|" : "",
184
+ bus->cmd & I2CD_TX_DMA_ENABLE ? "txdma|" : "",
185
+ bus->cmd & I2CD_RX_BUFF_ENABLE ? "rxbuf|" : "",
186
+ bus->cmd & I2CD_TX_BUFF_ENABLE ? "txbuf|" : "",
187
+ bus->cmd & I2CD_M_TX_CMD ? "tx|" : "",
188
+ bus->cmd & I2CD_M_RX_CMD ? "rx|" : "",
189
+ bus->cmd & I2CD_M_S_RX_CMD_LAST ? "last|" : "",
190
+ bus->cmd & I2CD_M_STOP_CMD ? "stop" : "");
191
+
192
+ trace_aspeed_i2c_bus_cmd(bus->cmd, cmd_flags, count, bus->intr_status);
193
+}
194
+
195
/*
196
* The state machine needs some refinement. It is only used to track
197
* invalid STOP commands for the moment.
198
@@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_bus_handle_cmd(AspeedI2CBus *bus, uint64_t value)
199
return;
200
}
201
202
+ if (trace_event_get_state_backends(TRACE_ASPEED_I2C_BUS_CMD)) {
203
+ aspeed_i2c_bus_cmd_dump(bus);
204
+ }
205
+
206
if (bus->cmd & I2CD_M_START_CMD) {
207
uint8_t state = aspeed_i2c_get_state(bus) & I2CD_MACTIVE ?
208
I2CD_MSTARTR : I2CD_MSTART;
209
@@ -XXX,XX +XXX,XX @@ static void aspeed_i2c_bus_write(void *opaque, hwaddr offset,
210
AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(bus->controller);
211
bool handle_rx;
212
213
+ trace_aspeed_i2c_bus_write(bus->id, offset, size, value);
214
+
215
switch (offset) {
216
case I2CD_FUN_CTRL_REG:
217
if (value & I2CD_SLAVE_EN) {
218
diff --git a/hw/i2c/trace-events b/hw/i2c/trace-events
219
index XXXXXXX..XXXXXXX 100644
220
--- a/hw/i2c/trace-events
221
+++ b/hw/i2c/trace-events
222
@@ -XXX,XX +XXX,XX @@
223
i2c_event(const char *event, uint8_t address) "%s(addr:0x%02x)"
224
i2c_send(uint8_t address, uint8_t data) "send(addr:0x%02x) data:0x%02x"
225
i2c_recv(uint8_t address, uint8_t data) "recv(addr:0x%02x) data:0x%02x"
226
+
227
+# aspeed_i2c.c
228
+
229
+aspeed_i2c_bus_cmd(uint32_t cmd, const char *cmd_flags, uint32_t count, uint32_t intr_status) "handling cmd=0x%x %s count=%d intr=0x%x"
230
+aspeed_i2c_bus_raise_interrupt(uint32_t intr_status, const char *str1, const char *str2, const char *str3, const char *str4, const char *str5) "handled intr=0x%x %s%s%s%s%s"
231
+aspeed_i2c_bus_read(uint32_t busid, uint64_t offset, unsigned size, uint64_t value) "bus[%d]: To 0x%" PRIx64 " of size %u: 0x%" PRIx64
232
+aspeed_i2c_bus_write(uint32_t busid, uint64_t offset, unsigned size, uint64_t value) "bus[%d]: To 0x%" PRIx64 " of size %u: 0x%" PRIx64
233
+aspeed_i2c_bus_send(const char *mode, int i, int count, uint8_t byte) "%s send %d/%d 0x%02x"
234
+aspeed_i2c_bus_recv(const char *mode, int i, int count, uint8_t byte) "%s recv %d/%d 0x%02x"
235
--
236
2.20.1
237
238
diff view generated by jsdifflib
Deleted patch
1
From: Joel Stanley <joel@jms.id.au>
2
1
3
Most boards have this much.
4
5
Reviewed-by: Cédric Le Goater <clg@kaod.org>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Signed-off-by: Joel Stanley <joel@jms.id.au>
8
Signed-off-by: Cédric Le Goater <clg@kaod.org>
9
Message-id: 20191119141211.25716-7-clg@kaod.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
hw/misc/aspeed_sdmc.c | 6 +++---
13
1 file changed, 3 insertions(+), 3 deletions(-)
14
15
diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/misc/aspeed_sdmc.c
18
+++ b/hw/misc/aspeed_sdmc.c
19
@@ -XXX,XX +XXX,XX @@ static int ast2600_rambits(AspeedSDMCState *s)
20
}
21
22
/* use a common default */
23
- warn_report("Invalid RAM size 0x%" PRIx64 ". Using default 512M",
24
+ warn_report("Invalid RAM size 0x%" PRIx64 ". Using default 1024M",
25
s->ram_size);
26
- s->ram_size = 512 << 20;
27
- return ASPEED_SDMC_AST2600_512MB;
28
+ s->ram_size = 1024 << 20;
29
+ return ASPEED_SDMC_AST2600_1024MB;
30
}
31
32
static void aspeed_sdmc_reset(DeviceState *dev)
33
--
34
2.20.1
35
36
diff view generated by jsdifflib
Deleted patch
1
From: Joel Stanley <joel@jms.id.au>
2
1
3
This models the clock write one to clear registers, and fixes up some
4
incorrect behavior in all of the write to clear registers.
5
6
There was also a typo in one of the register definitions.
7
8
Reviewed-by: Cédric Le Goater <clg@kaod.org>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
Signed-off-by: Joel Stanley <joel@jms.id.au>
11
Signed-off-by: Cédric Le Goater <clg@kaod.org>
12
Message-id: 20191119141211.25716-8-clg@kaod.org
13
[clg: checkpatch.pl fixes ]
14
Signed-off-by: Cédric Le Goater <clg@kaod.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
hw/misc/aspeed_scu.c | 19 ++++++++++++++-----
18
1 file changed, 14 insertions(+), 5 deletions(-)
19
20
diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/misc/aspeed_scu.c
23
+++ b/hw/misc/aspeed_scu.c
24
@@ -XXX,XX +XXX,XX @@
25
#define AST2600_CLK_STOP_CTRL TO_REG(0x80)
26
#define AST2600_CLK_STOP_CTRL_CLR TO_REG(0x84)
27
#define AST2600_CLK_STOP_CTRL2 TO_REG(0x90)
28
-#define AST2600_CLK_STOP_CTR2L_CLR TO_REG(0x94)
29
+#define AST2600_CLK_STOP_CTRL2_CLR TO_REG(0x94)
30
#define AST2600_SDRAM_HANDSHAKE TO_REG(0x100)
31
#define AST2600_HPLL_PARAM TO_REG(0x200)
32
#define AST2600_HPLL_EXT TO_REG(0x204)
33
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_ast2600_scu_read(void *opaque, hwaddr offset,
34
return s->regs[reg];
35
}
36
37
-static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset, uint64_t data,
38
- unsigned size)
39
+static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset,
40
+ uint64_t data64, unsigned size)
41
{
42
AspeedSCUState *s = ASPEED_SCU(opaque);
43
int reg = TO_REG(offset);
44
+ /* Truncate here so bitwise operations below behave as expected */
45
+ uint32_t data = data64;
46
47
if (reg >= ASPEED_AST2600_SCU_NR_REGS) {
48
qemu_log_mask(LOG_GUEST_ERROR,
49
@@ -XXX,XX +XXX,XX @@ static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset, uint64_t data,
50
/* fall through */
51
case AST2600_SYS_RST_CTRL:
52
case AST2600_SYS_RST_CTRL2:
53
+ case AST2600_CLK_STOP_CTRL:
54
+ case AST2600_CLK_STOP_CTRL2:
55
/* W1S (Write 1 to set) registers */
56
s->regs[reg] |= data;
57
return;
58
case AST2600_SYS_RST_CTRL_CLR:
59
case AST2600_SYS_RST_CTRL2_CLR:
60
+ case AST2600_CLK_STOP_CTRL_CLR:
61
+ case AST2600_CLK_STOP_CTRL2_CLR:
62
case AST2600_HW_STRAP1_CLR:
63
case AST2600_HW_STRAP2_CLR:
64
- /* W1C (Write 1 to clear) registers */
65
- s->regs[reg] &= ~data;
66
+ /*
67
+ * W1C (Write 1 to clear) registers are offset by one address from
68
+ * the data register
69
+ */
70
+ s->regs[reg - 1] &= ~data;
71
return;
72
73
case AST2600_RNG_DATA:
74
--
75
2.20.1
76
77
diff view generated by jsdifflib
Deleted patch
1
From: Joel Stanley <joel@jms.id.au>
2
1
3
Users benefit from knowing which watchdog timer has expired. The address
4
of the watchdog's registers unambiguously indicates which has expired,
5
so log that.
6
7
Reviewed-by: Cédric Le Goater <clg@kaod.org>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Signed-off-by: Joel Stanley <joel@jms.id.au>
10
Signed-off-by: Cédric Le Goater <clg@kaod.org>
11
Message-id: 20191119141211.25716-9-clg@kaod.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
hw/watchdog/wdt_aspeed.c | 3 ++-
15
1 file changed, 2 insertions(+), 1 deletion(-)
16
17
diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/watchdog/wdt_aspeed.c
20
+++ b/hw/watchdog/wdt_aspeed.c
21
@@ -XXX,XX +XXX,XX @@ static void aspeed_wdt_timer_expired(void *dev)
22
return;
23
}
24
25
- qemu_log_mask(CPU_LOG_RESET, "Watchdog timer expired.\n");
26
+ qemu_log_mask(CPU_LOG_RESET, "Watchdog timer %" HWADDR_PRIx " expired.\n",
27
+ s->iomem.addr);
28
watchdog_perform_action();
29
timer_del(s->timer);
30
}
31
--
32
2.20.1
33
34
diff view generated by jsdifflib
Deleted patch
1
From: Joel Stanley <joel@jms.id.au>
2
1
3
The AST2600 control register sneakily changed the meaning of bit 4
4
without anyone noticing. It no longer controls the 1MHz vs APB clock
5
select, and instead always runs at 1MHz.
6
7
The AST2500 was always 1MHz too, but it retained bit 4, making it read
8
only. We can model both using the same fixed 1MHz calculation.
9
10
Fixes: 6b2b2a703cad ("hw: wdt_aspeed: Add AST2600 support")
11
Reviewed-by: Cédric Le Goater <clg@kaod.org>
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
Signed-off-by: Joel Stanley <joel@jms.id.au>
14
Signed-off-by: Cédric Le Goater <clg@kaod.org>
15
Message-id: 20191119141211.25716-10-clg@kaod.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
18
include/hw/watchdog/wdt_aspeed.h | 1 +
19
hw/watchdog/wdt_aspeed.c | 21 +++++++++++++++++----
20
2 files changed, 18 insertions(+), 4 deletions(-)
21
22
diff --git a/include/hw/watchdog/wdt_aspeed.h b/include/hw/watchdog/wdt_aspeed.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/watchdog/wdt_aspeed.h
25
+++ b/include/hw/watchdog/wdt_aspeed.h
26
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedWDTClass {
27
uint32_t ext_pulse_width_mask;
28
uint32_t reset_ctrl_reg;
29
void (*reset_pulse)(AspeedWDTState *s, uint32_t property);
30
+ void (*wdt_reload)(AspeedWDTState *s);
31
} AspeedWDTClass;
32
33
#endif /* WDT_ASPEED_H */
34
diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/watchdog/wdt_aspeed.c
37
+++ b/hw/watchdog/wdt_aspeed.c
38
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_wdt_read(void *opaque, hwaddr offset, unsigned size)
39
40
}
41
42
-static void aspeed_wdt_reload(AspeedWDTState *s, bool pclk)
43
+static void aspeed_wdt_reload(AspeedWDTState *s)
44
{
45
uint64_t reload;
46
47
- if (pclk) {
48
+ if (!(s->regs[WDT_CTRL] & WDT_CTRL_1MHZ_CLK)) {
49
reload = muldiv64(s->regs[WDT_RELOAD_VALUE], NANOSECONDS_PER_SECOND,
50
s->pclk_freq);
51
} else {
52
@@ -XXX,XX +XXX,XX @@ static void aspeed_wdt_reload(AspeedWDTState *s, bool pclk)
53
}
54
}
55
56
+static void aspeed_wdt_reload_1mhz(AspeedWDTState *s)
57
+{
58
+ uint64_t reload = s->regs[WDT_RELOAD_VALUE] * 1000ULL;
59
+
60
+ if (aspeed_wdt_is_enabled(s)) {
61
+ timer_mod(s->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + reload);
62
+ }
63
+}
64
+
65
+
66
static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data,
67
unsigned size)
68
{
69
@@ -XXX,XX +XXX,XX @@ static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data,
70
case WDT_RESTART:
71
if ((data & 0xFFFF) == WDT_RESTART_MAGIC) {
72
s->regs[WDT_STATUS] = s->regs[WDT_RELOAD_VALUE];
73
- aspeed_wdt_reload(s, !(s->regs[WDT_CTRL] & WDT_CTRL_1MHZ_CLK));
74
+ awc->wdt_reload(s);
75
}
76
break;
77
case WDT_CTRL:
78
if (enable && !aspeed_wdt_is_enabled(s)) {
79
s->regs[WDT_CTRL] = data;
80
- aspeed_wdt_reload(s, !(data & WDT_CTRL_1MHZ_CLK));
81
+ awc->wdt_reload(s);
82
} else if (!enable && aspeed_wdt_is_enabled(s)) {
83
s->regs[WDT_CTRL] = data;
84
timer_del(s->timer);
85
@@ -XXX,XX +XXX,XX @@ static void aspeed_2400_wdt_class_init(ObjectClass *klass, void *data)
86
awc->offset = 0x20;
87
awc->ext_pulse_width_mask = 0xff;
88
awc->reset_ctrl_reg = SCU_RESET_CONTROL1;
89
+ awc->wdt_reload = aspeed_wdt_reload;
90
}
91
92
static const TypeInfo aspeed_2400_wdt_info = {
93
@@ -XXX,XX +XXX,XX @@ static void aspeed_2500_wdt_class_init(ObjectClass *klass, void *data)
94
awc->ext_pulse_width_mask = 0xfffff;
95
awc->reset_ctrl_reg = SCU_RESET_CONTROL1;
96
awc->reset_pulse = aspeed_2500_wdt_reset_pulse;
97
+ awc->wdt_reload = aspeed_wdt_reload_1mhz;
98
}
99
100
static const TypeInfo aspeed_2500_wdt_info = {
101
@@ -XXX,XX +XXX,XX @@ static void aspeed_2600_wdt_class_init(ObjectClass *klass, void *data)
102
awc->ext_pulse_width_mask = 0xfffff; /* TODO */
103
awc->reset_ctrl_reg = AST2600_SCU_RESET_CONTROL1;
104
awc->reset_pulse = aspeed_2500_wdt_reset_pulse;
105
+ awc->wdt_reload = aspeed_wdt_reload_1mhz;
106
}
107
108
static const TypeInfo aspeed_2600_wdt_info = {
109
--
110
2.20.1
111
112
diff view generated by jsdifflib
Deleted patch
1
From: Cédric Le Goater <clg@kaod.org>
2
1
3
The current model only restores the Segment Register values but leaves
4
the previous CS mapping behind. Introduce a helper setting the
5
register value and mapping the region at the requested address. Use
6
this helper when a Segment register is set and at reset.
7
8
Signed-off-by: Cédric Le Goater <clg@kaod.org>
9
Reviewed-by: Joel Stanley <joel@jms.id.au>
10
Signed-off-by: Cédric Le Goater <clg@kaod.org>
11
Message-id: 20191119141211.25716-11-clg@kaod.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
hw/ssi/aspeed_smc.c | 32 +++++++++++++++++++++-----------
15
1 file changed, 21 insertions(+), 11 deletions(-)
16
17
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/ssi/aspeed_smc.c
20
+++ b/hw/ssi/aspeed_smc.c
21
@@ -XXX,XX +XXX,XX @@ static bool aspeed_smc_flash_overlap(const AspeedSMCState *s,
22
return false;
23
}
24
25
+static void aspeed_smc_flash_set_segment_region(AspeedSMCState *s, int cs,
26
+ uint64_t regval)
27
+{
28
+ AspeedSMCFlash *fl = &s->flashes[cs];
29
+ AspeedSegments seg;
30
+
31
+ s->ctrl->reg_to_segment(s, regval, &seg);
32
+
33
+ memory_region_transaction_begin();
34
+ memory_region_set_size(&fl->mmio, seg.size);
35
+ memory_region_set_address(&fl->mmio, seg.addr - s->ctrl->flash_window_base);
36
+ memory_region_set_enabled(&fl->mmio, true);
37
+ memory_region_transaction_commit();
38
+
39
+ s->regs[R_SEG_ADDR0 + cs] = regval;
40
+}
41
+
42
static void aspeed_smc_flash_set_segment(AspeedSMCState *s, int cs,
43
uint64_t new)
44
{
45
- AspeedSMCFlash *fl = &s->flashes[cs];
46
AspeedSegments seg;
47
48
s->ctrl->reg_to_segment(s, new, &seg);
49
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_flash_set_segment(AspeedSMCState *s, int cs,
50
aspeed_smc_flash_overlap(s, &seg, cs);
51
52
/* All should be fine now to move the region */
53
- memory_region_transaction_begin();
54
- memory_region_set_size(&fl->mmio, seg.size);
55
- memory_region_set_address(&fl->mmio, seg.addr - s->ctrl->flash_window_base);
56
- memory_region_set_enabled(&fl->mmio, true);
57
- memory_region_transaction_commit();
58
-
59
- s->regs[R_SEG_ADDR0 + cs] = new;
60
+ aspeed_smc_flash_set_segment_region(s, cs, new);
61
}
62
63
static uint64_t aspeed_smc_flash_default_read(void *opaque, hwaddr addr,
64
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_reset(DeviceState *d)
65
qemu_set_irq(s->cs_lines[i], true);
66
}
67
68
- /* setup default segment register values for all */
69
+ /* setup the default segment register values and regions for all */
70
for (i = 0; i < s->ctrl->max_slaves; ++i) {
71
- s->regs[R_SEG_ADDR0 + i] =
72
- s->ctrl->segment_to_reg(s, &s->ctrl->segments[i]);
73
+ aspeed_smc_flash_set_segment_region(s, i,
74
+ s->ctrl->segment_to_reg(s, &s->ctrl->segments[i]));
75
}
76
77
/* HW strapping flash type for the AST2600 controllers */
78
--
79
2.20.1
80
81
diff view generated by jsdifflib
Deleted patch
1
From: Cédric Le Goater <clg@kaod.org>
2
1
3
The segments can be disabled on the AST2600 (zero register value).
4
CS0 is open by default but not the other CS. This is closing the
5
access to the flash device in user mode and forbids scanning.
6
7
In the model, check the segment size and disable the associated region
8
when the value is zero.
9
10
Fixes: bcaa8ddd081c ("aspeed/smc: Add AST2600 support")
11
Signed-off-by: Cédric Le Goater <clg@kaod.org>
12
Reviewed-by: Joel Stanley <joel@jms.id.au>
13
Signed-off-by: Cédric Le Goater <clg@kaod.org>
14
Message-id: 20191119141211.25716-12-clg@kaod.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
hw/ssi/aspeed_smc.c | 16 +++++++++++-----
18
1 file changed, 11 insertions(+), 5 deletions(-)
19
20
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/ssi/aspeed_smc.c
23
+++ b/hw/ssi/aspeed_smc.c
24
@@ -XXX,XX +XXX,XX @@ static void aspeed_2600_smc_reg_to_segment(const AspeedSMCState *s,
25
uint32_t start_offset = (reg << 16) & AST2600_SEG_ADDR_MASK;
26
uint32_t end_offset = reg & AST2600_SEG_ADDR_MASK;
27
28
- seg->addr = s->ctrl->flash_window_base + start_offset;
29
- seg->size = end_offset + MiB - start_offset;
30
+ if (reg) {
31
+ seg->addr = s->ctrl->flash_window_base + start_offset;
32
+ seg->size = end_offset + MiB - start_offset;
33
+ } else {
34
+ seg->addr = s->ctrl->flash_window_base;
35
+ seg->size = 0;
36
+ }
37
}
38
39
static bool aspeed_smc_flash_overlap(const AspeedSMCState *s,
40
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_flash_set_segment_region(AspeedSMCState *s, int cs,
41
memory_region_transaction_begin();
42
memory_region_set_size(&fl->mmio, seg.size);
43
memory_region_set_address(&fl->mmio, seg.addr - s->ctrl->flash_window_base);
44
- memory_region_set_enabled(&fl->mmio, true);
45
+ memory_region_set_enabled(&fl->mmio, !!seg.size);
46
memory_region_transaction_commit();
47
48
s->regs[R_SEG_ADDR0 + cs] = regval;
49
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_flash_set_segment(AspeedSMCState *s, int cs,
50
}
51
52
/* Keep the segment in the overall flash window */
53
- if (seg.addr + seg.size <= s->ctrl->flash_window_base ||
54
- seg.addr > s->ctrl->flash_window_base + s->ctrl->flash_window_size) {
55
+ if (seg.size &&
56
+ (seg.addr + seg.size <= s->ctrl->flash_window_base ||
57
+ seg.addr > s->ctrl->flash_window_base + s->ctrl->flash_window_size)) {
58
qemu_log_mask(LOG_GUEST_ERROR, "%s: new segment for CS%d is invalid : "
59
"[ 0x%"HWADDR_PRIx" - 0x%"HWADDR_PRIx" ]\n",
60
s->ctrl->name, cs, seg.addr, seg.addr + seg.size);
61
--
62
2.20.1
63
64
diff view generated by jsdifflib
Deleted patch
1
From: Cédric Le Goater <clg@kaod.org>
2
1
3
Each CS has its own Read Timing Compensation Register on newer SoCs.
4
5
Signed-off-by: Cédric Le Goater <clg@kaod.org>
6
Reviewed-by: Joel Stanley <joel@jms.id.au>
7
Signed-off-by: Cédric Le Goater <clg@kaod.org>
8
Message-id: 20191119141211.25716-13-clg@kaod.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/hw/ssi/aspeed_smc.h | 1 +
12
hw/ssi/aspeed_smc.c | 17 ++++++++++++++---
13
2 files changed, 15 insertions(+), 3 deletions(-)
14
15
diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/ssi/aspeed_smc.h
18
+++ b/include/hw/ssi/aspeed_smc.h
19
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedSMCController {
20
uint8_t r_ce_ctrl;
21
uint8_t r_ctrl0;
22
uint8_t r_timings;
23
+ uint8_t nregs_timings;
24
uint8_t conf_enable_w0;
25
uint8_t max_slaves;
26
const AspeedSegments *segments;
27
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/ssi/aspeed_smc.c
30
+++ b/hw/ssi/aspeed_smc.c
31
@@ -XXX,XX +XXX,XX @@
32
/* Checksum Calculation Result */
33
#define R_DMA_CHECKSUM (0x90 / 4)
34
35
-/* Misc Control Register #2 */
36
+/* Read Timing Compensation Register */
37
#define R_TIMINGS (0x94 / 4)
38
39
/* SPI controller registers and bits (AST2400) */
40
@@ -XXX,XX +XXX,XX @@ static const AspeedSMCController controllers[] = {
41
.r_ce_ctrl = R_CE_CTRL,
42
.r_ctrl0 = R_CTRL0,
43
.r_timings = R_TIMINGS,
44
+ .nregs_timings = 1,
45
.conf_enable_w0 = CONF_ENABLE_W0,
46
.max_slaves = 5,
47
.segments = aspeed_segments_legacy,
48
@@ -XXX,XX +XXX,XX @@ static const AspeedSMCController controllers[] = {
49
.r_ce_ctrl = R_CE_CTRL,
50
.r_ctrl0 = R_CTRL0,
51
.r_timings = R_TIMINGS,
52
+ .nregs_timings = 1,
53
.conf_enable_w0 = CONF_ENABLE_W0,
54
.max_slaves = 5,
55
.segments = aspeed_segments_fmc,
56
@@ -XXX,XX +XXX,XX @@ static const AspeedSMCController controllers[] = {
57
.r_ce_ctrl = 0xff,
58
.r_ctrl0 = R_SPI_CTRL0,
59
.r_timings = R_SPI_TIMINGS,
60
+ .nregs_timings = 1,
61
.conf_enable_w0 = SPI_CONF_ENABLE_W0,
62
.max_slaves = 1,
63
.segments = aspeed_segments_spi,
64
@@ -XXX,XX +XXX,XX @@ static const AspeedSMCController controllers[] = {
65
.r_ce_ctrl = R_CE_CTRL,
66
.r_ctrl0 = R_CTRL0,
67
.r_timings = R_TIMINGS,
68
+ .nregs_timings = 1,
69
.conf_enable_w0 = CONF_ENABLE_W0,
70
.max_slaves = 3,
71
.segments = aspeed_segments_ast2500_fmc,
72
@@ -XXX,XX +XXX,XX @@ static const AspeedSMCController controllers[] = {
73
.r_ce_ctrl = R_CE_CTRL,
74
.r_ctrl0 = R_CTRL0,
75
.r_timings = R_TIMINGS,
76
+ .nregs_timings = 1,
77
.conf_enable_w0 = CONF_ENABLE_W0,
78
.max_slaves = 2,
79
.segments = aspeed_segments_ast2500_spi1,
80
@@ -XXX,XX +XXX,XX @@ static const AspeedSMCController controllers[] = {
81
.r_ce_ctrl = R_CE_CTRL,
82
.r_ctrl0 = R_CTRL0,
83
.r_timings = R_TIMINGS,
84
+ .nregs_timings = 1,
85
.conf_enable_w0 = CONF_ENABLE_W0,
86
.max_slaves = 2,
87
.segments = aspeed_segments_ast2500_spi2,
88
@@ -XXX,XX +XXX,XX @@ static const AspeedSMCController controllers[] = {
89
.r_ce_ctrl = R_CE_CTRL,
90
.r_ctrl0 = R_CTRL0,
91
.r_timings = R_TIMINGS,
92
+ .nregs_timings = 1,
93
.conf_enable_w0 = CONF_ENABLE_W0,
94
.max_slaves = 3,
95
.segments = aspeed_segments_ast2600_fmc,
96
@@ -XXX,XX +XXX,XX @@ static const AspeedSMCController controllers[] = {
97
.r_ce_ctrl = R_CE_CTRL,
98
.r_ctrl0 = R_CTRL0,
99
.r_timings = R_TIMINGS,
100
+ .nregs_timings = 2,
101
.conf_enable_w0 = CONF_ENABLE_W0,
102
.max_slaves = 2,
103
.segments = aspeed_segments_ast2600_spi1,
104
@@ -XXX,XX +XXX,XX @@ static const AspeedSMCController controllers[] = {
105
.r_ce_ctrl = R_CE_CTRL,
106
.r_ctrl0 = R_CTRL0,
107
.r_timings = R_TIMINGS,
108
+ .nregs_timings = 3,
109
.conf_enable_w0 = CONF_ENABLE_W0,
110
.max_slaves = 3,
111
.segments = aspeed_segments_ast2600_spi2,
112
@@ -XXX,XX +XXX,XX @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
113
addr >>= 2;
114
115
if (addr == s->r_conf ||
116
- addr == s->r_timings ||
117
+ (addr >= s->r_timings &&
118
+ addr < s->r_timings + s->ctrl->nregs_timings) ||
119
addr == s->r_ce_ctrl ||
120
addr == R_INTR_CTRL ||
121
addr == R_DUMMY_DATA ||
122
@@ -XXX,XX +XXX,XX @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
123
addr >>= 2;
124
125
if (addr == s->r_conf ||
126
- addr == s->r_timings ||
127
+ (addr >= s->r_timings &&
128
+ addr < s->r_timings + s->ctrl->nregs_timings) ||
129
addr == s->r_ce_ctrl) {
130
s->regs[addr] = value;
131
} else if (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->num_cs) {
132
--
133
2.20.1
134
135
diff view generated by jsdifflib
1
From: Cédric Le Goater <clg@kaod.org>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
The Aspeed MII model has a link pointing to its associated FTGMAC100
3
The ADC is part of NPCM7XX Module. Its behavior is controled by the
4
NIC in the machine.
4
ADC_CON register. It converts one of the eight analog inputs into a
5
digital input and stores it in the ADC_DATA register when enabled.
5
6
6
Change the "nic" property definition so that it explicitly sets the
7
Users can alter input value by using qom-set QMP command.
7
pointer. The property isn't optional : not being able to set the link
8
is a bug and QEMU should rather abort than exit in this case.
9
8
10
Signed-off-by: Cédric Le Goater <clg@kaod.org>
9
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
11
Reviewed-by: Greg Kurz <groug@kaod.org>
10
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
12
Reviewed-by: Joel Stanley <joel@jms.id.au>
11
Signed-off-by: Hao Wu <wuhaotsh@google.com>
13
Signed-off-by: Cédric Le Goater <clg@kaod.org>
12
Message-id: 20210108190945.949196-4-wuhaotsh@google.com
14
Message-id: 20191119141211.25716-18-clg@kaod.org
13
[PMM: Added missing hw/adc/trace.h file]
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
16
---
17
hw/arm/aspeed_ast2600.c | 5 ++---
17
docs/system/arm/nuvoton.rst | 2 +-
18
hw/net/ftgmac100.c | 19 +++++++++----------
18
meson.build | 1 +
19
2 files changed, 11 insertions(+), 13 deletions(-)
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
20
34
21
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
35
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
22
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/aspeed_ast2600.c
37
--- a/docs/system/arm/nuvoton.rst
24
+++ b/hw/arm/aspeed_ast2600.c
38
+++ b/docs/system/arm/nuvoton.rst
25
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2600_init(Object *obj)
39
@@ -XXX,XX +XXX,XX @@ Supported devices
26
40
* Random Number Generator (RNG)
27
sysbus_init_child_obj(obj, "mii[*]", &s->mii[i], sizeof(s->mii[i]),
41
* USB host (USBH)
28
TYPE_ASPEED_MII);
42
* GPIO controller
29
- object_property_add_const_link(OBJECT(&s->mii[i]), "nic",
43
+ * Analog to Digital Converter (ADC)
30
- OBJECT(&s->ftgmac100[i]),
44
31
- &error_abort);
45
Missing devices
32
}
46
---------------
33
47
@@ -XXX,XX +XXX,XX @@ Missing devices
34
sysbus_init_child_obj(obj, "xdma", OBJECT(&s->xdma), sizeof(s->xdma),
48
* USB device (USBD)
35
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
49
* SMBus controller (SMBF)
36
sysbus_connect_irq(SYS_BUS_DEVICE(&s->ftgmac100[i]), 0,
50
* Peripheral SPI controller (PSPI)
37
aspeed_soc_get_irq(s, ASPEED_ETH1 + i));
51
- * Analog to Digital Converter (ADC)
38
52
* SD/MMC host
39
+ object_property_set_link(OBJECT(&s->mii[i]), OBJECT(&s->ftgmac100[i]),
53
* PECI interface
40
+ "nic", &error_abort);
54
* Pulse Width Modulation (PWM)
41
object_property_set_bool(OBJECT(&s->mii[i]), true, "realized",
55
diff --git a/meson.build b/meson.build
42
&err);
43
if (err) {
44
diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c
45
index XXXXXXX..XXXXXXX 100644
56
index XXXXXXX..XXXXXXX 100644
46
--- a/hw/net/ftgmac100.c
57
--- a/meson.build
47
+++ b/hw/net/ftgmac100.c
58
+++ b/meson.build
48
@@ -XXX,XX +XXX,XX @@ static void aspeed_mii_realize(DeviceState *dev, Error **errp)
59
@@ -XXX,XX +XXX,XX @@ if have_system
49
{
60
'chardev',
50
AspeedMiiState *s = ASPEED_MII(dev);
61
'hw/9pfs',
51
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
62
'hw/acpi',
52
- Object *obj;
63
+ 'hw/adc',
53
- Error *local_err = NULL;
64
'hw/alpha',
54
65
'hw/arm',
55
- obj = object_property_get_link(OBJECT(dev), "nic", &local_err);
66
'hw/audio',
56
- if (!obj) {
67
diff --git a/hw/adc/trace.h b/hw/adc/trace.h
57
- error_propagate(errp, local_err);
68
new file mode 100644
58
- error_prepend(errp, "required link 'nic' not found: ");
69
index XXXXXXX..XXXXXXX
59
- return;
70
--- /dev/null
60
- }
71
+++ b/hw/adc/trace.h
61
-
72
@@ -0,0 +1 @@
62
- s->nic = FTGMAC100(obj);
73
+#include "trace/trace-hw_adc.h"
63
+ assert(s->nic);
74
diff --git a/include/hw/adc/npcm7xx_adc.h b/include/hw/adc/npcm7xx_adc.h
64
75
new file mode 100644
65
memory_region_init_io(&s->iomem, OBJECT(dev), &aspeed_mii_ops, s,
76
index XXXXXXX..XXXXXXX
66
TYPE_ASPEED_MII, 0x8);
77
--- /dev/null
67
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_aspeed_mii = {
78
+++ b/include/hw/adc/npcm7xx_adc.h
68
VMSTATE_END_OF_LIST()
79
@@ -XXX,XX +XXX,XX @@
69
}
80
+/*
70
};
81
+ * Nuvoton NPCM7xx ADC Module
71
+
82
+ *
72
+static Property aspeed_mii_properties[] = {
83
+ * Copyright 2020 Google LLC
73
+ DEFINE_PROP_LINK("nic", AspeedMiiState, nic, TYPE_FTGMAC100,
84
+ *
74
+ FTGMAC100State *),
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"
195
+#include "hw/registerfields.h"
196
+#include "migration/vmstate.h"
197
+#include "qemu/log.h"
198
+#include "qemu/module.h"
199
+#include "qemu/timer.h"
200
+#include "qemu/units.h"
201
+#include "trace.h"
202
+
203
+REG32(NPCM7XX_ADC_CON, 0x0)
204
+REG32(NPCM7XX_ADC_DATA, 0x4)
205
+
206
+/* Register field definitions. */
207
+#define NPCM7XX_ADC_CON_MUX(rv) extract32(rv, 24, 4)
208
+#define NPCM7XX_ADC_CON_INT_EN BIT(21)
209
+#define NPCM7XX_ADC_CON_REFSEL BIT(19)
210
+#define NPCM7XX_ADC_CON_INT BIT(18)
211
+#define NPCM7XX_ADC_CON_EN BIT(17)
212
+#define NPCM7XX_ADC_CON_RST BIT(16)
213
+#define NPCM7XX_ADC_CON_CONV BIT(14)
214
+#define NPCM7XX_ADC_CON_DIV(rv) extract32(rv, 1, 8)
215
+
216
+#define NPCM7XX_ADC_MAX_RESULT 1023
217
+#define NPCM7XX_ADC_DEFAULT_IREF 2000000
218
+#define NPCM7XX_ADC_CONV_CYCLES 20
219
+#define NPCM7XX_ADC_RESET_CYCLES 10
220
+#define NPCM7XX_ADC_R0_INPUT 500000
221
+#define NPCM7XX_ADC_R1_INPUT 1500000
222
+
223
+static void npcm7xx_adc_reset(NPCM7xxADCState *s)
224
+{
225
+ timer_del(&s->conv_timer);
226
+ s->con = 0x000c0001;
227
+ s->data = 0x00000000;
228
+}
229
+
230
+static uint32_t npcm7xx_adc_convert(uint32_t input, uint32_t ref)
231
+{
232
+ uint32_t result;
233
+
234
+ result = input * (NPCM7XX_ADC_MAX_RESULT + 1) / ref;
235
+ if (result > NPCM7XX_ADC_MAX_RESULT) {
236
+ result = NPCM7XX_ADC_MAX_RESULT;
237
+ }
238
+
239
+ return result;
240
+}
241
+
242
+static uint32_t npcm7xx_adc_prescaler(NPCM7xxADCState *s)
243
+{
244
+ return 2 * (NPCM7XX_ADC_CON_DIV(s->con) + 1);
245
+}
246
+
247
+static void npcm7xx_adc_start_timer(Clock *clk, QEMUTimer *timer,
248
+ uint32_t cycles, uint32_t prescaler)
249
+{
250
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
251
+ int64_t ticks = cycles;
252
+ int64_t ns;
253
+
254
+ ticks *= prescaler;
255
+ ns = clock_ticks_to_ns(clk, ticks);
256
+ ns += now;
257
+ timer_mod(timer, ns);
258
+}
259
+
260
+static void npcm7xx_adc_start_convert(NPCM7xxADCState *s)
261
+{
262
+ uint32_t prescaler = npcm7xx_adc_prescaler(s);
263
+
264
+ npcm7xx_adc_start_timer(s->clock, &s->conv_timer, NPCM7XX_ADC_CONV_CYCLES,
265
+ prescaler);
266
+}
267
+
268
+static void npcm7xx_adc_convert_done(void *opaque)
269
+{
270
+ NPCM7xxADCState *s = opaque;
271
+ uint32_t input = NPCM7XX_ADC_CON_MUX(s->con);
272
+ uint32_t ref = (s->con & NPCM7XX_ADC_CON_REFSEL)
273
+ ? s->iref : s->vref;
274
+
275
+ if (input >= NPCM7XX_ADC_NUM_INPUTS) {
276
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid input: %u\n",
277
+ __func__, input);
278
+ return;
279
+ }
280
+ s->data = npcm7xx_adc_convert(s->adci[input], ref);
281
+ if (s->con & NPCM7XX_ADC_CON_INT_EN) {
282
+ s->con |= NPCM7XX_ADC_CON_INT;
283
+ qemu_irq_raise(s->irq);
284
+ }
285
+ s->con &= ~NPCM7XX_ADC_CON_CONV;
286
+}
287
+
288
+static void npcm7xx_adc_calibrate(NPCM7xxADCState *adc)
289
+{
290
+ adc->calibration_r_values[0] = npcm7xx_adc_convert(NPCM7XX_ADC_R0_INPUT,
291
+ adc->iref);
292
+ adc->calibration_r_values[1] = npcm7xx_adc_convert(NPCM7XX_ADC_R1_INPUT,
293
+ adc->iref);
294
+}
295
+
296
+static void npcm7xx_adc_write_con(NPCM7xxADCState *s, uint32_t new_con)
297
+{
298
+ uint32_t old_con = s->con;
299
+
300
+ /* Write ADC_INT to 1 to clear it */
301
+ if (new_con & NPCM7XX_ADC_CON_INT) {
302
+ new_con &= ~NPCM7XX_ADC_CON_INT;
303
+ qemu_irq_lower(s->irq);
304
+ } else if (old_con & NPCM7XX_ADC_CON_INT) {
305
+ new_con |= NPCM7XX_ADC_CON_INT;
306
+ }
307
+
308
+ s->con = new_con;
309
+
310
+ if (s->con & NPCM7XX_ADC_CON_RST) {
311
+ npcm7xx_adc_reset(s);
312
+ return;
313
+ }
314
+
315
+ if ((s->con & NPCM7XX_ADC_CON_EN)) {
316
+ if (s->con & NPCM7XX_ADC_CON_CONV) {
317
+ if (!(old_con & NPCM7XX_ADC_CON_CONV)) {
318
+ npcm7xx_adc_start_convert(s);
319
+ }
320
+ } else {
321
+ timer_del(&s->conv_timer);
322
+ }
323
+ }
324
+}
325
+
326
+static uint64_t npcm7xx_adc_read(void *opaque, hwaddr offset, unsigned size)
327
+{
328
+ uint64_t value = 0;
329
+ NPCM7xxADCState *s = opaque;
330
+
331
+ switch (offset) {
332
+ case A_NPCM7XX_ADC_CON:
333
+ value = s->con;
334
+ break;
335
+
336
+ case A_NPCM7XX_ADC_DATA:
337
+ value = s->data;
338
+ break;
339
+
340
+ default:
341
+ qemu_log_mask(LOG_GUEST_ERROR,
342
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
343
+ __func__, offset);
344
+ break;
345
+ }
346
+
347
+ trace_npcm7xx_adc_read(DEVICE(s)->canonical_path, offset, value);
348
+ return value;
349
+}
350
+
351
+static void npcm7xx_adc_write(void *opaque, hwaddr offset, uint64_t v,
352
+ unsigned size)
353
+{
354
+ NPCM7xxADCState *s = opaque;
355
+
356
+ trace_npcm7xx_adc_write(DEVICE(s)->canonical_path, offset, v);
357
+ switch (offset) {
358
+ case A_NPCM7XX_ADC_CON:
359
+ npcm7xx_adc_write_con(s, v);
360
+ break;
361
+
362
+ case A_NPCM7XX_ADC_DATA:
363
+ qemu_log_mask(LOG_GUEST_ERROR,
364
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
365
+ __func__, offset);
366
+ break;
367
+
368
+ default:
369
+ qemu_log_mask(LOG_GUEST_ERROR,
370
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
371
+ __func__, offset);
372
+ break;
373
+ }
374
+
375
+}
376
+
377
+static const struct MemoryRegionOps npcm7xx_adc_ops = {
378
+ .read = npcm7xx_adc_read,
379
+ .write = npcm7xx_adc_write,
380
+ .endianness = DEVICE_LITTLE_ENDIAN,
381
+ .valid = {
382
+ .min_access_size = 4,
383
+ .max_access_size = 4,
384
+ .unaligned = false,
385
+ },
386
+};
387
+
388
+static void npcm7xx_adc_enter_reset(Object *obj, ResetType type)
389
+{
390
+ NPCM7xxADCState *s = NPCM7XX_ADC(obj);
391
+
392
+ npcm7xx_adc_reset(s);
393
+}
394
+
395
+static void npcm7xx_adc_hold_reset(Object *obj)
396
+{
397
+ NPCM7xxADCState *s = NPCM7XX_ADC(obj);
398
+
399
+ qemu_irq_lower(s->irq);
400
+}
401
+
402
+static void npcm7xx_adc_init(Object *obj)
403
+{
404
+ NPCM7xxADCState *s = NPCM7XX_ADC(obj);
405
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
406
+ int i;
407
+
408
+ sysbus_init_irq(sbd, &s->irq);
409
+
410
+ timer_init_ns(&s->conv_timer, QEMU_CLOCK_VIRTUAL,
411
+ npcm7xx_adc_convert_done, s);
412
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_adc_ops, s,
413
+ TYPE_NPCM7XX_ADC, 4 * KiB);
414
+ sysbus_init_mmio(sbd, &s->iomem);
415
+ s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL);
416
+
417
+ for (i = 0; i < NPCM7XX_ADC_NUM_INPUTS; ++i) {
418
+ object_property_add_uint32_ptr(obj, "adci[*]",
419
+ &s->adci[i], OBJ_PROP_FLAG_WRITE);
420
+ }
421
+ object_property_add_uint32_ptr(obj, "vref",
422
+ &s->vref, OBJ_PROP_FLAG_WRITE);
423
+ npcm7xx_adc_calibrate(s);
424
+}
425
+
426
+static const VMStateDescription vmstate_npcm7xx_adc = {
427
+ .name = "npcm7xx-adc",
428
+ .version_id = 0,
429
+ .minimum_version_id = 0,
430
+ .fields = (VMStateField[]) {
431
+ VMSTATE_TIMER(conv_timer, NPCM7xxADCState),
432
+ VMSTATE_UINT32(con, NPCM7xxADCState),
433
+ VMSTATE_UINT32(data, NPCM7xxADCState),
434
+ VMSTATE_CLOCK(clock, NPCM7xxADCState),
435
+ VMSTATE_UINT32_ARRAY(adci, NPCM7xxADCState, NPCM7XX_ADC_NUM_INPUTS),
436
+ VMSTATE_UINT32(vref, NPCM7xxADCState),
437
+ VMSTATE_UINT32(iref, NPCM7xxADCState),
438
+ VMSTATE_UINT16_ARRAY(calibration_r_values, NPCM7xxADCState,
439
+ NPCM7XX_ADC_NUM_CALIB),
440
+ VMSTATE_END_OF_LIST(),
441
+ },
442
+};
443
+
444
+static Property npcm7xx_timer_properties[] = {
445
+ DEFINE_PROP_UINT32("iref", NPCM7xxADCState, iref, NPCM7XX_ADC_DEFAULT_IREF),
75
+ DEFINE_PROP_END_OF_LIST(),
446
+ DEFINE_PROP_END_OF_LIST(),
76
+};
447
+};
77
+
448
+
78
static void aspeed_mii_class_init(ObjectClass *klass, void *data)
449
+static void npcm7xx_adc_class_init(ObjectClass *klass, void *data)
450
+{
451
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
452
+ DeviceClass *dc = DEVICE_CLASS(klass);
453
+
454
+ dc->desc = "NPCM7xx ADC Module";
455
+ dc->vmsd = &vmstate_npcm7xx_adc;
456
+ rc->phases.enter = npcm7xx_adc_enter_reset;
457
+ rc->phases.hold = npcm7xx_adc_hold_reset;
458
+
459
+ device_class_set_props(dc, npcm7xx_timer_properties);
460
+}
461
+
462
+static const TypeInfo npcm7xx_adc_info = {
463
+ .name = TYPE_NPCM7XX_ADC,
464
+ .parent = TYPE_SYS_BUS_DEVICE,
465
+ .instance_size = sizeof(NPCM7xxADCState),
466
+ .class_init = npcm7xx_adc_class_init,
467
+ .instance_init = npcm7xx_adc_init,
468
+};
469
+
470
+static void npcm7xx_adc_register_types(void)
471
+{
472
+ type_register_static(&npcm7xx_adc_info);
473
+}
474
+
475
+type_init(npcm7xx_adc_register_types);
476
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
477
index XXXXXXX..XXXXXXX 100644
478
--- a/hw/arm/npcm7xx.c
479
+++ b/hw/arm/npcm7xx.c
480
@@ -XXX,XX +XXX,XX @@
481
#define NPCM7XX_EHCI_BA (0xf0806000)
482
#define NPCM7XX_OHCI_BA (0xf0807000)
483
484
+/* ADC Module */
485
+#define NPCM7XX_ADC_BA (0xf000c000)
486
+
487
/* Internal AHB SRAM */
488
#define NPCM7XX_RAM3_BA (0xc0008000)
489
#define NPCM7XX_RAM3_SZ (4 * KiB)
490
@@ -XXX,XX +XXX,XX @@
491
#define NPCM7XX_ROM_BA (0xffff0000)
492
#define NPCM7XX_ROM_SZ (64 * KiB)
493
494
+
495
/* Clock configuration values to be fixed up when bypassing bootloader */
496
497
/* Run PLL1 at 1600 MHz */
498
@@ -XXX,XX +XXX,XX @@
499
* interrupts.
500
*/
501
enum NPCM7xxInterrupt {
502
+ NPCM7XX_ADC_IRQ = 0,
503
NPCM7XX_UART0_IRQ = 2,
504
NPCM7XX_UART1_IRQ,
505
NPCM7XX_UART2_IRQ,
506
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init_fuses(NPCM7xxState *s)
507
sizeof(value));
508
}
509
510
+static void npcm7xx_write_adc_calibration(NPCM7xxState *s)
511
+{
512
+ /* Both ADC and the fuse array must have realized. */
513
+ QEMU_BUILD_BUG_ON(sizeof(s->adc.calibration_r_values) != 4);
514
+ npcm7xx_otp_array_write(&s->fuse_array, s->adc.calibration_r_values,
515
+ NPCM7XX_FUSE_ADC_CALIB, sizeof(s->adc.calibration_r_values));
516
+}
517
+
518
static qemu_irq npcm7xx_irq(NPCM7xxState *s, int n)
79
{
519
{
80
DeviceClass *dc = DEVICE_CLASS(klass);
520
return qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
81
@@ -XXX,XX +XXX,XX @@ static void aspeed_mii_class_init(ObjectClass *klass, void *data)
521
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
82
dc->reset = aspeed_mii_reset;
522
TYPE_NPCM7XX_FUSE_ARRAY);
83
dc->realize = aspeed_mii_realize;
523
object_initialize_child(obj, "mc", &s->mc, TYPE_NPCM7XX_MC);
84
dc->desc = "Aspeed MII controller";
524
object_initialize_child(obj, "rng", &s->rng, TYPE_NPCM7XX_RNG);
85
+ dc->props = aspeed_mii_properties;
525
+ object_initialize_child(obj, "adc", &s->adc, TYPE_NPCM7XX_ADC);
86
}
526
87
527
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
88
static const TypeInfo aspeed_mii_info = {
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']
89
--
968
--
90
2.20.1
969
2.20.1
91
970
92
971
diff view generated by jsdifflib
1
From: Cédric Le Goater <clg@kaod.org>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
AspeedBoardConfig is a redundant way to define class attributes and it
3
The PWM module is part of NPCM7XX module. Each NPCM7XX module has two
4
complexifies the machine definition and initialization.
4
identical PWM modules. Each module contains 4 PWM entries. Each PWM has
5
two outputs: frequency and duty_cycle. Both are computed using inputs
6
from software side.
5
7
6
Signed-off-by: Cédric Le Goater <clg@kaod.org>
8
This module does not model detail pulse signals since it is expensive.
7
Reviewed-by: Joel Stanley <joel@jms.id.au>
9
It also does not model interrupts and watchdogs that are dependant on
8
Signed-off-by: Cédric Le Goater <clg@kaod.org>
10
the detail models. The interfaces for these are left in the module so
9
Message-id: 20191119141211.25716-14-clg@kaod.org
11
that anyone in need for these functionalities can implement on their
12
own.
13
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>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
22
---
12
include/hw/arm/aspeed.h | 24 ++--
23
docs/system/arm/nuvoton.rst | 2 +-
13
hw/arm/aspeed.c | 243 ++++++++++++++++++++++------------------
24
include/hw/arm/npcm7xx.h | 2 +
14
2 files changed, 143 insertions(+), 124 deletions(-)
25
include/hw/misc/npcm7xx_pwm.h | 105 +++++++
26
hw/arm/npcm7xx.c | 26 +-
27
hw/misc/npcm7xx_pwm.c | 550 ++++++++++++++++++++++++++++++++++
28
hw/misc/meson.build | 1 +
29
hw/misc/trace-events | 6 +
30
7 files changed, 689 insertions(+), 3 deletions(-)
31
create mode 100644 include/hw/misc/npcm7xx_pwm.h
32
create mode 100644 hw/misc/npcm7xx_pwm.c
15
33
16
diff --git a/include/hw/arm/aspeed.h b/include/hw/arm/aspeed.h
34
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
17
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/aspeed.h
36
--- a/docs/system/arm/nuvoton.rst
19
+++ b/include/hw/arm/aspeed.h
37
+++ b/docs/system/arm/nuvoton.rst
38
@@ -XXX,XX +XXX,XX @@ Supported devices
39
* USB host (USBH)
40
* GPIO controller
41
* Analog to Digital Converter (ADC)
42
+ * Pulse Width Modulation (PWM)
43
44
Missing devices
45
---------------
46
@@ -XXX,XX +XXX,XX @@ Missing devices
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
20
@@ -XXX,XX +XXX,XX @@
58
@@ -XXX,XX +XXX,XX @@
21
59
#include "hw/mem/npcm7xx_mc.h"
22
typedef struct AspeedBoardState AspeedBoardState;
60
#include "hw/misc/npcm7xx_clk.h"
23
61
#include "hw/misc/npcm7xx_gcr.h"
24
-typedef struct AspeedBoardConfig {
62
+#include "hw/misc/npcm7xx_pwm.h"
25
- const char *name;
63
#include "hw/misc/npcm7xx_rng.h"
26
- const char *desc;
64
#include "hw/nvram/npcm7xx_otp.h"
27
- const char *soc_name;
65
#include "hw/timer/npcm7xx_timer.h"
28
- uint32_t hw_strap1;
66
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
29
- uint32_t hw_strap2;
67
NPCM7xxCLKState clk;
30
- const char *fmc_model;
68
NPCM7xxTimerCtrlState tim[3];
31
- const char *spi_model;
69
NPCM7xxADCState adc;
32
- uint32_t num_cs;
70
+ NPCM7xxPWMState pwm[2];
33
- void (*i2c_init)(AspeedBoardState *bmc);
71
NPCM7xxOTPState key_storage;
34
- uint32_t ram;
72
NPCM7xxOTPState fuse_array;
35
-} AspeedBoardConfig;
73
NPCM7xxMCState mc;
36
-
74
diff --git a/include/hw/misc/npcm7xx_pwm.h b/include/hw/misc/npcm7xx_pwm.h
37
#define TYPE_ASPEED_MACHINE MACHINE_TYPE_NAME("aspeed")
75
new file mode 100644
38
#define ASPEED_MACHINE(obj) \
76
index XXXXXXX..XXXXXXX
39
OBJECT_CHECK(AspeedMachine, (obj), TYPE_ASPEED_MACHINE)
77
--- /dev/null
40
@@ -XXX,XX +XXX,XX @@ typedef struct AspeedMachine {
78
+++ b/include/hw/misc/npcm7xx_pwm.h
41
79
@@ -XXX,XX +XXX,XX @@
42
typedef struct AspeedMachineClass {
80
+/*
43
MachineClass parent_obj;
81
+ * Nuvoton NPCM7xx PWM Module
44
- const AspeedBoardConfig *board;
82
+ *
45
+
83
+ * Copyright 2020 Google LLC
46
+ const char *name;
84
+ *
47
+ const char *desc;
85
+ * This program is free software; you can redistribute it and/or modify it
48
+ const char *soc_name;
86
+ * under the terms of the GNU General Public License as published by the
49
+ uint32_t hw_strap1;
87
+ * Free Software Foundation; either version 2 of the License, or
50
+ uint32_t hw_strap2;
88
+ * (at your option) any later version.
51
+ const char *fmc_model;
89
+ *
52
+ const char *spi_model;
90
+ * This program is distributed in the hope that it will be useful, but WITHOUT
53
+ uint32_t num_cs;
91
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
54
+ void (*i2c_init)(AspeedBoardState *bmc);
92
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
55
} AspeedMachineClass;
93
+ * for more details.
56
94
+ */
57
95
+#ifndef NPCM7XX_PWM_H
58
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
96
+#define NPCM7XX_PWM_H
97
+
98
+#include "hw/clock.h"
99
+#include "hw/sysbus.h"
100
+#include "hw/irq.h"
101
+
102
+/* Each PWM module holds 4 PWM channels. */
103
+#define NPCM7XX_PWM_PER_MODULE 4
104
+
105
+/*
106
+ * Number of registers in one pwm module. Don't change this without increasing
107
+ * the version_id in vmstate.
108
+ */
109
+#define NPCM7XX_PWM_NR_REGS (0x54 / sizeof(uint32_t))
110
+
111
+/*
112
+ * The maximum duty values. Each duty unit represents 1/NPCM7XX_PWM_MAX_DUTY
113
+ * cycles. For example, if NPCM7XX_PWM_MAX_DUTY=1,000,000 and a PWM has a duty
114
+ * value of 100,000 the duty cycle for that PWM is 10%.
115
+ */
116
+#define NPCM7XX_PWM_MAX_DUTY 1000000
117
+
118
+typedef struct NPCM7xxPWMState NPCM7xxPWMState;
119
+
120
+/**
121
+ * struct NPCM7xxPWM - The state of a single PWM channel.
122
+ * @module: The PWM module that contains this channel.
123
+ * @irq: GIC interrupt line to fire on expiration if enabled.
124
+ * @running: Whether this PWM channel is generating output.
125
+ * @inverted: Whether this PWM channel is inverted.
126
+ * @index: The index of this PWM channel.
127
+ * @cnr: The counter register.
128
+ * @cmr: The comparator register.
129
+ * @pdr: The data register.
130
+ * @pwdr: The watchdog register.
131
+ * @freq: The frequency of this PWM channel.
132
+ * @duty: The duty cycle of this PWM channel. One unit represents
133
+ * 1/NPCM7XX_MAX_DUTY cycles.
134
+ */
135
+typedef struct NPCM7xxPWM {
136
+ NPCM7xxPWMState *module;
137
+
138
+ qemu_irq irq;
139
+
140
+ bool running;
141
+ bool inverted;
142
+
143
+ uint8_t index;
144
+ uint32_t cnr;
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
59
index XXXXXXX..XXXXXXX 100644
186
index XXXXXXX..XXXXXXX 100644
60
--- a/hw/arm/aspeed.c
187
--- a/hw/arm/npcm7xx.c
61
+++ b/hw/arm/aspeed.c
188
+++ b/hw/arm/npcm7xx.c
62
@@ -XXX,XX +XXX,XX @@ static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
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);
63
}
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
+ }
64
}
219
}
65
220
66
-static void aspeed_board_init(MachineState *machine,
221
static void npcm7xx_realize(DeviceState *dev, Error **errp)
67
- const AspeedBoardConfig *cfg)
222
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
68
+static void aspeed_machine_init(MachineState *machine)
223
sysbus_connect_irq(SYS_BUS_DEVICE(&s->ohci), 0,
69
{
224
npcm7xx_irq(s, NPCM7XX_OHCI_IRQ));
70
AspeedBoardState *bmc;
225
71
+ AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(machine);
226
+ /* PWM Modules. Cannot fail. */
72
AspeedSoCClass *sc;
227
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_pwm_addr) != ARRAY_SIZE(s->pwm));
73
DriveInfo *drive0 = drive_get(IF_MTD, 0, 0);
228
+ for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
74
ram_addr_t max_ram_size;
229
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->pwm[i]);
75
@@ -XXX,XX +XXX,XX @@ static void aspeed_board_init(MachineState *machine,
230
+
76
UINT32_MAX);
231
+ qdev_connect_clock_in(DEVICE(&s->pwm[i]), "clock", qdev_get_clock_out(
77
232
+ DEVICE(&s->clk), "apb3-clock"));
78
object_initialize_child(OBJECT(machine), "soc", &bmc->soc,
233
+ sysbus_realize(sbd, &error_abort);
79
- (sizeof(bmc->soc)), cfg->soc_name, &error_abort,
234
+ sysbus_mmio_map(sbd, 0, npcm7xx_pwm_addr[i]);
80
+ (sizeof(bmc->soc)), amc->soc_name, &error_abort,
235
+ sysbus_connect_irq(sbd, i, npcm7xx_irq(s, NPCM7XX_PWM0_IRQ + i));
81
NULL);
236
+ }
82
237
+
83
sc = ASPEED_SOC_GET_CLASS(&bmc->soc);
238
/*
84
239
* Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
85
object_property_set_uint(OBJECT(&bmc->soc), ram_size, "ram-size",
240
* specified, but this is a programming error.
86
&error_abort);
241
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
87
- object_property_set_int(OBJECT(&bmc->soc), cfg->hw_strap1, "hw-strap1",
242
create_unimplemented_device("npcm7xx.peci", 0xf0100000, 4 * KiB);
88
+ object_property_set_int(OBJECT(&bmc->soc), amc->hw_strap1, "hw-strap1",
243
create_unimplemented_device("npcm7xx.siox[1]", 0xf0101000, 4 * KiB);
89
&error_abort);
244
create_unimplemented_device("npcm7xx.siox[2]", 0xf0102000, 4 * KiB);
90
- object_property_set_int(OBJECT(&bmc->soc), cfg->hw_strap2, "hw-strap2",
245
- create_unimplemented_device("npcm7xx.pwm[0]", 0xf0103000, 4 * KiB);
91
+ object_property_set_int(OBJECT(&bmc->soc), amc->hw_strap2, "hw-strap2",
246
- create_unimplemented_device("npcm7xx.pwm[1]", 0xf0104000, 4 * KiB);
92
&error_abort);
247
create_unimplemented_device("npcm7xx.mft[0]", 0xf0180000, 4 * KiB);
93
- object_property_set_int(OBJECT(&bmc->soc), cfg->num_cs, "num-cs",
248
create_unimplemented_device("npcm7xx.mft[1]", 0xf0181000, 4 * KiB);
94
+ object_property_set_int(OBJECT(&bmc->soc), amc->num_cs, "num-cs",
249
create_unimplemented_device("npcm7xx.mft[2]", 0xf0182000, 4 * KiB);
95
&error_abort);
250
diff --git a/hw/misc/npcm7xx_pwm.c b/hw/misc/npcm7xx_pwm.c
96
object_property_set_int(OBJECT(&bmc->soc), machine->smp.cpus, "num-cpus",
251
new file mode 100644
97
&error_abort);
252
index XXXXXXX..XXXXXXX
98
@@ -XXX,XX +XXX,XX @@ static void aspeed_board_init(MachineState *machine,
253
--- /dev/null
99
"max_ram", max_ram_size - ram_size);
254
+++ b/hw/misc/npcm7xx_pwm.c
100
memory_region_add_subregion(&bmc->ram_container, ram_size, &bmc->max_ram);
255
@@ -XXX,XX +XXX,XX @@
101
256
+/*
102
- aspeed_board_init_flashes(&bmc->soc.fmc, cfg->fmc_model, &error_abort);
257
+ * Nuvoton NPCM7xx PWM Module
103
- aspeed_board_init_flashes(&bmc->soc.spi[0], cfg->spi_model, &error_abort);
258
+ *
104
+ aspeed_board_init_flashes(&bmc->soc.fmc, amc->fmc_model, &error_abort);
259
+ * Copyright 2020 Google LLC
105
+ aspeed_board_init_flashes(&bmc->soc.spi[0], amc->spi_model, &error_abort);
260
+ *
106
261
+ * This program is free software; you can redistribute it and/or modify it
107
/* Install first FMC flash content as a boot rom. */
262
+ * under the terms of the GNU General Public License as published by the
108
if (drive0) {
263
+ * Free Software Foundation; either version 2 of the License, or
109
@@ -XXX,XX +XXX,XX @@ static void aspeed_board_init(MachineState *machine,
264
+ * (at your option) any later version.
110
aspeed_board_binfo.loader_start = sc->memmap[ASPEED_SDRAM];
265
+ *
111
aspeed_board_binfo.nb_cpus = bmc->soc.num_cpus;
266
+ * This program is distributed in the hope that it will be useful, but WITHOUT
112
267
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
113
- if (cfg->i2c_init) {
268
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
114
- cfg->i2c_init(bmc);
269
+ * for more details.
115
+ if (amc->i2c_init) {
270
+ */
116
+ amc->i2c_init(bmc);
271
+
117
}
272
+#include "qemu/osdep.h"
118
273
+#include "hw/irq.h"
119
for (i = 0; i < ARRAY_SIZE(bmc->soc.sdhci.slots); i++) {
274
+#include "hw/qdev-clock.h"
120
@@ -XXX,XX +XXX,XX @@ static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
275
+#include "hw/qdev-properties.h"
121
0x60);
276
+#include "hw/misc/npcm7xx_pwm.h"
122
}
277
+#include "hw/registerfields.h"
123
278
+#include "migration/vmstate.h"
124
-static void aspeed_machine_init(MachineState *machine)
279
+#include "qemu/bitops.h"
125
-{
280
+#include "qemu/error-report.h"
126
- AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(machine);
281
+#include "qemu/log.h"
127
-
282
+#include "qemu/module.h"
128
- aspeed_board_init(machine, amc->board);
283
+#include "qemu/units.h"
129
-}
284
+#include "trace.h"
130
-
285
+
131
static void aspeed_machine_class_init(ObjectClass *oc, void *data)
286
+REG32(NPCM7XX_PWM_PPR, 0x00);
132
{
287
+REG32(NPCM7XX_PWM_CSR, 0x04);
133
MachineClass *mc = MACHINE_CLASS(oc);
288
+REG32(NPCM7XX_PWM_PCR, 0x08);
134
- AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
289
+REG32(NPCM7XX_PWM_CNR0, 0x0c);
135
- const AspeedBoardConfig *board = data;
290
+REG32(NPCM7XX_PWM_CMR0, 0x10);
136
291
+REG32(NPCM7XX_PWM_PDR0, 0x14);
137
- mc->desc = board->desc;
292
+REG32(NPCM7XX_PWM_CNR1, 0x18);
138
mc->init = aspeed_machine_init;
293
+REG32(NPCM7XX_PWM_CMR1, 0x1c);
139
mc->max_cpus = ASPEED_CPUS_NUM;
294
+REG32(NPCM7XX_PWM_PDR1, 0x20);
140
mc->no_floppy = 1;
295
+REG32(NPCM7XX_PWM_CNR2, 0x24);
141
mc->no_cdrom = 1;
296
+REG32(NPCM7XX_PWM_CMR2, 0x28);
142
mc->no_parallel = 1;
297
+REG32(NPCM7XX_PWM_PDR2, 0x2c);
143
- if (board->ram) {
298
+REG32(NPCM7XX_PWM_CNR3, 0x30);
144
- mc->default_ram_size = board->ram;
299
+REG32(NPCM7XX_PWM_CMR3, 0x34);
145
- }
300
+REG32(NPCM7XX_PWM_PDR3, 0x38);
146
- amc->board = board;
301
+REG32(NPCM7XX_PWM_PIER, 0x3c);
147
}
302
+REG32(NPCM7XX_PWM_PIIR, 0x40);
148
303
+REG32(NPCM7XX_PWM_PWDR0, 0x44);
149
-static const TypeInfo aspeed_machine_type = {
304
+REG32(NPCM7XX_PWM_PWDR1, 0x48);
150
- .name = TYPE_ASPEED_MACHINE,
305
+REG32(NPCM7XX_PWM_PWDR2, 0x4c);
151
- .parent = TYPE_MACHINE,
306
+REG32(NPCM7XX_PWM_PWDR3, 0x50);
152
- .instance_size = sizeof(AspeedMachine),
307
+
153
- .class_size = sizeof(AspeedMachineClass),
308
+/* Register field definitions. */
154
- .abstract = true,
309
+#define NPCM7XX_PPR(rv, index) extract32((rv), npcm7xx_ppr_base[index], 8)
155
-};
310
+#define NPCM7XX_CSR(rv, index) extract32((rv), npcm7xx_csr_base[index], 3)
156
-
311
+#define NPCM7XX_CH(rv, index) extract32((rv), npcm7xx_ch_base[index], 4)
157
-static const AspeedBoardConfig aspeed_boards[] = {
312
+#define NPCM7XX_CH_EN BIT(0)
158
- {
313
+#define NPCM7XX_CH_INV BIT(2)
159
- .name = MACHINE_TYPE_NAME("palmetto-bmc"),
314
+#define NPCM7XX_CH_MOD BIT(3)
160
- .desc = "OpenPOWER Palmetto BMC (ARM926EJ-S)",
315
+
161
- .soc_name = "ast2400-a1",
316
+/* Offset of each PWM channel's prescaler in the PPR register. */
162
- .hw_strap1 = PALMETTO_BMC_HW_STRAP1,
317
+static const int npcm7xx_ppr_base[] = { 0, 0, 8, 8 };
163
- .fmc_model = "n25q256a",
318
+/* Offset of each PWM channel's clock selector in the CSR register. */
164
- .spi_model = "mx25l25635e",
319
+static const int npcm7xx_csr_base[] = { 0, 4, 8, 12 };
165
- .num_cs = 1,
320
+/* Offset of each PWM channel's control variable in the PCR register. */
166
- .i2c_init = palmetto_bmc_i2c_init,
321
+static const int npcm7xx_ch_base[] = { 0, 8, 12, 16 };
167
- .ram = 256 * MiB,
322
+
168
- }, {
323
+static uint32_t npcm7xx_pwm_calculate_freq(NPCM7xxPWM *p)
169
- .name = MACHINE_TYPE_NAME("ast2500-evb"),
324
+{
170
- .desc = "Aspeed AST2500 EVB (ARM1176)",
325
+ uint32_t ppr;
171
- .soc_name = "ast2500-a1",
326
+ uint32_t csr;
172
- .hw_strap1 = AST2500_EVB_HW_STRAP1,
327
+ uint32_t freq;
173
- .fmc_model = "w25q256",
328
+
174
- .spi_model = "mx25l25635e",
329
+ if (!p->running) {
175
- .num_cs = 1,
330
+ return 0;
176
- .i2c_init = ast2500_evb_i2c_init,
331
+ }
177
- .ram = 512 * MiB,
332
+
178
- }, {
333
+ csr = NPCM7XX_CSR(p->module->csr, p->index);
179
- .name = MACHINE_TYPE_NAME("romulus-bmc"),
334
+ ppr = NPCM7XX_PPR(p->module->ppr, p->index);
180
- .desc = "OpenPOWER Romulus BMC (ARM1176)",
335
+ freq = clock_get_hz(p->module->clock);
181
- .soc_name = "ast2500-a1",
336
+ freq /= ppr + 1;
182
- .hw_strap1 = ROMULUS_BMC_HW_STRAP1,
337
+ /* csr can only be 0~4 */
183
- .fmc_model = "n25q256a",
338
+ if (csr > 4) {
184
- .spi_model = "mx66l1g45g",
339
+ qemu_log_mask(LOG_GUEST_ERROR,
185
- .num_cs = 2,
340
+ "%s: invalid csr value %u\n",
186
- .i2c_init = romulus_bmc_i2c_init,
341
+ __func__, csr);
187
- .ram = 512 * MiB,
342
+ csr = 4;
188
- }, {
343
+ }
189
- .name = MACHINE_TYPE_NAME("swift-bmc"),
344
+ /* freq won't be changed if csr == 4. */
190
- .desc = "OpenPOWER Swift BMC (ARM1176)",
345
+ if (csr < 4) {
191
- .soc_name = "ast2500-a1",
346
+ freq >>= csr + 1;
192
- .hw_strap1 = SWIFT_BMC_HW_STRAP1,
347
+ }
193
- .fmc_model = "mx66l1g45g",
348
+
194
- .spi_model = "mx66l1g45g",
349
+ return freq / (p->cnr + 1);
195
- .num_cs = 2,
350
+}
196
- .i2c_init = swift_bmc_i2c_init,
351
+
197
- .ram = 512 * MiB,
352
+static uint32_t npcm7xx_pwm_calculate_duty(NPCM7xxPWM *p)
198
- }, {
353
+{
199
- .name = MACHINE_TYPE_NAME("witherspoon-bmc"),
354
+ uint64_t duty;
200
- .desc = "OpenPOWER Witherspoon BMC (ARM1176)",
355
+
201
- .soc_name = "ast2500-a1",
356
+ if (p->running) {
202
- .hw_strap1 = WITHERSPOON_BMC_HW_STRAP1,
357
+ if (p->cnr == 0) {
203
- .fmc_model = "mx25l25635e",
358
+ duty = 0;
204
- .spi_model = "mx66l1g45g",
359
+ } else if (p->cmr >= p->cnr) {
205
- .num_cs = 2,
360
+ duty = NPCM7XX_PWM_MAX_DUTY;
206
- .i2c_init = witherspoon_bmc_i2c_init,
361
+ } else {
207
- .ram = 512 * MiB,
362
+ duty = NPCM7XX_PWM_MAX_DUTY * (p->cmr + 1) / (p->cnr + 1);
208
- }, {
363
+ }
209
- .name = MACHINE_TYPE_NAME("ast2600-evb"),
364
+ } else {
210
- .desc = "Aspeed AST2600 EVB (Cortex A7)",
365
+ duty = 0;
211
- .soc_name = "ast2600-a0",
366
+ }
212
- .hw_strap1 = AST2600_EVB_HW_STRAP1,
367
+
213
- .hw_strap2 = AST2600_EVB_HW_STRAP2,
368
+ if (p->inverted) {
214
- .fmc_model = "w25q512jv",
369
+ duty = NPCM7XX_PWM_MAX_DUTY - duty;
215
- .spi_model = "mx66u51235f",
370
+ }
216
- .num_cs = 1,
371
+
217
- .i2c_init = ast2600_evb_i2c_init,
372
+ return duty;
218
- .ram = 1 * GiB,
373
+}
219
- },
374
+
220
-};
375
+static void npcm7xx_pwm_update_freq(NPCM7xxPWM *p)
221
-
376
+{
222
-static void aspeed_machine_types(void)
377
+ uint32_t freq = npcm7xx_pwm_calculate_freq(p);
223
+static void aspeed_machine_palmetto_class_init(ObjectClass *oc, void *data)
378
+
224
{
379
+ if (freq != p->freq) {
225
- int i;
380
+ trace_npcm7xx_pwm_update_freq(DEVICE(p->module)->canonical_path,
226
+ MachineClass *mc = MACHINE_CLASS(oc);
381
+ p->index, p->freq, freq);
227
+ AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
382
+ p->freq = freq;
228
383
+ }
229
- type_register_static(&aspeed_machine_type);
384
+}
230
- for (i = 0; i < ARRAY_SIZE(aspeed_boards); ++i) {
385
+
231
- TypeInfo ti = {
386
+static void npcm7xx_pwm_update_duty(NPCM7xxPWM *p)
232
- .name = aspeed_boards[i].name,
387
+{
233
- .parent = TYPE_ASPEED_MACHINE,
388
+ uint32_t duty = npcm7xx_pwm_calculate_duty(p);
234
- .class_init = aspeed_machine_class_init,
389
+
235
- .class_data = (void *)&aspeed_boards[i],
390
+ if (duty != p->duty) {
236
- };
391
+ trace_npcm7xx_pwm_update_duty(DEVICE(p->module)->canonical_path,
237
- type_register(&ti);
392
+ p->index, p->duty, duty);
238
+ mc->desc = "OpenPOWER Palmetto BMC (ARM926EJ-S)";
393
+ p->duty = duty;
239
+ amc->soc_name = "ast2400-a1";
394
+ }
240
+ amc->hw_strap1 = PALMETTO_BMC_HW_STRAP1;
395
+}
241
+ amc->fmc_model = "n25q256a";
396
+
242
+ amc->spi_model = "mx25l25635e";
397
+static void npcm7xx_pwm_update_output(NPCM7xxPWM *p)
243
+ amc->num_cs = 1;
398
+{
244
+ amc->i2c_init = palmetto_bmc_i2c_init;
399
+ npcm7xx_pwm_update_freq(p);
245
+ mc->default_ram_size = 256 * MiB;
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
+ }
414
+ }
415
+}
416
+
417
+static void npcm7xx_pwm_write_csr(NPCM7xxPWMState *s, uint32_t new_csr)
418
+{
419
+ int i;
420
+ uint32_t old_csr = s->csr;
421
+
422
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_csr_base) != NPCM7XX_PWM_PER_MODULE);
423
+ s->csr = new_csr;
424
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
425
+ if (NPCM7XX_CSR(old_csr, i) != NPCM7XX_CSR(new_csr, i)) {
426
+ npcm7xx_pwm_update_freq(&s->pwm[i]);
427
+ }
428
+ }
429
+}
430
+
431
+static void npcm7xx_pwm_write_pcr(NPCM7xxPWMState *s, uint32_t new_pcr)
432
+{
433
+ int i;
434
+ bool inverted;
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
+ },
246
+};
687
+};
247
+
688
+
248
+static void aspeed_machine_ast2500_evb_class_init(ObjectClass *oc, void *data)
689
+static void npcm7xx_pwm_enter_reset(Object *obj, ResetType type)
249
+{
690
+{
250
+ MachineClass *mc = MACHINE_CLASS(oc);
691
+ NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
251
+ AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
692
+ int i;
252
+
693
+
253
+ mc->desc = "Aspeed AST2500 EVB (ARM1176)";
694
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
254
+ amc->soc_name = "ast2500-a1";
695
+ NPCM7xxPWM *p = &s->pwm[i];
255
+ amc->hw_strap1 = AST2500_EVB_HW_STRAP1;
696
+
256
+ amc->fmc_model = "w25q256";
697
+ p->cnr = 0x00000000;
257
+ amc->spi_model = "mx25l25635e";
698
+ p->cmr = 0x00000000;
258
+ amc->num_cs = 1;
699
+ p->pdr = 0x00000000;
259
+ amc->i2c_init = ast2500_evb_i2c_init;
700
+ p->pwdr = 0x00000000;
260
+ mc->default_ram_size = 512 * MiB;
701
+ }
702
+
703
+ s->ppr = 0x00000000;
704
+ s->csr = 0x00000000;
705
+ s->pcr = 0x00000000;
706
+ s->pier = 0x00000000;
707
+ s->piir = 0x00000000;
708
+}
709
+
710
+static void npcm7xx_pwm_hold_reset(Object *obj)
711
+{
712
+ NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
713
+ int i;
714
+
715
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
716
+ qemu_irq_lower(s->pwm[i].irq);
717
+ }
718
+}
719
+
720
+static void npcm7xx_pwm_init(Object *obj)
721
+{
722
+ NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
723
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
724
+ int i;
725
+
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
+ },
261
+};
762
+};
262
+
763
+
263
+static void aspeed_machine_romulus_class_init(ObjectClass *oc, void *data)
764
+static const VMStateDescription vmstate_npcm7xx_pwm_module = {
264
+{
765
+ .name = "npcm7xx-pwm-module",
265
+ MachineClass *mc = MACHINE_CLASS(oc);
766
+ .version_id = 0,
266
+ AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
767
+ .minimum_version_id = 0,
267
+
768
+ .fields = (VMStateField[]) {
268
+ mc->desc = "OpenPOWER Romulus BMC (ARM1176)";
769
+ VMSTATE_CLOCK(clock, NPCM7xxPWMState),
269
+ amc->soc_name = "ast2500-a1";
770
+ VMSTATE_STRUCT_ARRAY(pwm, NPCM7xxPWMState,
270
+ amc->hw_strap1 = ROMULUS_BMC_HW_STRAP1;
771
+ NPCM7XX_PWM_PER_MODULE, 0, vmstate_npcm7xx_pwm,
271
+ amc->fmc_model = "n25q256a";
772
+ NPCM7xxPWM),
272
+ amc->spi_model = "mx66l1g45g";
773
+ VMSTATE_UINT32(ppr, NPCM7xxPWMState),
273
+ amc->num_cs = 2;
774
+ VMSTATE_UINT32(csr, NPCM7xxPWMState),
274
+ amc->i2c_init = romulus_bmc_i2c_init;
775
+ VMSTATE_UINT32(pcr, NPCM7xxPWMState),
275
+ mc->default_ram_size = 512 * MiB;
776
+ VMSTATE_UINT32(pier, NPCM7xxPWMState),
777
+ VMSTATE_UINT32(piir, NPCM7xxPWMState),
778
+ VMSTATE_END_OF_LIST(),
779
+ },
276
+};
780
+};
277
+
781
+
278
+static void aspeed_machine_swift_class_init(ObjectClass *oc, void *data)
782
+static void npcm7xx_pwm_class_init(ObjectClass *klass, void *data)
279
+{
783
+{
280
+ MachineClass *mc = MACHINE_CLASS(oc);
784
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
281
+ AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
785
+ DeviceClass *dc = DEVICE_CLASS(klass);
282
+
786
+
283
+ mc->desc = "OpenPOWER Swift BMC (ARM1176)";
787
+ dc->desc = "NPCM7xx PWM Controller";
284
+ amc->soc_name = "ast2500-a1";
788
+ dc->vmsd = &vmstate_npcm7xx_pwm_module;
285
+ amc->hw_strap1 = SWIFT_BMC_HW_STRAP1;
789
+ rc->phases.enter = npcm7xx_pwm_enter_reset;
286
+ amc->fmc_model = "mx66l1g45g";
790
+ rc->phases.hold = npcm7xx_pwm_hold_reset;
287
+ amc->spi_model = "mx66l1g45g";
791
+}
288
+ amc->num_cs = 2;
792
+
289
+ amc->i2c_init = swift_bmc_i2c_init;
793
+static const TypeInfo npcm7xx_pwm_info = {
290
+ mc->default_ram_size = 512 * MiB;
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,
291
+};
799
+};
292
+
800
+
293
+static void aspeed_machine_witherspoon_class_init(ObjectClass *oc, void *data)
801
+static void npcm7xx_pwm_register_type(void)
294
+{
802
+{
295
+ MachineClass *mc = MACHINE_CLASS(oc);
803
+ type_register_static(&npcm7xx_pwm_info);
296
+ AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
804
+}
297
+
805
+type_init(npcm7xx_pwm_register_type);
298
+ mc->desc = "OpenPOWER Witherspoon BMC (ARM1176)";
806
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
299
+ amc->soc_name = "ast2500-a1";
807
index XXXXXXX..XXXXXXX 100644
300
+ amc->hw_strap1 = WITHERSPOON_BMC_HW_STRAP1;
808
--- a/hw/misc/meson.build
301
+ amc->fmc_model = "mx25l25635e";
809
+++ b/hw/misc/meson.build
302
+ amc->spi_model = "mx66l1g45g";
810
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c'))
303
+ amc->num_cs = 2;
811
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
304
+ amc->i2c_init = witherspoon_bmc_i2c_init;
812
'npcm7xx_clk.c',
305
+ mc->default_ram_size = 512 * MiB;
813
'npcm7xx_gcr.c',
306
+};
814
+ 'npcm7xx_pwm.c',
307
+
815
'npcm7xx_rng.c',
308
+static void aspeed_machine_ast2600_evb_class_init(ObjectClass *oc, void *data)
816
))
309
+{
817
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files(
310
+ MachineClass *mc = MACHINE_CLASS(oc);
818
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
311
+ AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
819
index XXXXXXX..XXXXXXX 100644
312
+
820
--- a/hw/misc/trace-events
313
+ mc->desc = "Aspeed AST2600 EVB (Cortex A7)";
821
+++ b/hw/misc/trace-events
314
+ amc->soc_name = "ast2600-a0";
822
@@ -XXX,XX +XXX,XX @@ npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " valu
315
+ amc->hw_strap1 = AST2600_EVB_HW_STRAP1;
823
npcm7xx_rng_read(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
316
+ amc->hw_strap2 = AST2600_EVB_HW_STRAP2;
824
npcm7xx_rng_write(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
317
+ amc->fmc_model = "w25q512jv";
825
318
+ amc->spi_model = "mx66u51235f";
826
+# npcm7xx_pwm.c
319
+ amc->num_cs = 1;
827
+npcm7xx_pwm_read(const char *id, uint64_t offset, uint32_t value) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
320
+ amc->i2c_init = ast2600_evb_i2c_init;
828
+npcm7xx_pwm_write(const char *id, uint64_t offset, uint32_t value) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
321
+ mc->default_ram_size = 1 * GiB;
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"
322
+};
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"
323
+
831
+
324
+static const TypeInfo aspeed_machine_types[] = {
832
# stm32f4xx_syscfg.c
325
+ {
833
stm32f4xx_syscfg_set_irq(int gpio, int line, int level) "Interupt: GPIO: %d, Line: %d; Level: %d"
326
+ .name = MACHINE_TYPE_NAME("palmetto-bmc"),
834
stm32f4xx_pulse_exti(int irq) "Pulse EXTI: %d"
327
+ .parent = TYPE_ASPEED_MACHINE,
328
+ .class_init = aspeed_machine_palmetto_class_init,
329
+ }, {
330
+ .name = MACHINE_TYPE_NAME("ast2500-evb"),
331
+ .parent = TYPE_ASPEED_MACHINE,
332
+ .class_init = aspeed_machine_ast2500_evb_class_init,
333
+ }, {
334
+ .name = MACHINE_TYPE_NAME("romulus-bmc"),
335
+ .parent = TYPE_ASPEED_MACHINE,
336
+ .class_init = aspeed_machine_romulus_class_init,
337
+ }, {
338
+ .name = MACHINE_TYPE_NAME("swift-bmc"),
339
+ .parent = TYPE_ASPEED_MACHINE,
340
+ .class_init = aspeed_machine_swift_class_init,
341
+ }, {
342
+ .name = MACHINE_TYPE_NAME("witherspoon-bmc"),
343
+ .parent = TYPE_ASPEED_MACHINE,
344
+ .class_init = aspeed_machine_witherspoon_class_init,
345
+ }, {
346
+ .name = MACHINE_TYPE_NAME("ast2600-evb"),
347
+ .parent = TYPE_ASPEED_MACHINE,
348
+ .class_init = aspeed_machine_ast2600_evb_class_init,
349
+ }, {
350
+ .name = TYPE_ASPEED_MACHINE,
351
+ .parent = TYPE_MACHINE,
352
+ .instance_size = sizeof(AspeedMachine),
353
+ .class_size = sizeof(AspeedMachineClass),
354
+ .class_init = aspeed_machine_class_init,
355
+ .abstract = true,
356
}
357
-}
358
+};
359
360
-type_init(aspeed_machine_types)
361
+DEFINE_TYPES(aspeed_machine_types)
362
--
835
--
363
2.20.1
836
2.20.1
364
837
365
838
diff view generated by jsdifflib
Deleted patch
1
From: Cédric Le Goater <clg@kaod.org>
2
1
3
The Aspeed Watchdog and Timer models have a link pointing to the SCU
4
controller model of the machine.
5
6
Change the "scu" property definition so that it explicitly sets the
7
pointer. The property isn't optional : not being able to set the link
8
is a bug and QEMU should rather abort than exit in this case.
9
10
Signed-off-by: Cédric Le Goater <clg@kaod.org>
11
Reviewed-by: Greg Kurz <groug@kaod.org>
12
Reviewed-by: Joel Stanley <joel@jms.id.au>
13
Signed-off-by: Cédric Le Goater <clg@kaod.org>
14
Message-id: 20191119141211.25716-17-clg@kaod.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
hw/arm/aspeed_ast2600.c | 8 ++++----
18
hw/arm/aspeed_soc.c | 8 ++++----
19
hw/timer/aspeed_timer.c | 17 +++++++++--------
20
hw/watchdog/wdt_aspeed.c | 17 ++++++++---------
21
4 files changed, 25 insertions(+), 25 deletions(-)
22
23
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/arm/aspeed_ast2600.c
26
+++ b/hw/arm/aspeed_ast2600.c
27
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2600_init(Object *obj)
28
snprintf(typename, sizeof(typename), "aspeed.timer-%s", socname);
29
sysbus_init_child_obj(obj, "timerctrl", OBJECT(&s->timerctrl),
30
sizeof(s->timerctrl), typename);
31
- object_property_add_const_link(OBJECT(&s->timerctrl), "scu",
32
- OBJECT(&s->scu), &error_abort);
33
34
snprintf(typename, sizeof(typename), "aspeed.i2c-%s", socname);
35
sysbus_init_child_obj(obj, "i2c", OBJECT(&s->i2c), sizeof(s->i2c),
36
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2600_init(Object *obj)
37
snprintf(typename, sizeof(typename), "aspeed.wdt-%s", socname);
38
sysbus_init_child_obj(obj, "wdt[*]", OBJECT(&s->wdt[i]),
39
sizeof(s->wdt[i]), typename);
40
- object_property_add_const_link(OBJECT(&s->wdt[i]), "scu",
41
- OBJECT(&s->scu), &error_abort);
42
}
43
44
for (i = 0; i < sc->macs_num; i++) {
45
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
46
aspeed_soc_get_irq(s, ASPEED_RTC));
47
48
/* Timer */
49
+ object_property_set_link(OBJECT(&s->timerctrl),
50
+ OBJECT(&s->scu), "scu", &error_abort);
51
object_property_set_bool(OBJECT(&s->timerctrl), true, "realized", &err);
52
if (err) {
53
error_propagate(errp, err);
54
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
55
for (i = 0; i < sc->wdts_num; i++) {
56
AspeedWDTClass *awc = ASPEED_WDT_GET_CLASS(&s->wdt[i]);
57
58
+ object_property_set_link(OBJECT(&s->wdt[i]),
59
+ OBJECT(&s->scu), "scu", &error_abort);
60
object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized", &err);
61
if (err) {
62
error_propagate(errp, err);
63
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/hw/arm/aspeed_soc.c
66
+++ b/hw/arm/aspeed_soc.c
67
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj)
68
snprintf(typename, sizeof(typename), "aspeed.timer-%s", socname);
69
sysbus_init_child_obj(obj, "timerctrl", OBJECT(&s->timerctrl),
70
sizeof(s->timerctrl), typename);
71
- object_property_add_const_link(OBJECT(&s->timerctrl), "scu",
72
- OBJECT(&s->scu), &error_abort);
73
74
snprintf(typename, sizeof(typename), "aspeed.i2c-%s", socname);
75
sysbus_init_child_obj(obj, "i2c", OBJECT(&s->i2c), sizeof(s->i2c),
76
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_init(Object *obj)
77
snprintf(typename, sizeof(typename), "aspeed.wdt-%s", socname);
78
sysbus_init_child_obj(obj, "wdt[*]", OBJECT(&s->wdt[i]),
79
sizeof(s->wdt[i]), typename);
80
- object_property_add_const_link(OBJECT(&s->wdt[i]), "scu",
81
- OBJECT(&s->scu), &error_abort);
82
}
83
84
for (i = 0; i < sc->macs_num; i++) {
85
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
86
aspeed_soc_get_irq(s, ASPEED_RTC));
87
88
/* Timer */
89
+ object_property_set_link(OBJECT(&s->timerctrl),
90
+ OBJECT(&s->scu), "scu", &error_abort);
91
object_property_set_bool(OBJECT(&s->timerctrl), true, "realized", &err);
92
if (err) {
93
error_propagate(errp, err);
94
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
95
for (i = 0; i < sc->wdts_num; i++) {
96
AspeedWDTClass *awc = ASPEED_WDT_GET_CLASS(&s->wdt[i]);
97
98
+ object_property_set_link(OBJECT(&s->wdt[i]),
99
+ OBJECT(&s->scu), "scu", &error_abort);
100
object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized", &err);
101
if (err) {
102
error_propagate(errp, err);
103
diff --git a/hw/timer/aspeed_timer.c b/hw/timer/aspeed_timer.c
104
index XXXXXXX..XXXXXXX 100644
105
--- a/hw/timer/aspeed_timer.c
106
+++ b/hw/timer/aspeed_timer.c
107
@@ -XXX,XX +XXX,XX @@
108
#include "qemu/timer.h"
109
#include "qemu/log.h"
110
#include "qemu/module.h"
111
+#include "hw/qdev-properties.h"
112
#include "trace.h"
113
114
#define TIMER_NR_REGS 4
115
@@ -XXX,XX +XXX,XX @@ static void aspeed_timer_realize(DeviceState *dev, Error **errp)
116
int i;
117
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
118
AspeedTimerCtrlState *s = ASPEED_TIMER(dev);
119
- Object *obj;
120
- Error *err = NULL;
121
122
- obj = object_property_get_link(OBJECT(dev), "scu", &err);
123
- if (!obj) {
124
- error_propagate_prepend(errp, err, "required link 'scu' not found: ");
125
- return;
126
- }
127
- s->scu = ASPEED_SCU(obj);
128
+ assert(s->scu);
129
130
for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) {
131
aspeed_init_one_timer(s, i);
132
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_aspeed_timer_state = {
133
}
134
};
135
136
+static Property aspeed_timer_properties[] = {
137
+ DEFINE_PROP_LINK("scu", AspeedTimerCtrlState, scu, TYPE_ASPEED_SCU,
138
+ AspeedSCUState *),
139
+ DEFINE_PROP_END_OF_LIST(),
140
+};
141
+
142
static void timer_class_init(ObjectClass *klass, void *data)
143
{
144
DeviceClass *dc = DEVICE_CLASS(klass);
145
@@ -XXX,XX +XXX,XX @@ static void timer_class_init(ObjectClass *klass, void *data)
146
dc->reset = aspeed_timer_reset;
147
dc->desc = "ASPEED Timer";
148
dc->vmsd = &vmstate_aspeed_timer_state;
149
+ dc->props = aspeed_timer_properties;
150
}
151
152
static const TypeInfo aspeed_timer_info = {
153
diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
154
index XXXXXXX..XXXXXXX 100644
155
--- a/hw/watchdog/wdt_aspeed.c
156
+++ b/hw/watchdog/wdt_aspeed.c
157
@@ -XXX,XX +XXX,XX @@ static void aspeed_wdt_realize(DeviceState *dev, Error **errp)
158
{
159
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
160
AspeedWDTState *s = ASPEED_WDT(dev);
161
- Error *err = NULL;
162
- Object *obj;
163
164
- obj = object_property_get_link(OBJECT(dev), "scu", &err);
165
- if (!obj) {
166
- error_propagate(errp, err);
167
- error_prepend(errp, "required link 'scu' not found: ");
168
- return;
169
- }
170
- s->scu = ASPEED_SCU(obj);
171
+ assert(s->scu);
172
173
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, aspeed_wdt_timer_expired, dev);
174
175
@@ -XXX,XX +XXX,XX @@ static void aspeed_wdt_realize(DeviceState *dev, Error **errp)
176
sysbus_init_mmio(sbd, &s->iomem);
177
}
178
179
+static Property aspeed_wdt_properties[] = {
180
+ DEFINE_PROP_LINK("scu", AspeedWDTState, scu, TYPE_ASPEED_SCU,
181
+ AspeedSCUState *),
182
+ DEFINE_PROP_END_OF_LIST(),
183
+};
184
+
185
static void aspeed_wdt_class_init(ObjectClass *klass, void *data)
186
{
187
DeviceClass *dc = DEVICE_CLASS(klass);
188
@@ -XXX,XX +XXX,XX @@ static void aspeed_wdt_class_init(ObjectClass *klass, void *data)
189
dc->reset = aspeed_wdt_reset;
190
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
191
dc->vmsd = &vmstate_aspeed_wdt;
192
+ dc->props = aspeed_wdt_properties;
193
}
194
195
static const TypeInfo aspeed_wdt_info = {
196
--
197
2.20.1
198
199
diff view generated by jsdifflib
Deleted patch
1
From: Marc Zyngier <maz@kernel.org>
2
1
3
HCR_EL2.TID2 mandates that access from EL1 to CTR_EL0, CCSIDR_EL1,
4
CCSIDR2_EL1, CLIDR_EL1, CSSELR_EL1 are trapped to EL2, and QEMU
5
completely ignores it, making it impossible for hypervisors to
6
virtualize the cache hierarchy.
7
8
Do the right thing by trapping to EL2 if HCR_EL2.TID2 is set.
9
10
Signed-off-by: Marc Zyngier <maz@kernel.org>
11
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20191201122018.25808-2-maz@kernel.org
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
target/arm/helper.c | 31 +++++++++++++++++++++++++++----
17
1 file changed, 27 insertions(+), 4 deletions(-)
18
19
diff --git a/target/arm/helper.c b/target/arm/helper.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/helper.c
22
+++ b/target/arm/helper.c
23
@@ -XXX,XX +XXX,XX @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
24
raw_write(env, ri, value);
25
}
26
27
+static CPAccessResult access_aa64_tid2(CPUARMState *env,
28
+ const ARMCPRegInfo *ri,
29
+ bool isread)
30
+{
31
+ if (arm_current_el(env) == 1 && (arm_hcr_el2_eff(env) & HCR_TID2)) {
32
+ return CP_ACCESS_TRAP_EL2;
33
+ }
34
+
35
+ return CP_ACCESS_OK;
36
+}
37
+
38
static uint64_t ccsidr_read(CPUARMState *env, const ARMCPRegInfo *ri)
39
{
40
ARMCPU *cpu = env_archcpu(env);
41
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
42
.writefn = pmintenclr_write },
43
{ .name = "CCSIDR", .state = ARM_CP_STATE_BOTH,
44
.opc0 = 3, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 0,
45
- .access = PL1_R, .readfn = ccsidr_read, .type = ARM_CP_NO_RAW },
46
+ .access = PL1_R,
47
+ .accessfn = access_aa64_tid2,
48
+ .readfn = ccsidr_read, .type = ARM_CP_NO_RAW },
49
{ .name = "CSSELR", .state = ARM_CP_STATE_BOTH,
50
.opc0 = 3, .crn = 0, .crm = 0, .opc1 = 2, .opc2 = 0,
51
- .access = PL1_RW, .writefn = csselr_write, .resetvalue = 0,
52
+ .access = PL1_RW,
53
+ .accessfn = access_aa64_tid2,
54
+ .writefn = csselr_write, .resetvalue = 0,
55
.bank_fieldoffsets = { offsetof(CPUARMState, cp15.csselr_s),
56
offsetof(CPUARMState, cp15.csselr_ns) } },
57
/* Auxiliary ID register: this actually has an IMPDEF value but for now
58
@@ -XXX,XX +XXX,XX @@ static CPAccessResult ctr_el0_access(CPUARMState *env, const ARMCPRegInfo *ri,
59
if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UCT)) {
60
return CP_ACCESS_TRAP;
61
}
62
+
63
+ if (arm_current_el(env) < 2 && arm_hcr_el2_eff(env) & HCR_TID2) {
64
+ return CP_ACCESS_TRAP_EL2;
65
+ }
66
+
67
return CP_ACCESS_OK;
68
}
69
70
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
71
ARMCPRegInfo clidr = {
72
.name = "CLIDR", .state = ARM_CP_STATE_BOTH,
73
.opc0 = 3, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 1,
74
- .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = cpu->clidr
75
+ .access = PL1_R, .type = ARM_CP_CONST,
76
+ .accessfn = access_aa64_tid2,
77
+ .resetvalue = cpu->clidr
78
};
79
define_one_arm_cp_reg(cpu, &clidr);
80
define_arm_cp_regs(cpu, v7_cp_reginfo);
81
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
82
/* These are common to v8 and pre-v8 */
83
{ .name = "CTR",
84
.cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 1,
85
- .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = cpu->ctr },
86
+ .access = PL1_R, .accessfn = ctr_el0_access,
87
+ .type = ARM_CP_CONST, .resetvalue = cpu->ctr },
88
{ .name = "CTR_EL0", .state = ARM_CP_STATE_AA64,
89
.opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 0, .crm = 0,
90
.access = PL0_R, .accessfn = ctr_el0_access,
91
--
92
2.20.1
93
94
diff view generated by jsdifflib
Deleted patch
1
From: Marc Zyngier <maz@kernel.org>
2
1
3
HCR_EL2.TID1 mandates that access from EL1 to REVIDR_EL1, AIDR_EL1
4
(and their 32bit equivalents) as well as TCMTR, TLBTR are trapped
5
to EL2. QEMU ignores it, making it harder for a hypervisor to
6
virtualize the HW (though to be fair, no known hypervisor actually
7
cares).
8
9
Do the right thing by trapping to EL2 if HCR_EL2.TID1 is set.
10
11
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
12
Signed-off-by: Marc Zyngier <maz@kernel.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20191201122018.25808-3-maz@kernel.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
target/arm/helper.c | 36 ++++++++++++++++++++++++++++++++----
18
1 file changed, 32 insertions(+), 4 deletions(-)
19
20
diff --git a/target/arm/helper.c b/target/arm/helper.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/helper.c
23
+++ b/target/arm/helper.c
24
@@ -XXX,XX +XXX,XX @@ static uint64_t isr_read(CPUARMState *env, const ARMCPRegInfo *ri)
25
return ret;
26
}
27
28
+static CPAccessResult access_aa64_tid1(CPUARMState *env, const ARMCPRegInfo *ri,
29
+ bool isread)
30
+{
31
+ if (arm_current_el(env) == 1 && (arm_hcr_el2_eff(env) & HCR_TID1)) {
32
+ return CP_ACCESS_TRAP_EL2;
33
+ }
34
+
35
+ return CP_ACCESS_OK;
36
+}
37
+
38
+static CPAccessResult access_aa32_tid1(CPUARMState *env, const ARMCPRegInfo *ri,
39
+ bool isread)
40
+{
41
+ if (arm_feature(env, ARM_FEATURE_V8)) {
42
+ return access_aa64_tid1(env, ri, isread);
43
+ }
44
+
45
+ return CP_ACCESS_OK;
46
+}
47
+
48
static const ARMCPRegInfo v7_cp_reginfo[] = {
49
/* the old v6 WFI, UNPREDICTABLE in v7 but we choose to NOP */
50
{ .name = "NOP", .cp = 15, .crn = 7, .crm = 0, .opc1 = 0, .opc2 = 4,
51
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
52
*/
53
{ .name = "AIDR", .state = ARM_CP_STATE_BOTH,
54
.opc0 = 3, .opc1 = 1, .crn = 0, .crm = 0, .opc2 = 7,
55
- .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
56
+ .access = PL1_R, .type = ARM_CP_CONST,
57
+ .accessfn = access_aa64_tid1,
58
+ .resetvalue = 0 },
59
/* Auxiliary fault status registers: these also are IMPDEF, and we
60
* choose to RAZ/WI for all cores.
61
*/
62
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
63
.access = PL1_R, .resetvalue = cpu->midr },
64
{ .name = "REVIDR_EL1", .state = ARM_CP_STATE_BOTH,
65
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 0, .opc2 = 6,
66
- .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = cpu->revidr },
67
+ .access = PL1_R,
68
+ .accessfn = access_aa64_tid1,
69
+ .type = ARM_CP_CONST, .resetvalue = cpu->revidr },
70
REGINFO_SENTINEL
71
};
72
ARMCPRegInfo id_cp_reginfo[] = {
73
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
74
/* TCMTR and TLBTR exist in v8 but have no 64-bit versions */
75
{ .name = "TCMTR",
76
.cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 2,
77
- .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
78
+ .access = PL1_R,
79
+ .accessfn = access_aa32_tid1,
80
+ .type = ARM_CP_CONST, .resetvalue = 0 },
81
REGINFO_SENTINEL
82
};
83
/* TLBTR is specific to VMSA */
84
ARMCPRegInfo id_tlbtr_reginfo = {
85
.name = "TLBTR",
86
.cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 3,
87
- .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0,
88
+ .access = PL1_R,
89
+ .accessfn = access_aa32_tid1,
90
+ .type = ARM_CP_CONST, .resetvalue = 0,
91
};
92
/* MPUIR is specific to PMSA V6+ */
93
ARMCPRegInfo id_mpuir_reginfo = {
94
--
95
2.20.1
96
97
diff view generated by jsdifflib
1
From: Marc Zyngier <maz@kernel.org>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
HCR_EL2.TID3 requires that AArch32 reads of MVFR[012] are trapped to
3
We add a qtest for the PWM in the previous patch. It proves it works as
4
EL2, and HCR_EL2.TID0 does the same for reads of FPSID.
4
expected.
5
In order to handle this, introduce a new TCG helper function that
6
checks for these control bits before executing the VMRC instruction.
7
5
8
Tested with a hacked-up version of KVM/arm64 that sets the control
6
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
9
bits for 32bit guests.
7
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
10
8
Signed-off-by: Hao Wu <wuhaotsh@google.com>
11
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Marc Zyngier <maz@kernel.org>
10
Message-id: 20210108190945.949196-6-wuhaotsh@google.com
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20191201122018.25808-4-maz@kernel.org
15
[PMM: move helper declaration to helper.h; make it
16
TCG_CALL_NO_WG]
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
12
---
19
target/arm/helper.h | 2 ++
13
tests/qtest/npcm7xx_pwm-test.c | 490 +++++++++++++++++++++++++++++++++
20
target/arm/translate-vfp.inc.c | 20 ++++++++++++++++----
14
tests/qtest/meson.build | 1 +
21
target/arm/vfp_helper.c | 29 +++++++++++++++++++++++++++++
15
2 files changed, 491 insertions(+)
22
3 files changed, 47 insertions(+), 4 deletions(-)
16
create mode 100644 tests/qtest/npcm7xx_pwm-test.c
23
17
24
diff --git a/target/arm/helper.h b/target/arm/helper.h
18
diff --git a/tests/qtest/npcm7xx_pwm-test.c b/tests/qtest/npcm7xx_pwm-test.c
25
index XXXXXXX..XXXXXXX 100644
19
new file mode 100644
26
--- a/target/arm/helper.h
20
index XXXXXXX..XXXXXXX
27
+++ b/target/arm/helper.h
21
--- /dev/null
28
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(rintd, TCG_CALL_NO_RWG, f64, f64, ptr)
22
+++ b/tests/qtest/npcm7xx_pwm-test.c
29
DEF_HELPER_FLAGS_2(vjcvt, TCG_CALL_NO_RWG, i32, f64, env)
23
@@ -XXX,XX +XXX,XX @@
30
DEF_HELPER_FLAGS_2(fjcvtzs, TCG_CALL_NO_RWG, i64, f64, ptr)
24
+/*
31
25
+ * QTests for Nuvoton NPCM7xx PWM Modules.
32
+DEF_HELPER_FLAGS_3(check_hcr_el2_trap, TCG_CALL_NO_WG, void, env, i32, i32)
26
+ *
33
+
27
+ * Copyright 2020 Google LLC
34
/* neon_helper.c */
28
+ *
35
DEF_HELPER_FLAGS_3(neon_qadd_u8, TCG_CALL_NO_RWG, i32, env, i32, i32)
29
+ * This program is free software; you can redistribute it and/or modify it
36
DEF_HELPER_FLAGS_3(neon_qadd_s8, TCG_CALL_NO_RWG, i32, env, i32, i32)
30
+ * under the terms of the GNU General Public License as published by the
37
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
31
+ * Free Software Foundation; either version 2 of the License, or
38
index XXXXXXX..XXXXXXX 100644
32
+ * (at your option) any later version.
39
--- a/target/arm/translate-vfp.inc.c
33
+ *
40
+++ b/target/arm/translate-vfp.inc.c
34
+ * This program is distributed in the hope that it will be useful, but WITHOUT
41
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
35
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
42
if (a->l) {
36
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
43
/* VMRS, move VFP special register to gp register */
37
+ * for more details.
44
switch (a->reg) {
38
+ */
45
- case ARM_VFP_FPSID:
39
+
46
- case ARM_VFP_FPEXC:
40
+#include "qemu/osdep.h"
47
- case ARM_VFP_FPINST:
41
+#include "qemu/bitops.h"
48
- case ARM_VFP_FPINST2:
42
+#include "libqos/libqtest.h"
49
case ARM_VFP_MVFR0:
43
+#include "qapi/qmp/qdict.h"
50
case ARM_VFP_MVFR1:
44
+#include "qapi/qmp/qnum.h"
51
case ARM_VFP_MVFR2:
45
+
52
+ case ARM_VFP_FPSID:
46
+#define REF_HZ 25000000
53
+ if (s->current_el == 1) {
47
+
54
+ TCGv_i32 tcg_reg, tcg_rt;
48
+/* Register field definitions. */
55
+
49
+#define CH_EN BIT(0)
56
+ gen_set_condexec(s);
50
+#define CH_INV BIT(2)
57
+ gen_set_pc_im(s, s->pc_curr);
51
+#define CH_MOD BIT(3)
58
+ tcg_reg = tcg_const_i32(a->reg);
52
+
59
+ tcg_rt = tcg_const_i32(a->rt);
53
+/* Registers shared between all PWMs in a module */
60
+ gen_helper_check_hcr_el2_trap(cpu_env, tcg_rt, tcg_reg);
54
+#define PPR 0x00
61
+ tcg_temp_free_i32(tcg_reg);
55
+#define CSR 0x04
62
+ tcg_temp_free_i32(tcg_rt);
56
+#define PCR 0x08
63
+ }
57
+#define PIER 0x3c
64
+ /* fall through */
58
+#define PIIR 0x40
65
+ case ARM_VFP_FPEXC:
59
+
66
+ case ARM_VFP_FPINST:
60
+/* CLK module related */
67
+ case ARM_VFP_FPINST2:
61
+#define CLK_BA 0xf0801000
68
tmp = load_cpu_field(vfp.xregs[a->reg]);
62
+#define CLKSEL 0x04
69
break;
63
+#define CLKDIV1 0x08
70
case ARM_VFP_FPSCR:
64
+#define CLKDIV2 0x2c
71
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
65
+#define PLLCON0 0x0c
72
index XXXXXXX..XXXXXXX 100644
66
+#define PLLCON1 0x10
73
--- a/target/arm/vfp_helper.c
67
+#define PLL_INDV(rv) extract32((rv), 0, 6)
74
+++ b/target/arm/vfp_helper.c
68
+#define PLL_FBDV(rv) extract32((rv), 16, 12)
75
@@ -XXX,XX +XXX,XX @@ float64 HELPER(frint64_d)(float64 f, void *fpst)
69
+#define PLL_OTDV1(rv) extract32((rv), 8, 3)
76
return frint_d(f, fpst, 64);
70
+#define PLL_OTDV2(rv) extract32((rv), 13, 3)
77
}
71
+#define APB3CKDIV(rv) extract32((rv), 28, 2)
78
72
+#define CLK2CKDIV(rv) extract32((rv), 0, 1)
79
+void HELPER(check_hcr_el2_trap)(CPUARMState *env, uint32_t rt, uint32_t reg)
73
+#define CLK4CKDIV(rv) extract32((rv), 26, 2)
80
+{
74
+#define CPUCKSEL(rv) extract32((rv), 0, 2)
81
+ uint32_t syndrome;
75
+
82
+
76
+#define MAX_DUTY 1000000
83
+ switch (reg) {
77
+
84
+ case ARM_VFP_MVFR0:
78
+typedef struct PWMModule {
85
+ case ARM_VFP_MVFR1:
79
+ int irq;
86
+ case ARM_VFP_MVFR2:
80
+ uint64_t base_addr;
87
+ if (!(arm_hcr_el2_eff(env) & HCR_TID3)) {
81
+} PWMModule;
88
+ return;
82
+
89
+ }
83
+typedef struct PWM {
84
+ uint32_t cnr_offset;
85
+ uint32_t cmr_offset;
86
+ uint32_t pdr_offset;
87
+ uint32_t pwdr_offset;
88
+} PWM;
89
+
90
+typedef struct TestData {
91
+ const PWMModule *module;
92
+ const PWM *pwm;
93
+} TestData;
94
+
95
+static const PWMModule pwm_module_list[] = {
96
+ {
97
+ .irq = 93,
98
+ .base_addr = 0xf0103000
99
+ },
100
+ {
101
+ .irq = 94,
102
+ .base_addr = 0xf0104000
103
+ }
104
+};
105
+
106
+static const PWM pwm_list[] = {
107
+ {
108
+ .cnr_offset = 0x0c,
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);
90
+ break;
251
+ break;
91
+ case ARM_VFP_FPSID:
252
+ case 1:
92
+ if (!(arm_hcr_el2_eff(env) & HCR_TID0)) {
253
+ pllcon = qtest_readl(qts, CLK_BA + PLLCON1);
93
+ return;
254
+ freq = get_pll(pllcon);
94
+ }
255
+ break;
256
+ case 2:
257
+ break;
258
+ case 3:
95
+ break;
259
+ break;
96
+ default:
260
+ default:
97
+ g_assert_not_reached();
261
+ g_assert_not_reached();
98
+ }
262
+ }
99
+
263
+
100
+ syndrome = ((EC_FPIDTRAP << ARM_EL_EC_SHIFT)
264
+ freq >>= (CLK2CKDIV(clkdiv1) + CLK4CKDIV(clkdiv1) + APB3CKDIV(clkdiv2));
101
+ | ARM_EL_IL
265
+
102
+ | (1 << 24) | (0xe << 20) | (7 << 14)
266
+ return freq;
103
+ | (reg << 10) | (rt << 5) | 1);
267
+}
104
+
268
+
105
+ raise_exception(env, EXCP_HYP_TRAP, syndrome, 2);
269
+static uint32_t pwm_selector(uint32_t csr)
106
+}
270
+{
107
+
271
+ switch (csr) {
108
#endif
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
+
385
+ qtest_quit(qts);
386
+}
387
+
388
+/* One-shot mode should not change frequency and duty cycle. */
389
+static void test_oneshot(gconstpointer test_data)
390
+{
391
+ const TestData *td = test_data;
392
+ QTestState *qts = qtest_init("-machine quanta-gsj");
393
+ int module = pwm_module_index(td->module);
394
+ int pwm = pwm_index(td->pwm);
395
+ uint32_t ppr, csr, pcr;
396
+ int i, j;
397
+
398
+ pcr = CH_EN;
399
+ for (i = 0; i < ARRAY_SIZE(ppr_list); ++i) {
400
+ ppr = ppr_list[i];
401
+ pwm_write_ppr(qts, td, ppr);
402
+
403
+ for (j = 0; j < ARRAY_SIZE(csr_list); ++j) {
404
+ csr = csr_list[j];
405
+ pwm_write_csr(qts, td, csr);
406
+ pwm_write_pcr(qts, td, pcr);
407
+
408
+ g_assert_cmpuint(pwm_read_ppr(qts, td), ==, ppr);
409
+ g_assert_cmpuint(pwm_read_csr(qts, td), ==, csr);
410
+ g_assert_cmpuint(pwm_read_pcr(qts, td), ==, pcr);
411
+ g_assert_cmpuint(pwm_get_freq(qts, module, pwm), ==, 0);
412
+ g_assert_cmpuint(pwm_get_duty(qts, module, pwm), ==, 0);
413
+ }
414
+ }
415
+
416
+ qtest_quit(qts);
417
+}
418
+
419
+/* In toggle mode, the PWM generates correct outputs. */
420
+static void test_toggle(gconstpointer test_data)
421
+{
422
+ const TestData *td = test_data;
423
+ QTestState *qts = qtest_init("-machine quanta-gsj");
424
+ int module = pwm_module_index(td->module);
425
+ int pwm = pwm_index(td->pwm);
426
+ uint32_t ppr, csr, pcr, cnr, cmr;
427
+ int i, j, k, l;
428
+ uint64_t expected_freq, expected_duty;
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
+
493
+int main(int argc, char **argv)
494
+{
495
+ TestData test_data_list[ARRAY_SIZE(pwm_module_list) * ARRAY_SIZE(pwm_list)];
496
+
497
+ g_test_init(&argc, &argv, NULL);
498
+
499
+ for (int i = 0; i < ARRAY_SIZE(pwm_module_list); ++i) {
500
+ for (int j = 0; j < ARRAY_SIZE(pwm_list); ++j) {
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();
513
+}
514
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
515
index XXXXXXX..XXXXXXX 100644
516
--- a/tests/qtest/meson.build
517
+++ b/tests/qtest/meson.build
518
@@ -XXX,XX +XXX,XX @@ qtests_sparc64 = \
519
qtests_npcm7xx = \
520
['npcm7xx_adc-test',
521
'npcm7xx_gpio-test',
522
+ 'npcm7xx_pwm-test',
523
'npcm7xx_rng-test',
524
'npcm7xx_timer-test',
525
'npcm7xx_watchdog_timer-test']
109
--
526
--
110
2.20.1
527
2.20.1
111
528
112
529
diff view generated by jsdifflib
1
From: Beata Michalska <beata.michalska@linaro.org>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
Add an option to trigger memory writeback to sync given memory region
3
A device shouldn't access its parent object which is QOM internal.
4
with the corresponding backing store, case one is available.
4
Instead it should use type cast for this purporse. This patch fixes this
5
This extends the support for persistent memory, allowing syncing on-demand.
5
issue for all NPCM7XX Devices.
6
6
7
Signed-off-by: Beata Michalska <beata.michalska@linaro.org>
7
Signed-off-by: Hao Wu <wuhaotsh@google.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20191121000843.24844-3-beata.michalska@linaro.org
9
Message-id: 20210108190945.949196-7-wuhaotsh@google.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
include/exec/memory.h | 6 ++++++
12
hw/arm/npcm7xx_boards.c | 2 +-
13
include/exec/ram_addr.h | 8 ++++++++
13
hw/mem/npcm7xx_mc.c | 2 +-
14
include/qemu/cutils.h | 1 +
14
hw/misc/npcm7xx_clk.c | 2 +-
15
exec.c | 36 ++++++++++++++++++++++++++++++++++++
15
hw/misc/npcm7xx_gcr.c | 2 +-
16
memory.c | 12 ++++++++++++
16
hw/misc/npcm7xx_rng.c | 2 +-
17
util/cutils.c | 38 ++++++++++++++++++++++++++++++++++++++
17
hw/nvram/npcm7xx_otp.c | 2 +-
18
6 files changed, 101 insertions(+)
18
hw/ssi/npcm7xx_fiu.c | 2 +-
19
7 files changed, 7 insertions(+), 7 deletions(-)
19
20
20
diff --git a/include/exec/memory.h b/include/exec/memory.h
21
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
21
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
22
--- a/include/exec/memory.h
23
--- a/hw/arm/npcm7xx_boards.c
23
+++ b/include/exec/memory.h
24
+++ b/hw/arm/npcm7xx_boards.c
24
@@ -XXX,XX +XXX,XX @@ void *memory_region_get_ram_ptr(MemoryRegion *mr);
25
@@ -XXX,XX +XXX,XX @@ static NPCM7xxState *npcm7xx_create_soc(MachineState *machine,
25
*/
26
uint32_t hw_straps)
26
void memory_region_ram_resize(MemoryRegion *mr, ram_addr_t newsize,
27
{
27
Error **errp);
28
NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_GET_CLASS(machine);
28
+/**
29
- MachineClass *mc = &nmc->parent;
29
+ * memory_region_do_writeback: Trigger writeback for selected address range
30
+ MachineClass *mc = MACHINE_CLASS(nmc);
30
+ * [addr, addr + size]
31
Object *obj;
31
+ *
32
32
+ */
33
if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
33
+void memory_region_do_writeback(MemoryRegion *mr, hwaddr addr, hwaddr size);
34
diff --git a/hw/mem/npcm7xx_mc.c b/hw/mem/npcm7xx_mc.c
34
35
/**
36
* memory_region_set_log: Turn dirty logging on or off for a region.
37
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
38
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
39
--- a/include/exec/ram_addr.h
36
--- a/hw/mem/npcm7xx_mc.c
40
+++ b/include/exec/ram_addr.h
37
+++ b/hw/mem/npcm7xx_mc.c
41
@@ -XXX,XX +XXX,XX @@ void qemu_ram_free(RAMBlock *block);
38
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_mc_realize(DeviceState *dev, Error **errp)
42
39
43
int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp);
40
memory_region_init_io(&s->mmio, OBJECT(s), &npcm7xx_mc_ops, s, "regs",
44
41
NPCM7XX_MC_REGS_SIZE);
45
+void qemu_ram_writeback(RAMBlock *block, ram_addr_t start, ram_addr_t length);
42
- sysbus_init_mmio(&s->parent, &s->mmio);
46
+
43
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio);
47
+/* Clear whole block of mem */
44
}
48
+static inline void qemu_ram_block_writeback(RAMBlock *block)
45
49
+{
46
static void npcm7xx_mc_class_init(ObjectClass *klass, void *data)
50
+ qemu_ram_writeback(block, 0, block->used_length);
47
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
51
+}
52
+
53
#define DIRTY_CLIENTS_ALL ((1 << DIRTY_MEMORY_NUM) - 1)
54
#define DIRTY_CLIENTS_NOCODE (DIRTY_CLIENTS_ALL & ~(1 << DIRTY_MEMORY_CODE))
55
56
diff --git a/include/qemu/cutils.h b/include/qemu/cutils.h
57
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
58
--- a/include/qemu/cutils.h
49
--- a/hw/misc/npcm7xx_clk.c
59
+++ b/include/qemu/cutils.h
50
+++ b/hw/misc/npcm7xx_clk.c
60
@@ -XXX,XX +XXX,XX @@ const char *qemu_strchrnul(const char *s, int c);
51
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_init(Object *obj)
61
#endif
52
62
time_t mktimegm(struct tm *tm);
53
memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s,
63
int qemu_fdatasync(int fd);
54
TYPE_NPCM7XX_CLK, 4 * KiB);
64
+int qemu_msync(void *addr, size_t length, int fd);
55
- sysbus_init_mmio(&s->parent, &s->iomem);
65
int fcntl_setfl(int fd, int flag);
56
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
66
int qemu_parse_fd(const char *param);
57
}
67
int qemu_strtoi(const char *nptr, const char **endptr, int base,
58
68
diff --git a/exec.c b/exec.c
59
static int npcm7xx_clk_post_load(void *opaque, int version_id)
60
diff --git a/hw/misc/npcm7xx_gcr.c b/hw/misc/npcm7xx_gcr.c
69
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
70
--- a/exec.c
62
--- a/hw/misc/npcm7xx_gcr.c
71
+++ b/exec.c
63
+++ b/hw/misc/npcm7xx_gcr.c
72
@@ -XXX,XX +XXX,XX @@
64
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_gcr_init(Object *obj)
73
#include "exec/ram_addr.h"
65
74
#include "exec/log.h"
66
memory_region_init_io(&s->iomem, obj, &npcm7xx_gcr_ops, s,
75
67
TYPE_NPCM7XX_GCR, 4 * KiB);
76
+#include "qemu/pmem.h"
68
- sysbus_init_mmio(&s->parent, &s->iomem);
77
+
69
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
78
#include "migration/vmstate.h"
79
80
#include "qemu/range.h"
81
@@ -XXX,XX +XXX,XX @@ int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp)
82
return 0;
83
}
70
}
84
71
85
+/*
72
static const VMStateDescription vmstate_npcm7xx_gcr = {
86
+ * Trigger sync on the given ram block for range [start, start + length]
73
diff --git a/hw/misc/npcm7xx_rng.c b/hw/misc/npcm7xx_rng.c
87
+ * with the backing store if one is available.
88
+ * Otherwise no-op.
89
+ * @Note: this is supposed to be a synchronous op.
90
+ */
91
+void qemu_ram_writeback(RAMBlock *block, ram_addr_t start, ram_addr_t length)
92
+{
93
+ void *addr = ramblock_ptr(block, start);
94
+
95
+ /* The requested range should fit in within the block range */
96
+ g_assert((start + length) <= block->used_length);
97
+
98
+#ifdef CONFIG_LIBPMEM
99
+ /* The lack of support for pmem should not block the sync */
100
+ if (ramblock_is_pmem(block)) {
101
+ pmem_persist(addr, length);
102
+ return;
103
+ }
104
+#endif
105
+ if (block->fd >= 0) {
106
+ /**
107
+ * Case there is no support for PMEM or the memory has not been
108
+ * specified as persistent (or is not one) - use the msync.
109
+ * Less optimal but still achieves the same goal
110
+ */
111
+ if (qemu_msync(addr, length, block->fd)) {
112
+ warn_report("%s: failed to sync memory range: start: "
113
+ RAM_ADDR_FMT " length: " RAM_ADDR_FMT,
114
+ __func__, start, length);
115
+ }
116
+ }
117
+}
118
+
119
/* Called with ram_list.mutex held */
120
static void dirty_memory_extend(ram_addr_t old_ram_size,
121
ram_addr_t new_ram_size)
122
diff --git a/memory.c b/memory.c
123
index XXXXXXX..XXXXXXX 100644
74
index XXXXXXX..XXXXXXX 100644
124
--- a/memory.c
75
--- a/hw/misc/npcm7xx_rng.c
125
+++ b/memory.c
76
+++ b/hw/misc/npcm7xx_rng.c
126
@@ -XXX,XX +XXX,XX @@ void memory_region_ram_resize(MemoryRegion *mr, ram_addr_t newsize, Error **errp
77
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_rng_init(Object *obj)
127
qemu_ram_resize(mr->ram_block, newsize, errp);
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);
128
}
83
}
129
84
130
+
85
static const VMStateDescription vmstate_npcm7xx_rng = {
131
+void memory_region_do_writeback(MemoryRegion *mr, hwaddr addr, hwaddr size)
86
diff --git a/hw/nvram/npcm7xx_otp.c b/hw/nvram/npcm7xx_otp.c
132
+{
133
+ /*
134
+ * Might be extended case needed to cover
135
+ * different types of memory regions
136
+ */
137
+ if (mr->ram_block && mr->dirty_log_mask) {
138
+ qemu_ram_writeback(mr->ram_block, addr, size);
139
+ }
140
+}
141
+
142
/*
143
* Call proper memory listeners about the change on the newly
144
* added/removed CoalescedMemoryRange.
145
diff --git a/util/cutils.c b/util/cutils.c
146
index XXXXXXX..XXXXXXX 100644
87
index XXXXXXX..XXXXXXX 100644
147
--- a/util/cutils.c
88
--- a/hw/nvram/npcm7xx_otp.c
148
+++ b/util/cutils.c
89
+++ b/hw/nvram/npcm7xx_otp.c
149
@@ -XXX,XX +XXX,XX @@ int qemu_fdatasync(int fd)
90
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_otp_realize(DeviceState *dev, Error **errp)
150
#endif
91
{
151
}
92
NPCM7xxOTPClass *oc = NPCM7XX_OTP_GET_CLASS(dev);
152
93
NPCM7xxOTPState *s = NPCM7XX_OTP(dev);
153
+/**
94
- SysBusDevice *sbd = &s->parent;
154
+ * Sync changes made to the memory mapped file back to the backing
95
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
155
+ * storage. For POSIX compliant systems this will fallback
96
156
+ * to regular msync call. Otherwise it will trigger whole file sync
97
memset(s->array, 0, sizeof(s->array));
157
+ * (including the metadata case there is no support to skip that otherwise)
98
158
+ *
99
diff --git a/hw/ssi/npcm7xx_fiu.c b/hw/ssi/npcm7xx_fiu.c
159
+ * @addr - start of the memory area to be synced
100
index XXXXXXX..XXXXXXX 100644
160
+ * @length - length of the are to be synced
101
--- a/hw/ssi/npcm7xx_fiu.c
161
+ * @fd - file descriptor for the file to be synced
102
+++ b/hw/ssi/npcm7xx_fiu.c
162
+ * (mandatory only for POSIX non-compliant systems)
103
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_fiu_hold_reset(Object *obj)
163
+ */
104
static void npcm7xx_fiu_realize(DeviceState *dev, Error **errp)
164
+int qemu_msync(void *addr, size_t length, int fd)
105
{
165
+{
106
NPCM7xxFIUState *s = NPCM7XX_FIU(dev);
166
+#ifdef CONFIG_POSIX
107
- SysBusDevice *sbd = &s->parent;
167
+ size_t align_mask = ~(qemu_real_host_page_size - 1);
108
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
168
+
109
int i;
169
+ /**
110
170
+ * There are no strict reqs as per the length of mapping
111
if (s->cs_count <= 0) {
171
+ * to be synced. Still the length needs to follow the address
172
+ * alignment changes. Additionally - round the size to the multiple
173
+ * of PAGE_SIZE
174
+ */
175
+ length += ((uintptr_t)addr & (qemu_real_host_page_size - 1));
176
+ length = (length + ~align_mask) & align_mask;
177
+
178
+ addr = (void *)((uintptr_t)addr & align_mask);
179
+
180
+ return msync(addr, length, MS_SYNC);
181
+#else /* CONFIG_POSIX */
182
+ /**
183
+ * Perform the sync based on the file descriptor
184
+ * The sync range will most probably be wider than the one
185
+ * requested - but it will still get the job done
186
+ */
187
+ return qemu_fdatasync(fd);
188
+#endif /* CONFIG_POSIX */
189
+}
190
+
191
#ifndef _WIN32
192
/* Sets a specific flag */
193
int fcntl_setfl(int fd, int flag)
194
--
112
--
195
2.20.1
113
2.20.1
196
114
197
115
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Roman Bolshakov <r.bolshakov@yadro.com>
2
2
3
Make the gic a field in the machine state, and instead of filling
3
ui/cocoa.m:1188:44: warning: 'openFile:' is deprecated: first deprecated in macOS 11.0 - Use -[NSWorkspace openURL:] instead.
4
an array of qemu_irq and passing it around, directly call
4
[-Wdeprecated-declarations]
5
qdev_get_gpio_in() on the gic field.
5
if ([[NSWorkspace sharedWorkspace] openFile: full_file_path] == YES) {
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
^
6
11
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Signed-off-by: Roman Bolshakov <r.bolshakov@yadro.com>
8
Reviewed-by: Luc Michel <luc.michel@greensocs.com>
9
Message-id: 20191209090306.20433-1-philmd@redhat.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20210102150718.47618-1-r.bolshakov@yadro.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
16
---
13
include/hw/arm/virt.h | 1 +
17
ui/cocoa.m | 5 ++++-
14
hw/arm/virt.c | 109 +++++++++++++++++++++---------------------
18
1 file changed, 4 insertions(+), 1 deletion(-)
15
2 files changed, 55 insertions(+), 55 deletions(-)
16
19
17
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
20
diff --git a/ui/cocoa.m b/ui/cocoa.m
18
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/virt.h
22
--- a/ui/cocoa.m
20
+++ b/include/hw/arm/virt.h
23
+++ b/ui/cocoa.m
21
@@ -XXX,XX +XXX,XX @@ typedef struct {
24
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
22
uint32_t iommu_phandle;
25
/* Where to look for local files */
23
int psci_conduit;
26
NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"docs/"};
24
hwaddr highest_gpa;
27
NSString *full_file_path;
25
+ DeviceState *gic;
28
+ NSURL *full_file_url;
26
DeviceState *acpi_dev;
29
27
Notifier powerdown_notifier;
30
/* iterate thru the possible paths until the file is found */
28
} VirtMachineState;
31
int index;
29
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
32
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
30
index XXXXXXX..XXXXXXX 100644
33
full_file_path = [full_file_path stringByDeletingLastPathComponent];
31
--- a/hw/arm/virt.c
34
full_file_path = [NSString stringWithFormat: @"%@/%@%@", full_file_path,
32
+++ b/hw/arm/virt.c
35
path_array[index], filename];
33
@@ -XXX,XX +XXX,XX @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms)
36
- if ([[NSWorkspace sharedWorkspace] openFile: full_file_path] == YES) {
34
}
37
+ full_file_url = [NSURL fileURLWithPath: full_file_path
35
}
38
+ isDirectory: false];
36
39
+ if ([[NSWorkspace sharedWorkspace] openURL: full_file_url] == YES) {
37
-static inline DeviceState *create_acpi_ged(VirtMachineState *vms, qemu_irq *pic)
40
return;
38
+static inline DeviceState *create_acpi_ged(VirtMachineState *vms)
39
{
40
DeviceState *dev;
41
MachineState *ms = MACHINE(vms);
42
@@ -XXX,XX +XXX,XX @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms, qemu_irq *pic)
43
44
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_ACPI_GED].base);
45
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, vms->memmap[VIRT_PCDIMM_ACPI].base);
46
- sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irq]);
47
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(vms->gic, irq));
48
49
qdev_init_nofail(dev);
50
51
return dev;
52
}
53
54
-static void create_its(VirtMachineState *vms, DeviceState *gicdev)
55
+static void create_its(VirtMachineState *vms)
56
{
57
const char *itsclass = its_class_name();
58
DeviceState *dev;
59
@@ -XXX,XX +XXX,XX @@ static void create_its(VirtMachineState *vms, DeviceState *gicdev)
60
61
dev = qdev_create(NULL, itsclass);
62
63
- object_property_set_link(OBJECT(dev), OBJECT(gicdev), "parent-gicv3",
64
+ object_property_set_link(OBJECT(dev), OBJECT(vms->gic), "parent-gicv3",
65
&error_abort);
66
qdev_init_nofail(dev);
67
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_GIC_ITS].base);
68
@@ -XXX,XX +XXX,XX @@ static void create_its(VirtMachineState *vms, DeviceState *gicdev)
69
fdt_add_its_gic_node(vms);
70
}
71
72
-static void create_v2m(VirtMachineState *vms, qemu_irq *pic)
73
+static void create_v2m(VirtMachineState *vms)
74
{
75
int i;
76
int irq = vms->irqmap[VIRT_GIC_V2M];
77
@@ -XXX,XX +XXX,XX @@ static void create_v2m(VirtMachineState *vms, qemu_irq *pic)
78
qdev_init_nofail(dev);
79
80
for (i = 0; i < NUM_GICV2M_SPIS; i++) {
81
- sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]);
82
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
83
+ qdev_get_gpio_in(vms->gic, irq + i));
84
}
85
86
fdt_add_v2m_gic_node(vms);
87
}
88
89
-static void create_gic(VirtMachineState *vms, qemu_irq *pic)
90
+static void create_gic(VirtMachineState *vms)
91
{
92
MachineState *ms = MACHINE(vms);
93
/* We create a standalone GIC */
94
- DeviceState *gicdev;
95
SysBusDevice *gicbusdev;
96
const char *gictype;
97
int type = vms->gic_version, i;
98
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
99
100
gictype = (type == 3) ? gicv3_class_name() : gic_class_name();
101
102
- gicdev = qdev_create(NULL, gictype);
103
- qdev_prop_set_uint32(gicdev, "revision", type);
104
- qdev_prop_set_uint32(gicdev, "num-cpu", smp_cpus);
105
+ vms->gic = qdev_create(NULL, gictype);
106
+ qdev_prop_set_uint32(vms->gic, "revision", type);
107
+ qdev_prop_set_uint32(vms->gic, "num-cpu", smp_cpus);
108
/* Note that the num-irq property counts both internal and external
109
* interrupts; there are always 32 of the former (mandated by GIC spec).
110
*/
111
- qdev_prop_set_uint32(gicdev, "num-irq", NUM_IRQS + 32);
112
+ qdev_prop_set_uint32(vms->gic, "num-irq", NUM_IRQS + 32);
113
if (!kvm_irqchip_in_kernel()) {
114
- qdev_prop_set_bit(gicdev, "has-security-extensions", vms->secure);
115
+ qdev_prop_set_bit(vms->gic, "has-security-extensions", vms->secure);
116
}
117
118
if (type == 3) {
119
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
120
121
nb_redist_regions = virt_gicv3_redist_region_count(vms);
122
123
- qdev_prop_set_uint32(gicdev, "len-redist-region-count",
124
+ qdev_prop_set_uint32(vms->gic, "len-redist-region-count",
125
nb_redist_regions);
126
- qdev_prop_set_uint32(gicdev, "redist-region-count[0]", redist0_count);
127
+ qdev_prop_set_uint32(vms->gic, "redist-region-count[0]", redist0_count);
128
129
if (nb_redist_regions == 2) {
130
uint32_t redist1_capacity =
131
vms->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE;
132
133
- qdev_prop_set_uint32(gicdev, "redist-region-count[1]",
134
+ qdev_prop_set_uint32(vms->gic, "redist-region-count[1]",
135
MIN(smp_cpus - redist0_count, redist1_capacity));
136
}
137
} else {
138
if (!kvm_irqchip_in_kernel()) {
139
- qdev_prop_set_bit(gicdev, "has-virtualization-extensions",
140
+ qdev_prop_set_bit(vms->gic, "has-virtualization-extensions",
141
vms->virt);
142
}
41
}
143
}
42
}
144
- qdev_init_nofail(gicdev);
145
- gicbusdev = SYS_BUS_DEVICE(gicdev);
146
+ qdev_init_nofail(vms->gic);
147
+ gicbusdev = SYS_BUS_DEVICE(vms->gic);
148
sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base);
149
if (type == 3) {
150
sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_REDIST].base);
151
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
152
153
for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
154
qdev_connect_gpio_out(cpudev, irq,
155
- qdev_get_gpio_in(gicdev,
156
+ qdev_get_gpio_in(vms->gic,
157
ppibase + timer_irq[irq]));
158
}
159
160
if (type == 3) {
161
- qemu_irq irq = qdev_get_gpio_in(gicdev,
162
+ qemu_irq irq = qdev_get_gpio_in(vms->gic,
163
ppibase + ARCH_GIC_MAINT_IRQ);
164
qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
165
0, irq);
166
} else if (vms->virt) {
167
- qemu_irq irq = qdev_get_gpio_in(gicdev,
168
+ qemu_irq irq = qdev_get_gpio_in(vms->gic,
169
ppibase + ARCH_GIC_MAINT_IRQ);
170
sysbus_connect_irq(gicbusdev, i + 4 * smp_cpus, irq);
171
}
172
173
qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
174
- qdev_get_gpio_in(gicdev, ppibase
175
+ qdev_get_gpio_in(vms->gic, ppibase
176
+ VIRTUAL_PMU_IRQ));
177
178
sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
179
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
180
qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
181
}
182
183
- for (i = 0; i < NUM_IRQS; i++) {
184
- pic[i] = qdev_get_gpio_in(gicdev, i);
185
- }
186
-
187
fdt_add_gic_node(vms);
188
189
if (type == 3 && vms->its) {
190
- create_its(vms, gicdev);
191
+ create_its(vms);
192
} else if (type == 2) {
193
- create_v2m(vms, pic);
194
+ create_v2m(vms);
195
}
196
}
197
198
-static void create_uart(const VirtMachineState *vms, qemu_irq *pic, int uart,
199
+static void create_uart(const VirtMachineState *vms, int uart,
200
MemoryRegion *mem, Chardev *chr)
201
{
202
char *nodename;
203
@@ -XXX,XX +XXX,XX @@ static void create_uart(const VirtMachineState *vms, qemu_irq *pic, int uart,
204
qdev_init_nofail(dev);
205
memory_region_add_subregion(mem, base,
206
sysbus_mmio_get_region(s, 0));
207
- sysbus_connect_irq(s, 0, pic[irq]);
208
+ sysbus_connect_irq(s, 0, qdev_get_gpio_in(vms->gic, irq));
209
210
nodename = g_strdup_printf("/pl011@%" PRIx64, base);
211
qemu_fdt_add_subnode(vms->fdt, nodename);
212
@@ -XXX,XX +XXX,XX @@ static void create_uart(const VirtMachineState *vms, qemu_irq *pic, int uart,
213
g_free(nodename);
214
}
215
216
-static void create_rtc(const VirtMachineState *vms, qemu_irq *pic)
217
+static void create_rtc(const VirtMachineState *vms)
218
{
219
char *nodename;
220
hwaddr base = vms->memmap[VIRT_RTC].base;
221
@@ -XXX,XX +XXX,XX @@ static void create_rtc(const VirtMachineState *vms, qemu_irq *pic)
222
int irq = vms->irqmap[VIRT_RTC];
223
const char compat[] = "arm,pl031\0arm,primecell";
224
225
- sysbus_create_simple("pl031", base, pic[irq]);
226
+ sysbus_create_simple("pl031", base, qdev_get_gpio_in(vms->gic, irq));
227
228
nodename = g_strdup_printf("/pl031@%" PRIx64, base);
229
qemu_fdt_add_subnode(vms->fdt, nodename);
230
@@ -XXX,XX +XXX,XX @@ static void virt_powerdown_req(Notifier *n, void *opaque)
231
}
232
}
233
234
-static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
235
+static void create_gpio(const VirtMachineState *vms)
236
{
237
char *nodename;
238
DeviceState *pl061_dev;
239
@@ -XXX,XX +XXX,XX @@ static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
240
int irq = vms->irqmap[VIRT_GPIO];
241
const char compat[] = "arm,pl061\0arm,primecell";
242
243
- pl061_dev = sysbus_create_simple("pl061", base, pic[irq]);
244
+ pl061_dev = sysbus_create_simple("pl061", base,
245
+ qdev_get_gpio_in(vms->gic, irq));
246
247
uint32_t phandle = qemu_fdt_alloc_phandle(vms->fdt);
248
nodename = g_strdup_printf("/pl061@%" PRIx64, base);
249
@@ -XXX,XX +XXX,XX @@ static void create_gpio(const VirtMachineState *vms, qemu_irq *pic)
250
g_free(nodename);
251
}
252
253
-static void create_virtio_devices(const VirtMachineState *vms, qemu_irq *pic)
254
+static void create_virtio_devices(const VirtMachineState *vms)
255
{
256
int i;
257
hwaddr size = vms->memmap[VIRT_MMIO].size;
258
@@ -XXX,XX +XXX,XX @@ static void create_virtio_devices(const VirtMachineState *vms, qemu_irq *pic)
259
int irq = vms->irqmap[VIRT_MMIO] + i;
260
hwaddr base = vms->memmap[VIRT_MMIO].base + i * size;
261
262
- sysbus_create_simple("virtio-mmio", base, pic[irq]);
263
+ sysbus_create_simple("virtio-mmio", base,
264
+ qdev_get_gpio_in(vms->gic, irq));
265
}
266
267
/* We add dtb nodes in reverse order so that they appear in the finished
268
@@ -XXX,XX +XXX,XX @@ static void create_pcie_irq_map(const VirtMachineState *vms,
269
0x7 /* PCI irq */);
270
}
271
272
-static void create_smmu(const VirtMachineState *vms, qemu_irq *pic,
273
+static void create_smmu(const VirtMachineState *vms,
274
PCIBus *bus)
275
{
276
char *node;
277
@@ -XXX,XX +XXX,XX @@ static void create_smmu(const VirtMachineState *vms, qemu_irq *pic,
278
qdev_init_nofail(dev);
279
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
280
for (i = 0; i < NUM_SMMU_IRQS; i++) {
281
- sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]);
282
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
283
+ qdev_get_gpio_in(vms->gic, irq + i));
284
}
285
286
node = g_strdup_printf("/smmuv3@%" PRIx64, base);
287
@@ -XXX,XX +XXX,XX @@ static void create_smmu(const VirtMachineState *vms, qemu_irq *pic,
288
g_free(node);
289
}
290
291
-static void create_pcie(VirtMachineState *vms, qemu_irq *pic)
292
+static void create_pcie(VirtMachineState *vms)
293
{
294
hwaddr base_mmio = vms->memmap[VIRT_PCIE_MMIO].base;
295
hwaddr size_mmio = vms->memmap[VIRT_PCIE_MMIO].size;
296
@@ -XXX,XX +XXX,XX @@ static void create_pcie(VirtMachineState *vms, qemu_irq *pic)
297
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, base_pio);
298
299
for (i = 0; i < GPEX_NUM_IRQS; i++) {
300
- sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]);
301
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
302
+ qdev_get_gpio_in(vms->gic, irq + i));
303
gpex_set_irq_num(GPEX_HOST(dev), i, irq + i);
304
}
305
306
@@ -XXX,XX +XXX,XX @@ static void create_pcie(VirtMachineState *vms, qemu_irq *pic)
307
if (vms->iommu) {
308
vms->iommu_phandle = qemu_fdt_alloc_phandle(vms->fdt);
309
310
- create_smmu(vms, pic, pci->bus);
311
+ create_smmu(vms, pci->bus);
312
313
qemu_fdt_setprop_cells(vms->fdt, nodename, "iommu-map",
314
0x0, vms->iommu_phandle, 0x0, 0x10000);
315
@@ -XXX,XX +XXX,XX @@ static void create_pcie(VirtMachineState *vms, qemu_irq *pic)
316
g_free(nodename);
317
}
318
319
-static void create_platform_bus(VirtMachineState *vms, qemu_irq *pic)
320
+static void create_platform_bus(VirtMachineState *vms)
321
{
322
DeviceState *dev;
323
SysBusDevice *s;
324
@@ -XXX,XX +XXX,XX @@ static void create_platform_bus(VirtMachineState *vms, qemu_irq *pic)
325
326
s = SYS_BUS_DEVICE(dev);
327
for (i = 0; i < PLATFORM_BUS_NUM_IRQS; i++) {
328
- int irqn = vms->irqmap[VIRT_PLATFORM_BUS] + i;
329
- sysbus_connect_irq(s, i, pic[irqn]);
330
+ int irq = vms->irqmap[VIRT_PLATFORM_BUS] + i;
331
+ sysbus_connect_irq(s, i, qdev_get_gpio_in(vms->gic, irq));
332
}
333
334
memory_region_add_subregion(sysmem,
335
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
336
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(machine);
337
MachineClass *mc = MACHINE_GET_CLASS(machine);
338
const CPUArchIdList *possible_cpus;
339
- qemu_irq pic[NUM_IRQS];
340
MemoryRegion *sysmem = get_system_memory();
341
MemoryRegion *secure_sysmem = NULL;
342
int n, virt_max_cpus;
343
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
344
345
virt_flash_fdt(vms, sysmem, secure_sysmem ?: sysmem);
346
347
- create_gic(vms, pic);
348
+ create_gic(vms);
349
350
fdt_add_pmu_nodes(vms);
351
352
- create_uart(vms, pic, VIRT_UART, sysmem, serial_hd(0));
353
+ create_uart(vms, VIRT_UART, sysmem, serial_hd(0));
354
355
if (vms->secure) {
356
create_secure_ram(vms, secure_sysmem);
357
- create_uart(vms, pic, VIRT_SECURE_UART, secure_sysmem, serial_hd(1));
358
+ create_uart(vms, VIRT_SECURE_UART, secure_sysmem, serial_hd(1));
359
}
360
361
vms->highmem_ecam &= vms->highmem && (!firmware_loaded || aarch64);
362
363
- create_rtc(vms, pic);
364
+ create_rtc(vms);
365
366
- create_pcie(vms, pic);
367
+ create_pcie(vms);
368
369
if (has_ged && aarch64 && firmware_loaded && acpi_enabled) {
370
- vms->acpi_dev = create_acpi_ged(vms, pic);
371
+ vms->acpi_dev = create_acpi_ged(vms);
372
} else {
373
- create_gpio(vms, pic);
374
+ create_gpio(vms);
375
}
376
377
/* connect powerdown request */
378
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
379
* (which will be automatically plugged in to the transports). If
380
* no backend is created the transport will just sit harmlessly idle.
381
*/
382
- create_virtio_devices(vms, pic);
383
+ create_virtio_devices(vms);
384
385
vms->fw_cfg = create_fw_cfg(vms, &address_space_memory);
386
rom_set_fw(vms->fw_cfg);
387
388
- create_platform_bus(vms, pic);
389
+ create_platform_bus(vms);
390
391
vms->bootinfo.ram_size = machine->ram_size;
392
vms->bootinfo.nb_cpus = smp_cpus;
393
--
43
--
394
2.20.1
44
2.20.1
395
45
396
46
diff view generated by jsdifflib