1
The following changes since commit 7e7eb9f852a46b51a71ae9d82590b2e4d28827ee:
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
Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2021-01-28' into staging (2021-01-28 22:43:18 +0000)
5
thanks
6
-- PMM
7
8
The following changes since commit b3f846c59d8405bb87c551187721fc92ff2f1b92:
9
10
Merge remote-tracking branch 'remotes/huth-gitlab/tags/pull-request-2021-01-11v2' into staging (2021-01-11 15:15:35 +0000)
4
11
5
are available in the Git repository at:
12
are available in the Git repository at:
6
13
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210129
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210112
8
15
9
for you to fetch changes up to 11749122e1a86866591306d43603d2795a3dea1a:
16
for you to fetch changes up to 19d131395ccaf503db21dadd8257e6dc9fc1d7de:
10
17
11
hw/arm/stellaris: Remove board-creation reset of STELLARIS_SYS (2021-01-29 10:47:29 +0000)
18
ui/cocoa: Fix openFile: deprecation on Big Sur (2021-01-12 11:38:37 +0000)
12
19
13
----------------------------------------------------------------
20
----------------------------------------------------------------
14
target-arm queue:
21
target-arm queue:
15
* Implement ID_PFR2
22
* arm: Support emulation of ARMv8.4-TTST extension
16
* Conditionalize DBGDIDR
23
* arm: Update cpu.h ID register field definitions
17
* rename xlnx-zcu102.canbusN properties
24
* arm: Fix breakage of XScale instruction emulation
18
* provide powerdown/reset mechanism for secure firmware on 'virt' board
25
* hw/net/lan9118: Fix RX Status FIFO PEEK value
19
* hw/misc: Fix arith overflow in NPCM7XX PWM module
26
* npcm7xx: Add ADC and PWM emulation
20
* target/arm: Replace magic value by MMU_DATA_LOAD definition
27
* ui/cocoa: Make "open docs" help menu entry work again when binary
21
* configure: fix preadv errors on Catalina macOS with new XCode
28
is run from the build tree
22
* Various configure and other cleanups in preparation for iOS support
29
* ui/cocoa: Fix openFile: deprecation on Big Sur
23
* hvf: Add hypervisor entitlement to output binaries (needed for Big Sur)
30
* docs: Add qemu-storage-daemon(1) manpage to meson.build
24
* Implement pvpanic-pci device
31
* docs: Build and install all the docs in a single manual
25
* Convert the CMSDK timer devices to the Clock framework
26
32
27
----------------------------------------------------------------
33
----------------------------------------------------------------
28
Alexander Graf (1):
34
Hao Wu (6):
29
hvf: Add hypervisor entitlement to output binaries
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
30
41
31
Hao Wu (1):
42
Leif Lindholm (6):
32
hw/misc: Fix arith overflow in NPCM7XX PWM module
43
target/arm: fix typo in cpu.h ID_AA64PFR1 field name
44
target/arm: make ARMCPU.clidr 64-bit
45
target/arm: make ARMCPU.ctr 64-bit
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
33
49
34
Joelle van Dyne (7):
50
Peter Maydell (5):
35
configure: cross-compiling with empty cross_prefix
51
docs: Add qemu-storage-daemon(1) manpage to meson.build
36
osdep: build with non-working system() function
52
docs: Build and install all the docs in a single manual
37
darwin: remove redundant dependency declaration
53
target/arm: Don't decode insns in the XScale/iWMMXt space as cp insns
38
darwin: fix cross-compiling for Darwin
54
hw/net/lan9118: Fix RX Status FIFO PEEK value
39
configure: cross compile should use x86_64 cpu_family
55
hw/net/lan9118: Add symbolic constants for register offsets
40
darwin: detect CoreAudio for build
41
darwin: remove 64-bit build detection on 32-bit OS
42
56
43
Maxim Uvarov (3):
57
Roman Bolshakov (2):
44
hw: gpio: implement gpio-pwr driver for qemu reset/poweroff
58
ui/cocoa: Update path to docs in build tree
45
arm-virt: refactor gpios creation
59
ui/cocoa: Fix openFile: deprecation on Big Sur
46
arm-virt: add secure pl061 for reset/power down
47
60
48
Mihai Carabas (4):
61
Rémi Denis-Courmont (2):
49
hw/misc/pvpanic: split-out generic and bus dependent code
62
target/arm: ARMv8.4-TTST extension
50
hw/misc/pvpanic: add PCI interface support
63
target/arm: enable Small Translation tables in max CPU
51
pvpanic : update pvpanic spec document
52
tests/qtest: add a test case for pvpanic-pci
53
64
54
Paolo Bonzini (1):
65
docs/conf.py | 46 ++-
55
arm: rename xlnx-zcu102.canbusN properties
66
docs/devel/conf.py | 15 -
67
docs/index.html.in | 17 -
68
docs/interop/conf.py | 28 --
69
docs/meson.build | 65 ++--
70
docs/specs/conf.py | 16 -
71
docs/system/arm/nuvoton.rst | 4 +-
72
docs/system/conf.py | 28 --
73
docs/tools/conf.py | 37 --
74
docs/user/conf.py | 15 -
75
meson.build | 1 +
76
hw/adc/trace.h | 1 +
77
include/hw/adc/npcm7xx_adc.h | 69 ++++
78
include/hw/arm/npcm7xx.h | 4 +
79
include/hw/misc/npcm7xx_clk.h | 146 ++++++-
80
include/hw/misc/npcm7xx_pwm.h | 105 +++++
81
include/hw/timer/npcm7xx_timer.h | 1 +
82
target/arm/cpu.h | 85 ++++-
83
hw/adc/npcm7xx_adc.c | 301 +++++++++++++++
84
hw/arm/npcm7xx.c | 55 ++-
85
hw/arm/npcm7xx_boards.c | 2 +-
86
hw/mem/npcm7xx_mc.c | 2 +-
87
hw/misc/npcm7xx_clk.c | 807 ++++++++++++++++++++++++++++++++++++++-
88
hw/misc/npcm7xx_gcr.c | 2 +-
89
hw/misc/npcm7xx_pwm.c | 550 ++++++++++++++++++++++++++
90
hw/misc/npcm7xx_rng.c | 2 +-
91
hw/net/lan9118.c | 26 +-
92
hw/nvram/npcm7xx_otp.c | 2 +-
93
hw/ssi/npcm7xx_fiu.c | 2 +-
94
hw/timer/npcm7xx_timer.c | 39 +-
95
target/arm/cpu64.c | 1 +
96
target/arm/helper.c | 15 +-
97
target/arm/translate.c | 7 +
98
tests/qtest/npcm7xx_adc-test.c | 377 ++++++++++++++++++
99
tests/qtest/npcm7xx_pwm-test.c | 490 ++++++++++++++++++++++++
100
hw/adc/meson.build | 1 +
101
hw/adc/trace-events | 5 +
102
hw/misc/meson.build | 1 +
103
hw/misc/trace-events | 6 +
104
tests/qtest/meson.build | 4 +-
105
ui/cocoa.m | 7 +-
106
41 files changed, 3124 insertions(+), 263 deletions(-)
107
delete mode 100644 docs/devel/conf.py
108
delete mode 100644 docs/index.html.in
109
delete mode 100644 docs/interop/conf.py
110
delete mode 100644 docs/specs/conf.py
111
delete mode 100644 docs/system/conf.py
112
delete mode 100644 docs/tools/conf.py
113
delete mode 100644 docs/user/conf.py
114
create mode 100644 hw/adc/trace.h
115
create mode 100644 include/hw/adc/npcm7xx_adc.h
116
create mode 100644 include/hw/misc/npcm7xx_pwm.h
117
create mode 100644 hw/adc/npcm7xx_adc.c
118
create mode 100644 hw/misc/npcm7xx_pwm.c
119
create mode 100644 tests/qtest/npcm7xx_adc-test.c
120
create mode 100644 tests/qtest/npcm7xx_pwm-test.c
121
create mode 100644 hw/adc/trace-events
56
122
57
Peter Maydell (26):
58
configure: Move preadv check to meson.build
59
ptimer: Add new ptimer_set_period_from_clock() function
60
clock: Add new clock_has_source() function
61
tests: Add a simple test of the CMSDK APB timer
62
tests: Add a simple test of the CMSDK APB watchdog
63
tests: Add a simple test of the CMSDK APB dual timer
64
hw/timer/cmsdk-apb-timer: Rename CMSDKAPBTIMER struct to CMSDKAPBTimer
65
hw/timer/cmsdk-apb-timer: Add Clock input
66
hw/timer/cmsdk-apb-dualtimer: Add Clock input
67
hw/watchdog/cmsdk-apb-watchdog: Add Clock input
68
hw/arm/armsse: Rename "MAINCLK" property to "MAINCLK_FRQ"
69
hw/arm/armsse: Wire up clocks
70
hw/arm/mps2: Inline CMSDK_APB_TIMER creation
71
hw/arm/mps2: Create and connect SYSCLK Clock
72
hw/arm/mps2-tz: Create and connect ARMSSE Clocks
73
hw/arm/musca: Create and connect ARMSSE Clocks
74
hw/arm/stellaris: Convert SSYS to QOM device
75
hw/arm/stellaris: Create Clock input for watchdog
76
hw/timer/cmsdk-apb-timer: Convert to use Clock input
77
hw/timer/cmsdk-apb-dualtimer: Convert to use Clock input
78
hw/watchdog/cmsdk-apb-watchdog: Convert to use Clock input
79
tests/qtest/cmsdk-apb-watchdog-test: Test clock changes
80
hw/arm/armsse: Use Clock to set system_clock_scale
81
arm: Don't set freq properties on CMSDK timer, dualtimer, watchdog, ARMSSE
82
arm: Remove frq properties on CMSDK timer, dualtimer, watchdog, ARMSSE
83
hw/arm/stellaris: Remove board-creation reset of STELLARIS_SYS
84
85
Philippe Mathieu-Daudé (1):
86
target/arm: Replace magic value by MMU_DATA_LOAD definition
87
88
Richard Henderson (2):
89
target/arm: Implement ID_PFR2
90
target/arm: Conditionalize DBGDIDR
91
92
docs/devel/clocks.rst | 16 +++
93
docs/specs/pci-ids.txt | 1 +
94
docs/specs/pvpanic.txt | 13 ++-
95
docs/system/arm/virt.rst | 2 +
96
configure | 78 ++++++++------
97
meson.build | 34 ++++++-
98
include/hw/arm/armsse.h | 14 ++-
99
include/hw/arm/virt.h | 2 +
100
include/hw/clock.h | 15 +++
101
include/hw/misc/pvpanic.h | 24 ++++-
102
include/hw/pci/pci.h | 1 +
103
include/hw/ptimer.h | 22 ++++
104
include/hw/timer/cmsdk-apb-dualtimer.h | 5 +-
105
include/hw/timer/cmsdk-apb-timer.h | 34 ++-----
106
include/hw/watchdog/cmsdk-apb-watchdog.h | 5 +-
107
include/qemu/osdep.h | 12 +++
108
include/qemu/typedefs.h | 1 +
109
target/arm/cpu.h | 1 +
110
hw/arm/armsse.c | 48 ++++++---
111
hw/arm/mps2-tz.c | 14 ++-
112
hw/arm/mps2.c | 28 ++++-
113
hw/arm/musca.c | 13 ++-
114
hw/arm/stellaris.c | 170 +++++++++++++++++++++++--------
115
hw/arm/virt.c | 111 ++++++++++++++++----
116
hw/arm/xlnx-zcu102.c | 4 +-
117
hw/core/ptimer.c | 34 +++++++
118
hw/gpio/gpio_pwr.c | 70 +++++++++++++
119
hw/misc/npcm7xx_pwm.c | 23 ++++-
120
hw/misc/pvpanic-isa.c | 94 +++++++++++++++++
121
hw/misc/pvpanic-pci.c | 94 +++++++++++++++++
122
hw/misc/pvpanic.c | 85 ++--------------
123
hw/timer/cmsdk-apb-dualtimer.c | 53 +++++++---
124
hw/timer/cmsdk-apb-timer.c | 55 +++++-----
125
hw/watchdog/cmsdk-apb-watchdog.c | 29 ++++--
126
target/arm/helper.c | 27 +++--
127
target/arm/kvm64.c | 2 +
128
tests/qtest/cmsdk-apb-dualtimer-test.c | 130 +++++++++++++++++++++++
129
tests/qtest/cmsdk-apb-timer-test.c | 75 ++++++++++++++
130
tests/qtest/cmsdk-apb-watchdog-test.c | 131 ++++++++++++++++++++++++
131
tests/qtest/npcm7xx_pwm-test.c | 4 +-
132
tests/qtest/pvpanic-pci-test.c | 94 +++++++++++++++++
133
tests/qtest/xlnx-can-test.c | 30 +++---
134
MAINTAINERS | 3 +
135
accel/hvf/entitlements.plist | 8 ++
136
hw/arm/Kconfig | 1 +
137
hw/gpio/Kconfig | 3 +
138
hw/gpio/meson.build | 1 +
139
hw/i386/Kconfig | 2 +-
140
hw/misc/Kconfig | 12 ++-
141
hw/misc/meson.build | 4 +-
142
scripts/entitlement.sh | 13 +++
143
tests/qtest/meson.build | 6 +-
144
52 files changed, 1432 insertions(+), 319 deletions(-)
145
create mode 100644 hw/gpio/gpio_pwr.c
146
create mode 100644 hw/misc/pvpanic-isa.c
147
create mode 100644 hw/misc/pvpanic-pci.c
148
create mode 100644 tests/qtest/cmsdk-apb-dualtimer-test.c
149
create mode 100644 tests/qtest/cmsdk-apb-timer-test.c
150
create mode 100644 tests/qtest/cmsdk-apb-watchdog-test.c
151
create mode 100644 tests/qtest/pvpanic-pci-test.c
152
create mode 100644 accel/hvf/entitlements.plist
153
create mode 100755 scripts/entitlement.sh
154
diff view generated by jsdifflib
1
From: Maxim Uvarov <maxim.uvarov@linaro.org>
1
From: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
2
2
3
Add secure pl061 for reset/power down machine from
3
This adds for the Small Translation tables extension in AArch64 state.
4
the secure world (Arm Trusted Firmware). Connect it
5
with gpio-pwr driver.
6
4
7
Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
5
Signed-off-by: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
8
Reviewed-by: Andrew Jones <drjones@redhat.com>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
[PMM: Added mention of the new device to the documentation]
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
8
---
12
docs/system/arm/virt.rst | 2 ++
9
target/arm/cpu.h | 5 +++++
13
include/hw/arm/virt.h | 2 ++
10
target/arm/helper.c | 15 +++++++++++++--
14
hw/arm/virt.c | 56 +++++++++++++++++++++++++++++++++++++++-
11
2 files changed, 18 insertions(+), 2 deletions(-)
15
hw/arm/Kconfig | 1 +
16
4 files changed, 60 insertions(+), 1 deletion(-)
17
12
18
diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
13
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
19
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
20
--- a/docs/system/arm/virt.rst
15
--- a/target/arm/cpu.h
21
+++ b/docs/system/arm/virt.rst
16
+++ b/target/arm/cpu.h
22
@@ -XXX,XX +XXX,XX @@ The virt board supports:
17
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_uao(const ARMISARegisters *id)
23
- Secure-World-only devices if the CPU has TrustZone:
18
return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0;
24
25
- A second PL011 UART
26
+ - A second PL061 GPIO controller, with GPIO lines for triggering
27
+ a system reset or system poweroff
28
- A secure flash memory
29
- 16MB of secure RAM
30
31
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/include/hw/arm/virt.h
34
+++ b/include/hw/arm/virt.h
35
@@ -XXX,XX +XXX,XX @@ enum {
36
VIRT_GPIO,
37
VIRT_SECURE_UART,
38
VIRT_SECURE_MEM,
39
+ VIRT_SECURE_GPIO,
40
VIRT_PCDIMM_ACPI,
41
VIRT_ACPI_GED,
42
VIRT_NVDIMM_ACPI,
43
@@ -XXX,XX +XXX,XX @@ struct VirtMachineClass {
44
bool kvm_no_adjvtime;
45
bool no_kvm_steal_time;
46
bool acpi_expose_flash;
47
+ bool no_secure_gpio;
48
};
49
50
struct VirtMachineState {
51
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/hw/arm/virt.c
54
+++ b/hw/arm/virt.c
55
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry base_memmap[] = {
56
[VIRT_ACPI_GED] = { 0x09080000, ACPI_GED_EVT_SEL_LEN },
57
[VIRT_NVDIMM_ACPI] = { 0x09090000, NVDIMM_ACPI_IO_LEN},
58
[VIRT_PVTIME] = { 0x090a0000, 0x00010000 },
59
+ [VIRT_SECURE_GPIO] = { 0x090b0000, 0x00001000 },
60
[VIRT_MMIO] = { 0x0a000000, 0x00000200 },
61
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
62
[VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 },
63
@@ -XXX,XX +XXX,XX @@ static void create_gpio_keys(const VirtMachineState *vms,
64
"gpios", phandle, 3, 0);
65
}
19
}
66
20
67
+#define SECURE_GPIO_POWEROFF 0
21
+static inline bool isar_feature_aa64_st(const ARMISARegisters *id)
68
+#define SECURE_GPIO_RESET 1
69
+
70
+static void create_secure_gpio_pwr(const VirtMachineState *vms,
71
+ DeviceState *pl061_dev,
72
+ uint32_t phandle)
73
+{
22
+{
74
+ DeviceState *gpio_pwr_dev;
23
+ return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, ST) != 0;
75
+
76
+ /* gpio-pwr */
77
+ gpio_pwr_dev = sysbus_create_simple("gpio-pwr", -1, NULL);
78
+
79
+ /* connect secure pl061 to gpio-pwr */
80
+ qdev_connect_gpio_out(pl061_dev, SECURE_GPIO_RESET,
81
+ qdev_get_gpio_in_named(gpio_pwr_dev, "reset", 0));
82
+ qdev_connect_gpio_out(pl061_dev, SECURE_GPIO_POWEROFF,
83
+ qdev_get_gpio_in_named(gpio_pwr_dev, "shutdown", 0));
84
+
85
+ qemu_fdt_add_subnode(vms->fdt, "/gpio-poweroff");
86
+ qemu_fdt_setprop_string(vms->fdt, "/gpio-poweroff", "compatible",
87
+ "gpio-poweroff");
88
+ qemu_fdt_setprop_cells(vms->fdt, "/gpio-poweroff",
89
+ "gpios", phandle, SECURE_GPIO_POWEROFF, 0);
90
+ qemu_fdt_setprop_string(vms->fdt, "/gpio-poweroff", "status", "disabled");
91
+ qemu_fdt_setprop_string(vms->fdt, "/gpio-poweroff", "secure-status",
92
+ "okay");
93
+
94
+ qemu_fdt_add_subnode(vms->fdt, "/gpio-restart");
95
+ qemu_fdt_setprop_string(vms->fdt, "/gpio-restart", "compatible",
96
+ "gpio-restart");
97
+ qemu_fdt_setprop_cells(vms->fdt, "/gpio-restart",
98
+ "gpios", phandle, SECURE_GPIO_RESET, 0);
99
+ qemu_fdt_setprop_string(vms->fdt, "/gpio-restart", "status", "disabled");
100
+ qemu_fdt_setprop_string(vms->fdt, "/gpio-restart", "secure-status",
101
+ "okay");
102
+}
24
+}
103
+
25
+
104
static void create_gpio_devices(const VirtMachineState *vms, int gpio,
26
static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
105
MemoryRegion *mem)
106
{
27
{
107
@@ -XXX,XX +XXX,XX @@ static void create_gpio_devices(const VirtMachineState *vms, int gpio,
28
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;
108
qemu_fdt_setprop_string(vms->fdt, nodename, "clock-names", "apb_pclk");
29
diff --git a/target/arm/helper.c b/target/arm/helper.c
109
qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", phandle);
30
index XXXXXXX..XXXXXXX 100644
110
31
--- a/target/arm/helper.c
111
+ if (gpio != VIRT_GPIO) {
32
+++ b/target/arm/helper.c
112
+ /* Mark as not usable by the normal world */
33
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
113
+ qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled");
34
{
114
+ qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay");
35
uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
115
+ }
36
bool epd, hpd, using16k, using64k;
116
g_free(nodename);
37
- int select, tsz, tbi;
117
38
+ int select, tsz, tbi, max_tsz;
118
/* Child gpio devices */
39
119
- create_gpio_keys(vms, pl061_dev, phandle);
40
if (!regime_has_2_ranges(mmu_idx)) {
120
+ if (gpio == VIRT_GPIO) {
41
select = 0;
121
+ create_gpio_keys(vms, pl061_dev, phandle);
42
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
43
hpd = extract64(tcr, 42, 1);
44
}
45
}
46
- tsz = MIN(tsz, 39); /* TODO: ARMv8.4-TTST */
47
+
48
+ if (cpu_isar_feature(aa64_st, env_archcpu(env))) {
49
+ max_tsz = 48 - using64k;
122
+ } else {
50
+ } else {
123
+ create_secure_gpio_pwr(vms, pl061_dev, phandle);
51
+ max_tsz = 39;
124
+ }
125
}
126
127
static void create_virtio_devices(const VirtMachineState *vms)
128
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
129
create_gpio_devices(vms, VIRT_GPIO, sysmem);
130
}
131
132
+ if (vms->secure && !vmc->no_secure_gpio) {
133
+ create_gpio_devices(vms, VIRT_SECURE_GPIO, secure_sysmem);
134
+ }
52
+ }
135
+
53
+
136
/* connect powerdown request */
54
+ tsz = MIN(tsz, max_tsz);
137
vms->powerdown_notifier.notify = virt_powerdown_req;
55
tsz = MAX(tsz, 16); /* TODO: ARMv8.2-LVA */
138
qemu_register_powerdown_notifier(&vms->powerdown_notifier);
56
139
@@ -XXX,XX +XXX,XX @@ DEFINE_VIRT_MACHINE_AS_LATEST(6, 0)
57
/* Present TBI as a composite with TBID. */
140
58
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
141
static void virt_machine_5_2_options(MachineClass *mc)
59
if (!aarch64 || stride == 9) {
142
{
60
/* AArch32 or 4KB pages */
143
+ VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
61
startlevel = 2 - sl0;
144
+
62
+
145
virt_machine_6_0_options(mc);
63
+ if (cpu_isar_feature(aa64_st, cpu)) {
146
compat_props_add(mc->compat_props, hw_compat_5_2, hw_compat_5_2_len);
64
+ startlevel &= 3;
147
+ vmc->no_secure_gpio = true;
65
+ }
148
}
66
} else {
149
DEFINE_VIRT_MACHINE(5, 2)
67
/* 16KB or 64KB pages */
150
68
startlevel = 3 - sl0;
151
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
152
index XXXXXXX..XXXXXXX 100644
153
--- a/hw/arm/Kconfig
154
+++ b/hw/arm/Kconfig
155
@@ -XXX,XX +XXX,XX @@ config ARM_VIRT
156
select PL011 # UART
157
select PL031 # RTC
158
select PL061 # GPIO
159
+ select GPIO_PWR
160
select PLATFORM_BUS
161
select SMBIOS
162
select VIRTIO_MMIO
163
--
69
--
164
2.20.1
70
2.20.1
165
71
166
72
diff view generated by jsdifflib
1
From: Joelle van Dyne <j@getutm.app>
1
From: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
2
2
3
Add objc to the Meson cross file as well as detection of Darwin.
3
Signed-off-by: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
4
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Joelle van Dyne <j@getutm.app>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20210126012457.39046-8-j@getutm.app
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
6
---
11
configure | 4 ++++
7
target/arm/cpu64.c | 1 +
12
1 file changed, 4 insertions(+)
8
1 file changed, 1 insertion(+)
13
9
14
diff --git a/configure b/configure
10
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
15
index XXXXXXX..XXXXXXX 100755
11
index XXXXXXX..XXXXXXX 100644
16
--- a/configure
12
--- a/target/arm/cpu64.c
17
+++ b/configure
13
+++ b/target/arm/cpu64.c
18
@@ -XXX,XX +XXX,XX @@ echo "cpp_link_args = [${LDFLAGS:+$(meson_quote $LDFLAGS)}]" >> $cross
14
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
19
echo "[binaries]" >> $cross
15
t = cpu->isar.id_aa64mmfr2;
20
echo "c = [$(meson_quote $cc)]" >> $cross
16
t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1);
21
test -n "$cxx" && echo "cpp = [$(meson_quote $cxx)]" >> $cross
17
t = FIELD_DP64(t, ID_AA64MMFR2, CNP, 1); /* TTCNP */
22
+test -n "$objcc" && echo "objc = [$(meson_quote $objcc)]" >> $cross
18
+ t = FIELD_DP64(t, ID_AA64MMFR2, ST, 1); /* TTST */
23
echo "ar = [$(meson_quote $ar)]" >> $cross
19
cpu->isar.id_aa64mmfr2 = t;
24
echo "nm = [$(meson_quote $nm)]" >> $cross
20
25
echo "pkgconfig = [$(meson_quote $pkg_config_exe)]" >> $cross
21
/* Replicate the same data to the 32-bit id registers. */
26
@@ -XXX,XX +XXX,XX @@ if test "$cross_compile" = "yes"; then
27
if test "$linux" = "yes" ; then
28
echo "system = 'linux'" >> $cross
29
fi
30
+ if test "$darwin" = "yes" ; then
31
+ echo "system = 'darwin'" >> $cross
32
+ fi
33
case "$ARCH" in
34
i386|x86_64)
35
echo "cpu_family = 'x86'" >> $cross
36
--
22
--
37
2.20.1
23
2.20.1
38
24
39
25
diff view generated by jsdifflib
1
From: Mihai Carabas <mihai.carabas@oracle.com>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
Add pvpanic PCI device support details in docs/specs/pvpanic.txt.
3
SBSS -> SSBS
4
4
5
Signed-off-by: Mihai Carabas <mihai.carabas@oracle.com>
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
9
Message-id: 20210108185154.8108-2-leif@nuviainc.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
11
---
9
docs/specs/pvpanic.txt | 13 ++++++++++++-
12
target/arm/cpu.h | 2 +-
10
1 file changed, 12 insertions(+), 1 deletion(-)
13
1 file changed, 1 insertion(+), 1 deletion(-)
11
14
12
diff --git a/docs/specs/pvpanic.txt b/docs/specs/pvpanic.txt
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
14
--- a/docs/specs/pvpanic.txt
17
--- a/target/arm/cpu.h
15
+++ b/docs/specs/pvpanic.txt
18
+++ b/target/arm/cpu.h
16
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64PFR0, RAS, 28, 4)
17
PVPANIC DEVICE
20
FIELD(ID_AA64PFR0, SVE, 32, 4)
18
==============
21
19
22
FIELD(ID_AA64PFR1, BT, 0, 4)
20
-pvpanic device is a simulated ISA device, through which a guest panic
23
-FIELD(ID_AA64PFR1, SBSS, 4, 4)
21
+pvpanic device is a simulated device, through which a guest panic
24
+FIELD(ID_AA64PFR1, SSBS, 4, 4)
22
event is sent to qemu, and a QMP event is generated. This allows
25
FIELD(ID_AA64PFR1, MTE, 8, 4)
23
management apps (e.g. libvirt) to be notified and respond to the event.
26
FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4)
24
25
@@ -XXX,XX +XXX,XX @@ The management app has the option of waiting for GUEST_PANICKED events,
26
and/or polling for guest-panicked RunState, to learn when the pvpanic
27
device has fired a panic event.
28
29
+The pvpanic device can be implemented as an ISA device (using IOPORT) or as a
30
+PCI device.
31
+
32
ISA Interface
33
-------------
34
35
@@ -XXX,XX +XXX,XX @@ bit 1: a guest panic has happened and will be handled by the guest;
36
the host should record it or report it, but should not affect
37
the execution of the guest.
38
39
+PCI Interface
40
+-------------
41
+
42
+The PCI interface is similar to the ISA interface except that it uses an MMIO
43
+address space provided by its BAR0, 1 byte long. Any machine with a PCI bus
44
+can enable a pvpanic device by adding '-device pvpanic-pci' to the command
45
+line.
46
+
47
ACPI Interface
48
--------------
49
27
50
--
28
--
51
2.20.1
29
2.20.1
52
30
53
31
diff view generated by jsdifflib
1
From: Joelle van Dyne <j@getutm.app>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
Meson will find CoreFoundation, IOKit, and Cocoa as needed.
3
The AArch64 view of CLIDR_EL1 extends the ICB field to include also bit
4
32, as well as adding a Ttype<n> field when FEAT_MTE is implemented.
5
Extend the clidr field to be able to hold this context.
4
6
7
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Joelle van Dyne <j@getutm.app>
10
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
7
Message-id: 20210126012457.39046-7-j@getutm.app
11
Message-id: 20210108185154.8108-3-leif@nuviainc.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
13
---
10
configure | 1 -
14
target/arm/cpu.h | 2 +-
11
1 file changed, 1 deletion(-)
15
1 file changed, 1 insertion(+), 1 deletion(-)
12
16
13
diff --git a/configure b/configure
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
index XXXXXXX..XXXXXXX 100755
18
index XXXXXXX..XXXXXXX 100644
15
--- a/configure
19
--- a/target/arm/cpu.h
16
+++ b/configure
20
+++ b/target/arm/cpu.h
17
@@ -XXX,XX +XXX,XX @@ Darwin)
21
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
18
fi
22
uint32_t id_afr0;
19
audio_drv_list="coreaudio try-sdl"
23
uint64_t id_aa64afr0;
20
audio_possible_drivers="coreaudio sdl"
24
uint64_t id_aa64afr1;
21
- QEMU_LDFLAGS="-framework CoreFoundation -framework IOKit $QEMU_LDFLAGS"
25
- uint32_t clidr;
22
# Disable attempts to use ObjectiveC features in os/object.h since they
26
+ uint64_t clidr;
23
# won't work when we're compiling with gcc as a C compiler.
27
uint64_t mp_affinity; /* MP ID without feature bits */
24
QEMU_CFLAGS="-DOS_OBJECT_USE_OBJC=0 $QEMU_CFLAGS"
28
/* The elements of this array are the CCSIDR values for each cache,
29
* in the order L1DCache, L1ICache, L2DCache, L2ICache, etc.
25
--
30
--
26
2.20.1
31
2.20.1
27
32
28
33
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
This was defined at some point before ARMv8.4, and will
3
When FEAT_MTE is implemented, the AArch64 view of CTR_EL0 adds the
4
shortly be used by new processor descriptions.
4
TminLine field in bits [37:32].
5
Extend the ctr field to be able to hold this context.
5
6
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Hao Wu <wuhaotsh@google.com>
8
Message-id: 20210120204400.1056582-1-richard.henderson@linaro.org
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
11
Message-id: 20210108185154.8108-4-leif@nuviainc.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
13
---
11
target/arm/cpu.h | 1 +
14
target/arm/cpu.h | 2 +-
12
target/arm/helper.c | 4 ++--
15
1 file changed, 1 insertion(+), 1 deletion(-)
13
target/arm/kvm64.c | 2 ++
14
3 files changed, 5 insertions(+), 2 deletions(-)
15
16
16
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
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/cpu.h
19
--- a/target/arm/cpu.h
19
+++ b/target/arm/cpu.h
20
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
21
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
21
uint32_t id_mmfr4;
22
uint64_t midr;
22
uint32_t id_pfr0;
23
uint32_t revidr;
23
uint32_t id_pfr1;
24
uint32_t reset_fpsid;
24
+ uint32_t id_pfr2;
25
- uint32_t ctr;
25
uint32_t mvfr0;
26
+ uint64_t ctr;
26
uint32_t mvfr1;
27
uint32_t reset_sctlr;
27
uint32_t mvfr2;
28
uint64_t pmceid0;
28
diff --git a/target/arm/helper.c b/target/arm/helper.c
29
uint64_t pmceid1;
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/helper.c
31
+++ b/target/arm/helper.c
32
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
33
.access = PL1_R, .type = ARM_CP_CONST,
34
.accessfn = access_aa64_tid3,
35
.resetvalue = 0 },
36
- { .name = "MVFR4_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
37
+ { .name = "ID_PFR2", .state = ARM_CP_STATE_BOTH,
38
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 4,
39
.access = PL1_R, .type = ARM_CP_CONST,
40
.accessfn = access_aa64_tid3,
41
- .resetvalue = 0 },
42
+ .resetvalue = cpu->isar.id_pfr2 },
43
{ .name = "MVFR5_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
44
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 5,
45
.access = PL1_R, .type = ARM_CP_CONST,
46
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/kvm64.c
49
+++ b/target/arm/kvm64.c
50
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
51
ARM64_SYS_REG(3, 0, 0, 1, 0));
52
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr1,
53
ARM64_SYS_REG(3, 0, 0, 1, 1));
54
+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr2,
55
+ ARM64_SYS_REG(3, 0, 0, 3, 4));
56
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0,
57
ARM64_SYS_REG(3, 0, 0, 1, 2));
58
err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0,
59
--
30
--
60
2.20.1
31
2.20.1
61
32
62
33
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
Only define the register if it exists for the cpu.
4
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210120031656.737646-1-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
target/arm/helper.c | 21 +++++++++++++++------
11
1 file changed, 15 insertions(+), 6 deletions(-)
12
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.c
16
+++ b/target/arm/helper.c
17
@@ -XXX,XX +XXX,XX @@ static void define_debug_regs(ARMCPU *cpu)
18
*/
19
int i;
20
int wrps, brps, ctx_cmps;
21
- ARMCPRegInfo dbgdidr = {
22
- .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 0,
23
- .access = PL0_R, .accessfn = access_tda,
24
- .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdidr,
25
- };
26
+
27
+ /*
28
+ * The Arm ARM says DBGDIDR is optional and deprecated if EL1 cannot
29
+ * use AArch32. Given that bit 15 is RES1, if the value is 0 then
30
+ * the register must not exist for this cpu.
31
+ */
32
+ if (cpu->isar.dbgdidr != 0) {
33
+ ARMCPRegInfo dbgdidr = {
34
+ .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0,
35
+ .opc1 = 0, .opc2 = 0,
36
+ .access = PL0_R, .accessfn = access_tda,
37
+ .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdidr,
38
+ };
39
+ define_one_arm_cp_reg(cpu, &dbgdidr);
40
+ }
41
42
/* Note that all these register fields hold "number of Xs minus 1". */
43
brps = arm_num_brps(cpu);
44
@@ -XXX,XX +XXX,XX @@ static void define_debug_regs(ARMCPU *cpu)
45
46
assert(ctx_cmps <= brps);
47
48
- define_one_arm_cp_reg(cpu, &dbgdidr);
49
define_arm_cp_regs(cpu, debug_cp_reginfo);
50
51
if (arm_feature(&cpu->env, ARM_FEATURE_LPAE)) {
52
--
53
2.20.1
54
55
diff view generated by jsdifflib
Deleted patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
1
3
The properties to attach a CANBUS object to the xlnx-zcu102 machine have
4
a period in them. We want to use periods in properties for compound QAPI types,
5
and besides the "xlnx-zcu102." prefix is both unnecessary and different
6
from any other machine property name. Remove it.
7
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
Message-id: 20210118162537.779542-1-pbonzini@redhat.com
10
Reviewed-by: Vikram Garhwal <fnu.vikram@xilinx.com>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/arm/xlnx-zcu102.c | 4 ++--
14
tests/qtest/xlnx-can-test.c | 30 +++++++++++++++---------------
15
2 files changed, 17 insertions(+), 17 deletions(-)
16
17
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/xlnx-zcu102.c
20
+++ b/hw/arm/xlnx-zcu102.c
21
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_machine_instance_init(Object *obj)
22
s->secure = false;
23
/* Default to virt (EL2) being disabled */
24
s->virt = false;
25
- object_property_add_link(obj, "xlnx-zcu102.canbus0", TYPE_CAN_BUS,
26
+ object_property_add_link(obj, "canbus0", TYPE_CAN_BUS,
27
(Object **)&s->canbus[0],
28
object_property_allow_set_link,
29
0);
30
31
- object_property_add_link(obj, "xlnx-zcu102.canbus1", TYPE_CAN_BUS,
32
+ object_property_add_link(obj, "canbus1", TYPE_CAN_BUS,
33
(Object **)&s->canbus[1],
34
object_property_allow_set_link,
35
0);
36
diff --git a/tests/qtest/xlnx-can-test.c b/tests/qtest/xlnx-can-test.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/tests/qtest/xlnx-can-test.c
39
+++ b/tests/qtest/xlnx-can-test.c
40
@@ -XXX,XX +XXX,XX @@ static void test_can_bus(void)
41
uint8_t can_timestamp = 1;
42
43
QTestState *qts = qtest_init("-machine xlnx-zcu102"
44
- " -object can-bus,id=canbus0"
45
- " -machine xlnx-zcu102.canbus0=canbus0"
46
- " -machine xlnx-zcu102.canbus1=canbus0"
47
+ " -object can-bus,id=canbus"
48
+ " -machine canbus0=canbus"
49
+ " -machine canbus1=canbus"
50
);
51
52
/* Configure the CAN0 and CAN1. */
53
@@ -XXX,XX +XXX,XX @@ static void test_can_loopback(void)
54
uint32_t status = 0;
55
56
QTestState *qts = qtest_init("-machine xlnx-zcu102"
57
- " -object can-bus,id=canbus0"
58
- " -machine xlnx-zcu102.canbus0=canbus0"
59
- " -machine xlnx-zcu102.canbus1=canbus0"
60
+ " -object can-bus,id=canbus"
61
+ " -machine canbus0=canbus"
62
+ " -machine canbus1=canbus"
63
);
64
65
/* Configure the CAN0 in loopback mode. */
66
@@ -XXX,XX +XXX,XX @@ static void test_can_filter(void)
67
uint8_t can_timestamp = 1;
68
69
QTestState *qts = qtest_init("-machine xlnx-zcu102"
70
- " -object can-bus,id=canbus0"
71
- " -machine xlnx-zcu102.canbus0=canbus0"
72
- " -machine xlnx-zcu102.canbus1=canbus0"
73
+ " -object can-bus,id=canbus"
74
+ " -machine canbus0=canbus"
75
+ " -machine canbus1=canbus"
76
);
77
78
/* Configure the CAN0 and CAN1. */
79
@@ -XXX,XX +XXX,XX @@ static void test_can_sleepmode(void)
80
uint8_t can_timestamp = 1;
81
82
QTestState *qts = qtest_init("-machine xlnx-zcu102"
83
- " -object can-bus,id=canbus0"
84
- " -machine xlnx-zcu102.canbus0=canbus0"
85
- " -machine xlnx-zcu102.canbus1=canbus0"
86
+ " -object can-bus,id=canbus"
87
+ " -machine canbus0=canbus"
88
+ " -machine canbus1=canbus"
89
);
90
91
/* Configure the CAN0. */
92
@@ -XXX,XX +XXX,XX @@ static void test_can_snoopmode(void)
93
uint8_t can_timestamp = 1;
94
95
QTestState *qts = qtest_init("-machine xlnx-zcu102"
96
- " -object can-bus,id=canbus0"
97
- " -machine xlnx-zcu102.canbus0=canbus0"
98
- " -machine xlnx-zcu102.canbus1=canbus0"
99
+ " -object can-bus,id=canbus"
100
+ " -machine canbus0=canbus"
101
+ " -machine canbus1=canbus"
102
);
103
104
/* Configure the CAN0. */
105
--
106
2.20.1
107
108
diff view generated by jsdifflib
Deleted patch
1
From: Maxim Uvarov <maxim.uvarov@linaro.org>
2
1
3
Implement gpio-pwr driver to allow reboot and poweroff machine.
4
This is simple driver with just 2 gpios lines. Current use case
5
is to reboot and poweroff virt machine in secure mode. Secure
6
pl066 gpio chip is needed for that.
7
8
Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
9
Reviewed-by: Hao Wu <wuhaotsh@google.com>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/gpio/gpio_pwr.c | 70 +++++++++++++++++++++++++++++++++++++++++++++
14
hw/gpio/Kconfig | 3 ++
15
hw/gpio/meson.build | 1 +
16
3 files changed, 74 insertions(+)
17
create mode 100644 hw/gpio/gpio_pwr.c
18
19
diff --git a/hw/gpio/gpio_pwr.c b/hw/gpio/gpio_pwr.c
20
new file mode 100644
21
index XXXXXXX..XXXXXXX
22
--- /dev/null
23
+++ b/hw/gpio/gpio_pwr.c
24
@@ -XXX,XX +XXX,XX @@
25
+/*
26
+ * GPIO qemu power controller
27
+ *
28
+ * Copyright (c) 2020 Linaro Limited
29
+ *
30
+ * Author: Maxim Uvarov <maxim.uvarov@linaro.org>
31
+ *
32
+ * Virtual gpio driver which can be used on top of pl061
33
+ * to reboot and shutdown qemu virtual machine. One of use
34
+ * case is gpio driver for secure world application (ARM
35
+ * Trusted Firmware.).
36
+ *
37
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
38
+ * See the COPYING file in the top-level directory.
39
+ * SPDX-License-Identifier: GPL-2.0-or-later
40
+ */
41
+
42
+/*
43
+ * QEMU interface:
44
+ * two named input GPIO lines:
45
+ * 'reset' : when asserted, trigger system reset
46
+ * 'shutdown' : when asserted, trigger system shutdown
47
+ */
48
+
49
+#include "qemu/osdep.h"
50
+#include "hw/sysbus.h"
51
+#include "sysemu/runstate.h"
52
+
53
+#define TYPE_GPIOPWR "gpio-pwr"
54
+OBJECT_DECLARE_SIMPLE_TYPE(GPIO_PWR_State, GPIOPWR)
55
+
56
+struct GPIO_PWR_State {
57
+ SysBusDevice parent_obj;
58
+};
59
+
60
+static void gpio_pwr_reset(void *opaque, int n, int level)
61
+{
62
+ if (level) {
63
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
64
+ }
65
+}
66
+
67
+static void gpio_pwr_shutdown(void *opaque, int n, int level)
68
+{
69
+ if (level) {
70
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
71
+ }
72
+}
73
+
74
+static void gpio_pwr_init(Object *obj)
75
+{
76
+ DeviceState *dev = DEVICE(obj);
77
+
78
+ qdev_init_gpio_in_named(dev, gpio_pwr_reset, "reset", 1);
79
+ qdev_init_gpio_in_named(dev, gpio_pwr_shutdown, "shutdown", 1);
80
+}
81
+
82
+static const TypeInfo gpio_pwr_info = {
83
+ .name = TYPE_GPIOPWR,
84
+ .parent = TYPE_SYS_BUS_DEVICE,
85
+ .instance_size = sizeof(GPIO_PWR_State),
86
+ .instance_init = gpio_pwr_init,
87
+};
88
+
89
+static void gpio_pwr_register_types(void)
90
+{
91
+ type_register_static(&gpio_pwr_info);
92
+}
93
+
94
+type_init(gpio_pwr_register_types)
95
diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
96
index XXXXXXX..XXXXXXX 100644
97
--- a/hw/gpio/Kconfig
98
+++ b/hw/gpio/Kconfig
99
@@ -XXX,XX +XXX,XX @@ config PL061
100
config GPIO_KEY
101
bool
102
103
+config GPIO_PWR
104
+ bool
105
+
106
config SIFIVE_GPIO
107
bool
108
diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
109
index XXXXXXX..XXXXXXX 100644
110
--- a/hw/gpio/meson.build
111
+++ b/hw/gpio/meson.build
112
@@ -XXX,XX +XXX,XX @@
113
softmmu_ss.add(when: 'CONFIG_E500', if_true: files('mpc8xxx.c'))
114
softmmu_ss.add(when: 'CONFIG_GPIO_KEY', if_true: files('gpio_key.c'))
115
+softmmu_ss.add(when: 'CONFIG_GPIO_PWR', if_true: files('gpio_pwr.c'))
116
softmmu_ss.add(when: 'CONFIG_MAX7310', if_true: files('max7310.c'))
117
softmmu_ss.add(when: 'CONFIG_PL061', if_true: files('pl061.c'))
118
softmmu_ss.add(when: 'CONFIG_PUV3', if_true: files('puv3_gpio.c'))
119
--
120
2.20.1
121
122
diff view generated by jsdifflib
1
From: Joelle van Dyne <j@getutm.app>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
Build without error on hosts without a working system(). If system()
3
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
4
is called, return -1 with ENOSYS.
4
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
5
5
Message-id: 20210108185154.8108-5-leif@nuviainc.com
6
Signed-off-by: Joelle van Dyne <j@getutm.app>
7
Message-id: 20210126012457.39046-6-j@getutm.app
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
7
---
11
meson.build | 1 +
8
target/arm/cpu.h | 31 +++++++++++++++++++++++++++++++
12
include/qemu/osdep.h | 12 ++++++++++++
9
1 file changed, 31 insertions(+)
13
2 files changed, 13 insertions(+)
14
10
15
diff --git a/meson.build b/meson.build
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/meson.build
13
--- a/target/arm/cpu.h
18
+++ b/meson.build
14
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@ config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
15
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_FPCCR, ASPEN, 31, 1)
20
config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
16
/*
21
config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
17
* System register ID fields.
22
config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
18
*/
23
+config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include <stdlib.h>'))
19
+FIELD(CLIDR_EL1, CTYPE1, 0, 3)
24
20
+FIELD(CLIDR_EL1, CTYPE2, 3, 3)
25
config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
21
+FIELD(CLIDR_EL1, CTYPE3, 6, 3)
26
22
+FIELD(CLIDR_EL1, CTYPE4, 9, 3)
27
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
23
+FIELD(CLIDR_EL1, CTYPE5, 12, 3)
28
index XXXXXXX..XXXXXXX 100644
24
+FIELD(CLIDR_EL1, CTYPE6, 15, 3)
29
--- a/include/qemu/osdep.h
25
+FIELD(CLIDR_EL1, CTYPE7, 18, 3)
30
+++ b/include/qemu/osdep.h
26
+FIELD(CLIDR_EL1, LOUIS, 21, 3)
31
@@ -XXX,XX +XXX,XX @@ static inline void qemu_thread_jit_write(void) {}
27
+FIELD(CLIDR_EL1, LOC, 24, 3)
32
static inline void qemu_thread_jit_execute(void) {}
28
+FIELD(CLIDR_EL1, LOUU, 27, 3)
33
#endif
29
+FIELD(CLIDR_EL1, ICB, 30, 3)
34
35
+/**
36
+ * Platforms which do not support system() return ENOSYS
37
+ */
38
+#ifndef HAVE_SYSTEM_FUNCTION
39
+#define system platform_does_not_support_system
40
+static inline int platform_does_not_support_system(const char *command)
41
+{
42
+ errno = ENOSYS;
43
+ return -1;
44
+}
45
+#endif /* !HAVE_SYSTEM_FUNCTION */
46
+
30
+
47
#endif
31
+/* When FEAT_CCIDX is implemented */
32
+FIELD(CCSIDR_EL1, CCIDX_LINESIZE, 0, 3)
33
+FIELD(CCSIDR_EL1, CCIDX_ASSOCIATIVITY, 3, 21)
34
+FIELD(CCSIDR_EL1, CCIDX_NUMSETS, 32, 24)
35
+
36
+/* When FEAT_CCIDX is not implemented */
37
+FIELD(CCSIDR_EL1, LINESIZE, 0, 3)
38
+FIELD(CCSIDR_EL1, ASSOCIATIVITY, 3, 10)
39
+FIELD(CCSIDR_EL1, NUMSETS, 13, 15)
40
+
41
+FIELD(CTR_EL0, IMINLINE, 0, 4)
42
+FIELD(CTR_EL0, L1IP, 14, 2)
43
+FIELD(CTR_EL0, DMINLINE, 16, 4)
44
+FIELD(CTR_EL0, ERG, 20, 4)
45
+FIELD(CTR_EL0, CWG, 24, 4)
46
+FIELD(CTR_EL0, IDC, 28, 1)
47
+FIELD(CTR_EL0, DIC, 29, 1)
48
+FIELD(CTR_EL0, TMINLINE, 32, 6)
49
+
50
FIELD(MIDR_EL1, REVISION, 0, 4)
51
FIELD(MIDR_EL1, PARTNUM, 4, 12)
52
FIELD(MIDR_EL1, ARCHITECTURE, 16, 4)
48
--
53
--
49
2.20.1
54
2.20.1
50
55
51
56
diff view generated by jsdifflib
1
From: Joelle van Dyne <j@getutm.app>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
The iOS toolchain does not use the host prefix naming convention. So we
3
Add entries present in ARM DDI 0487F.c (August 2020).
4
need to enable cross-compile options while allowing the PREFIX to be
5
blank.
6
4
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
8
Signed-off-by: Joelle van Dyne <j@getutm.app>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20210126012457.39046-3-j@getutm.app
7
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
8
Message-id: 20210108185154.8108-6-leif@nuviainc.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
configure | 6 ++++--
11
target/arm/cpu.h | 15 +++++++++++++++
13
1 file changed, 4 insertions(+), 2 deletions(-)
12
1 file changed, 15 insertions(+)
14
13
15
diff --git a/configure b/configure
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
index XXXXXXX..XXXXXXX 100755
15
index XXXXXXX..XXXXXXX 100644
17
--- a/configure
16
--- a/target/arm/cpu.h
18
+++ b/configure
17
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@ cpu=""
18
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64ISAR1, GPI, 28, 4)
20
iasl="iasl"
19
FIELD(ID_AA64ISAR1, FRINTTS, 32, 4)
21
interp_prefix="/usr/gnemul/qemu-%M"
20
FIELD(ID_AA64ISAR1, SB, 36, 4)
22
static="no"
21
FIELD(ID_AA64ISAR1, SPECRES, 40, 4)
23
+cross_compile="no"
22
+FIELD(ID_AA64ISAR1, BF16, 44, 4)
24
cross_prefix=""
23
+FIELD(ID_AA64ISAR1, DGH, 48, 4)
25
audio_drv_list=""
24
+FIELD(ID_AA64ISAR1, I8MM, 52, 4)
26
block_drv_rw_whitelist=""
25
27
@@ -XXX,XX +XXX,XX @@ for opt do
26
FIELD(ID_AA64PFR0, EL0, 0, 4)
28
optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)')
27
FIELD(ID_AA64PFR0, EL1, 4, 4)
29
case "$opt" in
28
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64PFR0, ADVSIMD, 20, 4)
30
--cross-prefix=*) cross_prefix="$optarg"
29
FIELD(ID_AA64PFR0, GIC, 24, 4)
31
+ cross_compile="yes"
30
FIELD(ID_AA64PFR0, RAS, 28, 4)
32
;;
31
FIELD(ID_AA64PFR0, SVE, 32, 4)
33
--cc=*) CC="$optarg"
32
+FIELD(ID_AA64PFR0, SEL2, 36, 4)
34
;;
33
+FIELD(ID_AA64PFR0, MPAM, 40, 4)
35
@@ -XXX,XX +XXX,XX @@ $(echo Deprecated targets: $deprecated_targets_list | \
34
+FIELD(ID_AA64PFR0, AMU, 44, 4)
36
--target-list-exclude=LIST exclude a set of targets from the default target-list
35
+FIELD(ID_AA64PFR0, DIT, 48, 4)
37
36
+FIELD(ID_AA64PFR0, CSV2, 56, 4)
38
Advanced options (experts only):
37
+FIELD(ID_AA64PFR0, CSV3, 60, 4)
39
- --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]
38
40
+ --cross-prefix=PREFIX use PREFIX for compile tools, PREFIX can be blank [$cross_prefix]
39
FIELD(ID_AA64PFR1, BT, 0, 4)
41
--cc=CC use C compiler CC [$cc]
40
FIELD(ID_AA64PFR1, SSBS, 4, 4)
42
--iasl=IASL use ACPI compiler IASL [$iasl]
41
FIELD(ID_AA64PFR1, MTE, 8, 4)
43
--host-cc=CC use C compiler CC [$host_cc] for code run at
42
FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4)
44
@@ -XXX,XX +XXX,XX @@ if has $sdl2_config; then
43
+FIELD(ID_AA64PFR1, MPAM_FRAC, 16, 4)
45
fi
44
46
echo "strip = [$(meson_quote $strip)]" >> $cross
45
FIELD(ID_AA64MMFR0, PARANGE, 0, 4)
47
echo "windres = [$(meson_quote $windres)]" >> $cross
46
FIELD(ID_AA64MMFR0, ASIDBITS, 4, 4)
48
-if test -n "$cross_prefix"; then
47
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64MMFR0, TGRAN16_2, 32, 4)
49
+if test "$cross_compile" = "yes"; then
48
FIELD(ID_AA64MMFR0, TGRAN64_2, 36, 4)
50
cross_arg="--cross-file config-meson.cross"
49
FIELD(ID_AA64MMFR0, TGRAN4_2, 40, 4)
51
echo "[host_machine]" >> $cross
50
FIELD(ID_AA64MMFR0, EXS, 44, 4)
52
if test "$mingw32" = "yes" ; then
51
+FIELD(ID_AA64MMFR0, FGT, 56, 4)
52
+FIELD(ID_AA64MMFR0, ECV, 60, 4)
53
54
FIELD(ID_AA64MMFR1, HAFDBS, 0, 4)
55
FIELD(ID_AA64MMFR1, VMIDBITS, 4, 4)
56
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64MMFR1, LO, 16, 4)
57
FIELD(ID_AA64MMFR1, PAN, 20, 4)
58
FIELD(ID_AA64MMFR1, SPECSEI, 24, 4)
59
FIELD(ID_AA64MMFR1, XNX, 28, 4)
60
+FIELD(ID_AA64MMFR1, TWED, 32, 4)
61
+FIELD(ID_AA64MMFR1, ETS, 36, 4)
62
63
FIELD(ID_AA64MMFR2, CNP, 0, 4)
64
FIELD(ID_AA64MMFR2, UAO, 4, 4)
65
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64DFR0, CTX_CMPS, 28, 4)
66
FIELD(ID_AA64DFR0, PMSVER, 32, 4)
67
FIELD(ID_AA64DFR0, DOUBLELOCK, 36, 4)
68
FIELD(ID_AA64DFR0, TRACEFILT, 40, 4)
69
+FIELD(ID_AA64DFR0, MTPMU, 48, 4)
70
71
FIELD(ID_DFR0, COPDBG, 0, 4)
72
FIELD(ID_DFR0, COPSDBG, 4, 4)
53
--
73
--
54
2.20.1
74
2.20.1
55
75
56
76
diff view generated by jsdifflib
1
From: Maxim Uvarov <maxim.uvarov@linaro.org>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
No functional change. Just refactor code to better
3
Add entries present in ARM DDI 0487F.c (August 2020).
4
support secure and normal world gpios.
5
4
6
Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
7
Reviewed-by: Andrew Jones <drjones@redhat.com>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
8
Message-id: 20210108185154.8108-7-leif@nuviainc.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
hw/arm/virt.c | 57 ++++++++++++++++++++++++++++++++-------------------
11
target/arm/cpu.h | 28 ++++++++++++++++++++++++++++
11
1 file changed, 36 insertions(+), 21 deletions(-)
12
1 file changed, 28 insertions(+)
12
13
13
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/virt.c
16
--- a/target/arm/cpu.h
16
+++ b/hw/arm/virt.c
17
+++ b/target/arm/cpu.h
17
@@ -XXX,XX +XXX,XX @@ static void virt_powerdown_req(Notifier *n, void *opaque)
18
@@ -XXX,XX +XXX,XX @@ FIELD(ID_ISAR6, DP, 4, 4)
18
}
19
FIELD(ID_ISAR6, FHM, 8, 4)
19
}
20
FIELD(ID_ISAR6, SB, 12, 4)
20
21
FIELD(ID_ISAR6, SPECRES, 16, 4)
21
-static void create_gpio(const VirtMachineState *vms)
22
+FIELD(ID_ISAR6, BF16, 20, 4)
22
+static void create_gpio_keys(const VirtMachineState *vms,
23
+FIELD(ID_ISAR6, I8MM, 24, 4)
23
+ DeviceState *pl061_dev,
24
24
+ uint32_t phandle)
25
FIELD(ID_MMFR0, VMSA, 0, 4)
25
+{
26
FIELD(ID_MMFR0, PMSA, 4, 4)
26
+ gpio_key_dev = sysbus_create_simple("gpio-key", -1,
27
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR0, AUXREG, 20, 4)
27
+ qdev_get_gpio_in(pl061_dev, 3));
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
+ qemu_fdt_add_subnode(vms->fdt, "/gpio-keys");
40
+FIELD(ID_MMFR2, L1HVDFG, 0, 4)
30
+ qemu_fdt_setprop_string(vms->fdt, "/gpio-keys", "compatible", "gpio-keys");
41
+FIELD(ID_MMFR2, L1HVDBG, 4, 4)
31
+ qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#size-cells", 0);
42
+FIELD(ID_MMFR2, L1HVDRNG, 8, 4)
32
+ qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#address-cells", 1);
43
+FIELD(ID_MMFR2, HVDTLB, 12, 4)
44
+FIELD(ID_MMFR2, UNITLB, 16, 4)
45
+FIELD(ID_MMFR2, MEMBARR, 20, 4)
46
+FIELD(ID_MMFR2, WFISTALL, 24, 4)
47
+FIELD(ID_MMFR2, HWACCFLG, 28, 4)
33
+
48
+
34
+ qemu_fdt_add_subnode(vms->fdt, "/gpio-keys/poweroff");
49
FIELD(ID_MMFR3, CMAINTVA, 0, 4)
35
+ qemu_fdt_setprop_string(vms->fdt, "/gpio-keys/poweroff",
50
FIELD(ID_MMFR3, CMAINTSW, 4, 4)
36
+ "label", "GPIO Key Poweroff");
51
FIELD(ID_MMFR3, BPMAINT, 8, 4)
37
+ qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys/poweroff", "linux,code",
52
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR4, LSM, 20, 4)
38
+ KEY_POWER);
53
FIELD(ID_MMFR4, CCIDX, 24, 4)
39
+ qemu_fdt_setprop_cells(vms->fdt, "/gpio-keys/poweroff",
54
FIELD(ID_MMFR4, EVT, 28, 4)
40
+ "gpios", phandle, 3, 0);
55
41
+}
56
+FIELD(ID_MMFR5, ETS, 0, 4)
42
+
57
+
43
+static void create_gpio_devices(const VirtMachineState *vms, int gpio,
58
FIELD(ID_PFR0, STATE0, 0, 4)
44
+ MemoryRegion *mem)
59
FIELD(ID_PFR0, STATE1, 4, 4)
45
{
60
FIELD(ID_PFR0, STATE2, 8, 4)
46
char *nodename;
61
@@ -XXX,XX +XXX,XX @@ FIELD(ID_PFR1, SEC_FRAC, 20, 4)
47
DeviceState *pl061_dev;
62
FIELD(ID_PFR1, VIRT_FRAC, 24, 4)
48
- hwaddr base = vms->memmap[VIRT_GPIO].base;
63
FIELD(ID_PFR1, GIC, 28, 4)
49
- hwaddr size = vms->memmap[VIRT_GPIO].size;
64
50
- int irq = vms->irqmap[VIRT_GPIO];
65
+FIELD(ID_PFR2, CSV3, 0, 4)
51
+ hwaddr base = vms->memmap[gpio].base;
66
+FIELD(ID_PFR2, SSBS, 4, 4)
52
+ hwaddr size = vms->memmap[gpio].size;
67
+FIELD(ID_PFR2, RAS_FRAC, 8, 4)
53
+ int irq = vms->irqmap[gpio];
54
const char compat[] = "arm,pl061\0arm,primecell";
55
+ SysBusDevice *s;
56
57
- pl061_dev = sysbus_create_simple("pl061", base,
58
- qdev_get_gpio_in(vms->gic, irq));
59
+ pl061_dev = qdev_new("pl061");
60
+ s = SYS_BUS_DEVICE(pl061_dev);
61
+ sysbus_realize_and_unref(s, &error_fatal);
62
+ memory_region_add_subregion(mem, base, sysbus_mmio_get_region(s, 0));
63
+ sysbus_connect_irq(s, 0, qdev_get_gpio_in(vms->gic, irq));
64
65
uint32_t phandle = qemu_fdt_alloc_phandle(vms->fdt);
66
nodename = g_strdup_printf("/pl061@%" PRIx64, base);
67
@@ -XXX,XX +XXX,XX @@ static void create_gpio(const VirtMachineState *vms)
68
qemu_fdt_setprop_string(vms->fdt, nodename, "clock-names", "apb_pclk");
69
qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", phandle);
70
71
- gpio_key_dev = sysbus_create_simple("gpio-key", -1,
72
- qdev_get_gpio_in(pl061_dev, 3));
73
- qemu_fdt_add_subnode(vms->fdt, "/gpio-keys");
74
- qemu_fdt_setprop_string(vms->fdt, "/gpio-keys", "compatible", "gpio-keys");
75
- qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#size-cells", 0);
76
- qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#address-cells", 1);
77
-
78
- qemu_fdt_add_subnode(vms->fdt, "/gpio-keys/poweroff");
79
- qemu_fdt_setprop_string(vms->fdt, "/gpio-keys/poweroff",
80
- "label", "GPIO Key Poweroff");
81
- qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys/poweroff", "linux,code",
82
- KEY_POWER);
83
- qemu_fdt_setprop_cells(vms->fdt, "/gpio-keys/poweroff",
84
- "gpios", phandle, 3, 0);
85
g_free(nodename);
86
+
68
+
87
+ /* Child gpio devices */
69
FIELD(ID_AA64ISAR0, AES, 4, 4)
88
+ create_gpio_keys(vms, pl061_dev, phandle);
70
FIELD(ID_AA64ISAR0, SHA1, 8, 4)
89
}
71
FIELD(ID_AA64ISAR0, SHA2, 12, 4)
90
72
@@ -XXX,XX +XXX,XX @@ FIELD(ID_DFR0, MPROFDBG, 20, 4)
91
static void create_virtio_devices(const VirtMachineState *vms)
73
FIELD(ID_DFR0, PERFMON, 24, 4)
92
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
74
FIELD(ID_DFR0, TRACEFILT, 28, 4)
93
if (has_ged && aarch64 && firmware_loaded && virt_is_acpi_enabled(vms)) {
75
94
vms->acpi_dev = create_acpi_ged(vms);
76
+FIELD(ID_DFR1, MTPMU, 0, 4)
95
} else {
77
+
96
- create_gpio(vms);
78
FIELD(DBGDIDR, SE_IMP, 12, 1)
97
+ create_gpio_devices(vms, VIRT_GPIO, sysmem);
79
FIELD(DBGDIDR, NSUHD_IMP, 14, 1)
98
}
80
FIELD(DBGDIDR, VERSION, 16, 4)
99
100
/* connect powerdown request */
101
--
81
--
102
2.20.1
82
2.20.1
103
83
104
84
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Roman Bolshakov <r.bolshakov@yadro.com>
2
2
3
cpu_get_phys_page_debug() uses 'DATA LOAD' MMU access type.
3
QEMU documentation can't be opened if QEMU is run from build tree
4
because executables are placed in the top of build tree after conversion
5
to meson.
4
6
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Signed-off-by: Roman Bolshakov <r.bolshakov@yadro.com>
6
Message-id: 20210127232822.3530782-1-f4bug@amsat.org
8
Reported-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20210108213815.64678-1-r.bolshakov@yadro.com
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
12
---
10
target/arm/helper.c | 2 +-
13
ui/cocoa.m | 2 +-
11
1 file changed, 1 insertion(+), 1 deletion(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
12
15
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
diff --git a/ui/cocoa.m b/ui/cocoa.m
14
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.c
18
--- a/ui/cocoa.m
16
+++ b/target/arm/helper.c
19
+++ b/ui/cocoa.m
17
@@ -XXX,XX +XXX,XX @@ hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr,
20
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
18
21
- (void) openDocumentation: (NSString *) filename
19
*attrs = (MemTxAttrs) {};
22
{
20
23
/* Where to look for local files */
21
- ret = get_phys_addr(env, addr, 0, mmu_idx, &phys_addr,
24
- NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"../docs/"};
22
+ ret = get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &phys_addr,
25
+ NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"docs/"};
23
attrs, &prot, &page_size, &fi, &cacheattrs);
26
NSString *full_file_path;
24
27
25
if (ret) {
28
/* iterate thru the possible paths until the file is found */
26
--
29
--
27
2.20.1
30
2.20.1
28
31
29
32
diff view generated by jsdifflib
1
Now that the watchdog device uses its Clock input rather than being
1
In commit 1982e1602d15 we added a new qemu-storage-daemon(1) manpage.
2
passed the value of system_clock_scale at creation time, we can
2
At the moment new manpages have to be listed both in the conf.py for
3
remove the hack where we reset the STELLARIS_SYS at board creation
3
Sphinx and also in docs/meson.build for Meson. We forgot the second
4
time to force it to set system_clock_scale. Instead it will be reset
4
of those -- correct the omission.
5
at the usual point in startup and will inform the watchdog of the
6
clock frequency at that point.
7
5
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Luc Michel <luc@lmichel.fr>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20210108161416.21129-2-peter.maydell@linaro.org
12
Message-id: 20210128114145.20536-26-peter.maydell@linaro.org
13
Message-id: 20210121190622.22000-26-peter.maydell@linaro.org
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
---
10
---
16
hw/arm/stellaris.c | 10 ----------
11
docs/meson.build | 1 +
17
1 file changed, 10 deletions(-)
12
1 file changed, 1 insertion(+)
18
13
19
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
14
diff --git a/docs/meson.build b/docs/meson.build
20
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/arm/stellaris.c
16
--- a/docs/meson.build
22
+++ b/hw/arm/stellaris.c
17
+++ b/docs/meson.build
23
@@ -XXX,XX +XXX,XX @@ static DeviceState *stellaris_sys_init(uint32_t base, qemu_irq irq,
18
@@ -XXX,XX +XXX,XX @@ if build_docs
24
sysbus_mmio_map(sbd, 0, base);
19
'qemu-img.1': (have_tools ? 'man1' : ''),
25
sysbus_connect_irq(sbd, 0, irq);
20
'qemu-nbd.8': (have_tools ? 'man8' : ''),
26
21
'qemu-pr-helper.8': (have_tools ? 'man8' : ''),
27
- /*
22
+ 'qemu-storage-daemon.1': (have_tools ? 'man1' : ''),
28
- * Normally we should not be resetting devices like this during
23
'qemu-trace-stap.1': (config_host.has_key('CONFIG_TRACE_SYSTEMTAP') ? 'man1' : ''),
29
- * board creation. For the moment we need to do so, because
24
'virtfs-proxy-helper.1': (have_virtfs_proxy_helper ? 'man1' : ''),
30
- * system_clock_scale will only get set when the STELLARIS_SYS
25
'virtiofsd.1': (have_virtiofsd ? 'man1' : ''),
31
- * device is reset, and we need its initial value to pass to
32
- * the watchdog device. This hack can be removed once the
33
- * watchdog has been converted to use a Clock input instead.
34
- */
35
- device_cold_reset(dev);
36
-
37
return dev;
38
}
39
40
--
26
--
41
2.20.1
27
2.20.1
42
28
43
29
diff view generated by jsdifflib
1
Now no users are setting the frq properties on the CMSDK timer,
1
When we first converted our documentation to Sphinx, we split it into
2
dualtimer, watchdog or ARMSSE SoC devices, we can remove the
2
multiple manuals (system, interop, tools, etc), which are all built
3
properties and the struct fields that back them.
3
separately. The primary driver for this was wanting to be able to
4
avoid shipping the 'devel' manual to end-users. However, this is
5
working against the grain of the way Sphinx wants to be used and
6
causes some annoyances:
7
* Cross-references between documents become much harder or
8
possibly impossible
9
* There is no single index to the whole documentation
10
* Within one manual there's no links or table-of-contents info
11
that lets you easily navigate to the others
12
* The devel manual doesn't get published on the QEMU website
13
(it would be nice to able to refer to it there)
14
15
Merely hiding our developer documentation from end users seems like
16
it's not enough benefit for these costs. Combine all the
17
documentation into a single manual (the same way that the readthedocs
18
site builds it) and install the whole thing. The previous manual
19
divisions remain as the new top level sections in the manual.
20
21
* The per-manual conf.py files are no longer needed
22
* The man_pages[] specifications previously in each per-manual
23
conf.py move to the top level conf.py
24
* docs/meson.build logic is simplified as we now only need to run
25
Sphinx once for the HTML and then once for the manpages5B
26
* The old index.html.in that produced the top-level page with
27
links to each manual is no longer needed
28
29
Unfortunately this means that we now have to build the HTML
30
documentation into docs/manual in the build tree rather than directly
31
into docs/; otherwise it is too awkward to ensure we install only the
32
built manual and not also the dependency info, stamp file, etc. The
33
manual still ends up in the same place in the final installed
34
directory, but anybody who was consulting documentation from within
35
the build tree will have to adjust where they're looking.
4
36
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
37
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
38
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
39
Message-id: 20210108161416.21129-3-peter.maydell@linaro.org
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20210128114145.20536-25-peter.maydell@linaro.org
10
Message-id: 20210121190622.22000-25-peter.maydell@linaro.org
11
---
40
---
12
include/hw/arm/armsse.h | 2 --
41
docs/conf.py | 46 ++++++++++++++++++++++++++++++-
13
include/hw/timer/cmsdk-apb-dualtimer.h | 2 --
42
docs/devel/conf.py | 15 -----------
14
include/hw/timer/cmsdk-apb-timer.h | 2 --
43
docs/index.html.in | 17 ------------
15
include/hw/watchdog/cmsdk-apb-watchdog.h | 2 --
44
docs/interop/conf.py | 28 -------------------
16
hw/arm/armsse.c | 2 --
45
docs/meson.build | 64 +++++++++++++++++---------------------------
17
hw/timer/cmsdk-apb-dualtimer.c | 6 ------
46
docs/specs/conf.py | 16 -----------
18
hw/timer/cmsdk-apb-timer.c | 6 ------
47
docs/system/conf.py | 28 -------------------
19
hw/watchdog/cmsdk-apb-watchdog.c | 6 ------
48
docs/tools/conf.py | 37 -------------------------
20
8 files changed, 28 deletions(-)
49
docs/user/conf.py | 15 -----------
21
50
9 files changed, 70 insertions(+), 196 deletions(-)
22
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
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
23
index XXXXXXX..XXXXXXX 100644
60
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/arm/armsse.h
61
--- a/docs/conf.py
25
+++ b/include/hw/arm/armsse.h
62
+++ b/docs/conf.py
26
@@ -XXX,XX +XXX,XX @@
63
@@ -XXX,XX +XXX,XX @@ latex_documents = [
27
* + Clock input "S32KCLK": slow 32KHz clock used for a few peripherals
64
28
* + QOM property "memory" is a MemoryRegion containing the devices provided
65
# -- Options for manual page output ---------------------------------------
29
* by the board model.
66
# Individual manual/conf.py can override this to create man pages
30
- * + QOM property "MAINCLK_FRQ" is the frequency of the main system clock
67
-man_pages = []
31
* + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts.
68
+man_pages = [
32
* (In hardware, the SSE-200 permits the number of expansion interrupts
69
+ ('interop/qemu-ga', 'qemu-ga',
33
* for the two CPUs to be configured separately, but we restrict it to
70
+ 'QEMU Guest Agent',
34
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
71
+ ['Michael Roth <mdroth@linux.vnet.ibm.com>'], 8),
35
/* Properties */
72
+ ('interop/qemu-ga-ref', 'qemu-ga-ref',
36
MemoryRegion *board_memory;
73
+ 'QEMU Guest Agent Protocol Reference',
37
uint32_t exp_numirq;
74
+ [], 7),
38
- uint32_t mainclk_frq;
75
+ ('interop/qemu-qmp-ref', 'qemu-qmp-ref',
39
uint32_t sram_addr_width;
76
+ 'QEMU QMP Reference Manual',
40
uint32_t init_svtor;
77
+ [], 7),
41
bool cpu_fpu[SSE_MAX_CPUS];
78
+ ('interop/qemu-storage-daemon-qmp-ref', 'qemu-storage-daemon-qmp-ref',
42
diff --git a/include/hw/timer/cmsdk-apb-dualtimer.h b/include/hw/timer/cmsdk-apb-dualtimer.h
79
+ 'QEMU Storage Daemon QMP Reference Manual',
80
+ [], 7),
81
+ ('system/qemu-manpage', 'qemu',
82
+ 'QEMU User Documentation',
83
+ ['Fabrice Bellard'], 1),
84
+ ('system/qemu-block-drivers', 'qemu-block-drivers',
85
+ 'QEMU block drivers reference',
86
+ ['Fabrice Bellard and the QEMU Project developers'], 7),
87
+ ('system/qemu-cpu-models', 'qemu-cpu-models',
88
+ 'QEMU CPU Models',
89
+ ['The QEMU Project developers'], 7),
90
+ ('tools/qemu-img', 'qemu-img',
91
+ 'QEMU disk image utility',
92
+ ['Fabrice Bellard'], 1),
93
+ ('tools/qemu-nbd', 'qemu-nbd',
94
+ 'QEMU Disk Network Block Device Server',
95
+ ['Anthony Liguori <anthony@codemonkey.ws>'], 8),
96
+ ('tools/qemu-pr-helper', 'qemu-pr-helper',
97
+ 'QEMU persistent reservation helper',
98
+ [], 8),
99
+ ('tools/qemu-storage-daemon', 'qemu-storage-daemon',
100
+ 'QEMU storage daemon',
101
+ [], 1),
102
+ ('tools/qemu-trace-stap', 'qemu-trace-stap',
103
+ 'QEMU SystemTap trace tool',
104
+ [], 1),
105
+ ('tools/virtfs-proxy-helper', 'virtfs-proxy-helper',
106
+ 'QEMU 9p virtfs proxy filesystem helper',
107
+ ['M. Mohan Kumar'], 1),
108
+ ('tools/virtiofsd', 'virtiofsd',
109
+ 'QEMU virtio-fs shared file system daemon',
110
+ ['Stefan Hajnoczi <stefanha@redhat.com>',
111
+ 'Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>'], 1),
112
+]
113
114
# -- Options for Texinfo output -------------------------------------------
115
116
diff --git a/docs/devel/conf.py b/docs/devel/conf.py
117
deleted file mode 100644
118
index XXXXXXX..XXXXXXX
119
--- a/docs/devel/conf.py
120
+++ /dev/null
121
@@ -XXX,XX +XXX,XX @@
122
-# -*- coding: utf-8 -*-
123
-#
124
-# QEMU documentation build configuration file for the 'devel' manual.
125
-#
126
-# This includes the top level conf file and then makes any necessary tweaks.
127
-import sys
128
-import os
129
-
130
-qemu_docdir = os.path.abspath("..")
131
-parent_config = os.path.join(qemu_docdir, "conf.py")
132
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
133
-
134
-# This slightly misuses the 'description', but is the best way to get
135
-# the manual title to appear in the sidebar.
136
-html_theme_options['description'] = u'Developer''s Guide'
137
diff --git a/docs/index.html.in b/docs/index.html.in
138
deleted file mode 100644
139
index XXXXXXX..XXXXXXX
140
--- a/docs/index.html.in
141
+++ /dev/null
142
@@ -XXX,XX +XXX,XX @@
143
-<!DOCTYPE html>
144
-<html lang="en">
145
- <head>
146
- <meta charset="UTF-8">
147
- <title>QEMU @VERSION@ Documentation</title>
148
- </head>
149
- <body>
150
- <h1>QEMU @VERSION@ Documentation</h1>
151
- <ul>
152
- <li><a href="system/index.html">System Emulation User's Guide</a></li>
153
- <li><a href="user/index.html">User Mode Emulation User's Guide</a></li>
154
- <li><a href="tools/index.html">Tools Guide</a></li>
155
- <li><a href="interop/index.html">System Emulation Management and Interoperability Guide</a></li>
156
- <li><a href="specs/index.html">System Emulation Guest Hardware Specifications</a></li>
157
- </ul>
158
- </body>
159
-</html>
160
diff --git a/docs/interop/conf.py b/docs/interop/conf.py
161
deleted file mode 100644
162
index XXXXXXX..XXXXXXX
163
--- a/docs/interop/conf.py
164
+++ /dev/null
165
@@ -XXX,XX +XXX,XX @@
166
-# -*- coding: utf-8 -*-
167
-#
168
-# QEMU documentation build configuration file for the 'interop' manual.
169
-#
170
-# This includes the top level conf file and then makes any necessary tweaks.
171
-import sys
172
-import os
173
-
174
-qemu_docdir = os.path.abspath("..")
175
-parent_config = os.path.join(qemu_docdir, "conf.py")
176
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
177
-
178
-# This slightly misuses the 'description', but is the best way to get
179
-# the manual title to appear in the sidebar.
180
-html_theme_options['description'] = u'System Emulation Management and Interoperability Guide'
181
-
182
-# One entry per manual page. List of tuples
183
-# (source start file, name, description, authors, manual section).
184
-man_pages = [
185
- ('qemu-ga', 'qemu-ga', u'QEMU Guest Agent',
186
- ['Michael Roth <mdroth@linux.vnet.ibm.com>'], 8),
187
- ('qemu-ga-ref', 'qemu-ga-ref', 'QEMU Guest Agent Protocol Reference',
188
- [], 7),
189
- ('qemu-qmp-ref', 'qemu-qmp-ref', 'QEMU QMP Reference Manual',
190
- [], 7),
191
- ('qemu-storage-daemon-qmp-ref', 'qemu-storage-daemon-qmp-ref',
192
- 'QEMU Storage Daemon QMP Reference Manual', [], 7),
193
-]
194
diff --git a/docs/meson.build b/docs/meson.build
43
index XXXXXXX..XXXXXXX 100644
195
index XXXXXXX..XXXXXXX 100644
44
--- a/include/hw/timer/cmsdk-apb-dualtimer.h
196
--- a/docs/meson.build
45
+++ b/include/hw/timer/cmsdk-apb-dualtimer.h
197
+++ b/docs/meson.build
46
@@ -XXX,XX +XXX,XX @@
198
@@ -XXX,XX +XXX,XX @@ if build_docs
47
* https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
199
meson.source_root() / 'docs/sphinx/qmp_lexer.py',
48
*
200
qapi_gen_depends ]
49
* QEMU interface:
201
50
- * + QOM property "pclk-frq": frequency at which the timer is clocked
202
- configure_file(output: 'index.html',
51
* + Clock input "TIMCLK": clock (for both timers)
203
- input: files('index.html.in'),
52
* + sysbus MMIO region 0: the register bank
204
- configuration: {'VERSION': meson.project_version()},
53
* + sysbus IRQ 0: combined timer interrupt TIMINTC
205
- install_dir: qemu_docdir)
54
@@ -XXX,XX +XXX,XX @@ struct CMSDKAPBDualTimer {
206
- manuals = [ 'devel', 'interop', 'tools', 'specs', 'system', 'user' ]
55
/*< public >*/
207
man_pages = {
56
MemoryRegion iomem;
208
- 'interop' : {
57
qemu_irq timerintc;
209
'qemu-ga.8': (have_tools ? 'man8' : ''),
58
- uint32_t pclk_frq;
210
'qemu-ga-ref.7': 'man7',
59
Clock *timclk;
211
'qemu-qmp-ref.7': 'man7',
60
212
'qemu-storage-daemon-qmp-ref.7': (have_tools ? 'man7' : ''),
61
CMSDKAPBDualTimerModule timermod[CMSDK_APB_DUALTIMER_NUM_MODULES];
213
- },
62
diff --git a/include/hw/timer/cmsdk-apb-timer.h b/include/hw/timer/cmsdk-apb-timer.h
214
- 'tools': {
63
index XXXXXXX..XXXXXXX 100644
215
'qemu-img.1': (have_tools ? 'man1' : ''),
64
--- a/include/hw/timer/cmsdk-apb-timer.h
216
'qemu-nbd.8': (have_tools ? 'man8' : ''),
65
+++ b/include/hw/timer/cmsdk-apb-timer.h
217
'qemu-pr-helper.8': (have_tools ? 'man8' : ''),
66
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBTimer, CMSDK_APB_TIMER)
218
@@ -XXX,XX +XXX,XX @@ if build_docs
67
219
'qemu-trace-stap.1': (config_host.has_key('CONFIG_TRACE_SYSTEMTAP') ? 'man1' : ''),
68
/*
220
'virtfs-proxy-helper.1': (have_virtfs_proxy_helper ? 'man1' : ''),
69
* QEMU interface:
221
'virtiofsd.1': (have_virtiofsd ? 'man1' : ''),
70
- * + QOM property "pclk-frq": frequency at which the timer is clocked
222
- },
71
* + Clock input "pclk": clock for the timer
223
- 'system': {
72
* + sysbus MMIO region 0: the register bank
224
'qemu.1': 'man1',
73
* + sysbus IRQ 0: timer interrupt TIMERINT
225
'qemu-block-drivers.7': 'man7',
74
@@ -XXX,XX +XXX,XX @@ struct CMSDKAPBTimer {
226
'qemu-cpu-models.7': 'man7'
75
/*< public >*/
227
- },
76
MemoryRegion iomem;
228
}
77
qemu_irq timerint;
229
78
- uint32_t pclk_frq;
230
sphinxdocs = []
79
struct ptimer_state *timer;
231
sphinxmans = []
80
Clock *pclk;
232
- foreach manual : manuals
81
233
- private_dir = meson.current_build_dir() / (manual + '.p')
82
diff --git a/include/hw/watchdog/cmsdk-apb-watchdog.h b/include/hw/watchdog/cmsdk-apb-watchdog.h
234
- output_dir = meson.current_build_dir() / manual
83
index XXXXXXX..XXXXXXX 100644
235
- input_dir = meson.current_source_dir() / manual
84
--- a/include/hw/watchdog/cmsdk-apb-watchdog.h
236
85
+++ b/include/hw/watchdog/cmsdk-apb-watchdog.h
237
- this_manual = custom_target(manual + ' manual',
86
@@ -XXX,XX +XXX,XX @@
238
+ private_dir = meson.current_build_dir() / 'manual.p'
87
* https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
239
+ output_dir = meson.current_build_dir() / 'manual'
88
*
240
+ input_dir = meson.current_source_dir()
89
* QEMU interface:
241
+
90
- * + QOM property "wdogclk-frq": frequency at which the watchdog is clocked
242
+ this_manual = custom_target('QEMU manual',
91
* + Clock input "WDOGCLK": clock for the watchdog's timer
243
build_by_default: build_docs,
92
* + sysbus MMIO region 0: the register bank
244
- output: [manual + '.stamp'],
93
* + sysbus IRQ 0: watchdog interrupt
245
- input: [files('conf.py'), files(manual / 'conf.py')],
94
@@ -XXX,XX +XXX,XX @@ struct CMSDKAPBWatchdog {
246
- depfile: manual + '.d',
95
/*< public >*/
247
+ output: 'docs.stamp',
96
MemoryRegion iomem;
248
+ input: files('conf.py'),
97
qemu_irq wdogint;
249
+ depfile: 'docs.d',
98
- uint32_t wdogclk_frq;
250
depend_files: sphinx_extn_depends,
99
bool is_luminary;
251
command: [SPHINX_ARGS, '-Ddepfile=@DEPFILE@',
100
struct ptimer_state *timer;
252
'-Ddepfile_stamp=@OUTPUT0@',
101
Clock *wdogclk;
253
'-b', 'html', '-d', private_dir,
102
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
254
input_dir, output_dir])
103
index XXXXXXX..XXXXXXX 100644
255
- sphinxdocs += this_manual
104
--- a/hw/arm/armsse.c
256
- if build_docs and manual != 'devel'
105
+++ b/hw/arm/armsse.c
257
- install_subdir(output_dir, install_dir: qemu_docdir)
106
@@ -XXX,XX +XXX,XX @@ static Property iotkit_properties[] = {
258
- endif
107
DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
259
+ sphinxdocs += this_manual
108
MemoryRegion *),
260
+ install_subdir(output_dir, install_dir: qemu_docdir, strip_directory: true)
109
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
261
110
- DEFINE_PROP_UINT32("MAINCLK_FRQ", ARMSSE, mainclk_frq, 0),
262
- these_man_pages = []
111
DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
263
- install_dirs = []
112
DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
264
- foreach page, section : man_pages.get(manual, {})
113
DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], true),
265
- these_man_pages += page
114
@@ -XXX,XX +XXX,XX @@ static Property armsse_properties[] = {
266
- install_dirs += section == '' ? false : get_option('mandir') / section
115
DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
267
- endforeach
116
MemoryRegion *),
268
- if these_man_pages.length() > 0
117
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
269
- sphinxmans += custom_target(manual + ' man pages',
118
- DEFINE_PROP_UINT32("MAINCLK_FRQ", ARMSSE, mainclk_frq, 0),
270
- build_by_default: build_docs,
119
DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
271
- output: these_man_pages,
120
DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
272
- input: this_manual,
121
DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], false),
273
- install: build_docs,
122
diff --git a/hw/timer/cmsdk-apb-dualtimer.c b/hw/timer/cmsdk-apb-dualtimer.c
274
- install_dir: install_dirs,
123
index XXXXXXX..XXXXXXX 100644
275
- command: [SPHINX_ARGS, '-b', 'man', '-d', private_dir,
124
--- a/hw/timer/cmsdk-apb-dualtimer.c
276
- input_dir, meson.current_build_dir()])
125
+++ b/hw/timer/cmsdk-apb-dualtimer.c
277
- endif
126
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription cmsdk_apb_dualtimer_vmstate = {
278
+ these_man_pages = []
127
}
279
+ install_dirs = []
128
};
280
+ foreach page, section : man_pages
129
281
+ these_man_pages += page
130
-static Property cmsdk_apb_dualtimer_properties[] = {
282
+ install_dirs += section == '' ? false : get_option('mandir') / section
131
- DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBDualTimer, pclk_frq, 0),
283
endforeach
132
- DEFINE_PROP_END_OF_LIST(),
284
+
133
-};
285
+ sphinxmans += custom_target('QEMU man pages',
134
-
286
+ build_by_default: build_docs,
135
static void cmsdk_apb_dualtimer_class_init(ObjectClass *klass, void *data)
287
+ output: these_man_pages,
136
{
288
+ input: this_manual,
137
DeviceClass *dc = DEVICE_CLASS(klass);
289
+ install: build_docs,
138
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_dualtimer_class_init(ObjectClass *klass, void *data)
290
+ install_dir: install_dirs,
139
dc->realize = cmsdk_apb_dualtimer_realize;
291
+ command: [SPHINX_ARGS, '-b', 'man', '-d', private_dir,
140
dc->vmsd = &cmsdk_apb_dualtimer_vmstate;
292
+ input_dir, meson.current_build_dir()])
141
dc->reset = cmsdk_apb_dualtimer_reset;
293
+
142
- device_class_set_props(dc, cmsdk_apb_dualtimer_properties);
294
alias_target('sphinxdocs', sphinxdocs)
143
}
295
alias_target('html', sphinxdocs)
144
296
alias_target('man', sphinxmans)
145
static const TypeInfo cmsdk_apb_dualtimer_info = {
297
diff --git a/docs/specs/conf.py b/docs/specs/conf.py
146
diff --git a/hw/timer/cmsdk-apb-timer.c b/hw/timer/cmsdk-apb-timer.c
298
deleted file mode 100644
147
index XXXXXXX..XXXXXXX 100644
299
index XXXXXXX..XXXXXXX
148
--- a/hw/timer/cmsdk-apb-timer.c
300
--- a/docs/specs/conf.py
149
+++ b/hw/timer/cmsdk-apb-timer.c
301
+++ /dev/null
150
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription cmsdk_apb_timer_vmstate = {
302
@@ -XXX,XX +XXX,XX @@
151
}
303
-# -*- coding: utf-8 -*-
152
};
304
-#
153
305
-# QEMU documentation build configuration file for the 'specs' manual.
154
-static Property cmsdk_apb_timer_properties[] = {
306
-#
155
- DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBTimer, pclk_frq, 0),
307
-# This includes the top level conf file and then makes any necessary tweaks.
156
- DEFINE_PROP_END_OF_LIST(),
308
-import sys
157
-};
309
-import os
158
-
310
-
159
static void cmsdk_apb_timer_class_init(ObjectClass *klass, void *data)
311
-qemu_docdir = os.path.abspath("..")
160
{
312
-parent_config = os.path.join(qemu_docdir, "conf.py")
161
DeviceClass *dc = DEVICE_CLASS(klass);
313
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
162
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_class_init(ObjectClass *klass, void *data)
314
-
163
dc->realize = cmsdk_apb_timer_realize;
315
-# This slightly misuses the 'description', but is the best way to get
164
dc->vmsd = &cmsdk_apb_timer_vmstate;
316
-# the manual title to appear in the sidebar.
165
dc->reset = cmsdk_apb_timer_reset;
317
-html_theme_options['description'] = \
166
- device_class_set_props(dc, cmsdk_apb_timer_properties);
318
- u'System Emulation Guest Hardware Specifications'
167
}
319
diff --git a/docs/system/conf.py b/docs/system/conf.py
168
320
deleted file mode 100644
169
static const TypeInfo cmsdk_apb_timer_info = {
321
index XXXXXXX..XXXXXXX
170
diff --git a/hw/watchdog/cmsdk-apb-watchdog.c b/hw/watchdog/cmsdk-apb-watchdog.c
322
--- a/docs/system/conf.py
171
index XXXXXXX..XXXXXXX 100644
323
+++ /dev/null
172
--- a/hw/watchdog/cmsdk-apb-watchdog.c
324
@@ -XXX,XX +XXX,XX @@
173
+++ b/hw/watchdog/cmsdk-apb-watchdog.c
325
-# -*- coding: utf-8 -*-
174
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription cmsdk_apb_watchdog_vmstate = {
326
-#
175
}
327
-# QEMU documentation build configuration file for the 'system' manual.
176
};
328
-#
177
329
-# This includes the top level conf file and then makes any necessary tweaks.
178
-static Property cmsdk_apb_watchdog_properties[] = {
330
-import sys
179
- DEFINE_PROP_UINT32("wdogclk-frq", CMSDKAPBWatchdog, wdogclk_frq, 0),
331
-import os
180
- DEFINE_PROP_END_OF_LIST(),
332
-
181
-};
333
-qemu_docdir = os.path.abspath("..")
182
-
334
-parent_config = os.path.join(qemu_docdir, "conf.py")
183
static void cmsdk_apb_watchdog_class_init(ObjectClass *klass, void *data)
335
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
184
{
336
-
185
DeviceClass *dc = DEVICE_CLASS(klass);
337
-# This slightly misuses the 'description', but is the best way to get
186
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_class_init(ObjectClass *klass, void *data)
338
-# the manual title to appear in the sidebar.
187
dc->realize = cmsdk_apb_watchdog_realize;
339
-html_theme_options['description'] = u'System Emulation User''s Guide'
188
dc->vmsd = &cmsdk_apb_watchdog_vmstate;
340
-
189
dc->reset = cmsdk_apb_watchdog_reset;
341
-# One entry per manual page. List of tuples
190
- device_class_set_props(dc, cmsdk_apb_watchdog_properties);
342
-# (source start file, name, description, authors, manual section).
191
}
343
-man_pages = [
192
344
- ('qemu-manpage', 'qemu', u'QEMU User Documentation',
193
static const TypeInfo cmsdk_apb_watchdog_info = {
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'
194
--
417
--
195
2.20.1
418
2.20.1
196
419
197
420
diff view generated by jsdifflib
1
The old-style convenience function cmsdk_apb_timer_create() for
1
In commit cd8be50e58f63413c0 we converted the A32 coprocessor
2
creating CMSDK_APB_TIMER objects is used in only two places in
2
insns to decodetree. This accidentally broke XScale/iWMMXt insns,
3
mps2.c. Most of the rest of the code in that file uses the new
3
because it moved the handling of "cp insns which are handled
4
"initialize in place" coding style.
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.
5
7
6
We want to connect up a Clock object which should be done between the
8
Update valid_cp() so that it knows that on XScale cp 0 and 1
7
object creation and realization; rather than adding a Clock* argument
9
are not standard coprocessor instructions; this will cause
8
to the convenience function, convert the timer creation code in
10
the decodetree trans_ functions to ignore them, so that
9
mps2.c to the same style as is used already for the watchdog,
11
execution will correctly get through to the legacy decode again.
10
dualtimer and other devices, and delete the now-unused convenience
11
function.
12
12
13
Cc: qemu-stable@nongnu.org
14
Reported-by: Guenter Roeck <linux@roeck-us.net>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Reviewed-by: Luc Michel <luc@lmichel.fr>
17
Tested-by: Guenter Roeck <linux@roeck-us.net>
16
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Message-id: 20210108195157.32067-1-peter.maydell@linaro.org
17
Message-id: 20210128114145.20536-13-peter.maydell@linaro.org
18
Message-id: 20210121190622.22000-13-peter.maydell@linaro.org
19
---
19
---
20
include/hw/timer/cmsdk-apb-timer.h | 21 ---------------------
20
target/arm/translate.c | 7 +++++++
21
hw/arm/mps2.c | 18 ++++++++++++++++--
21
1 file changed, 7 insertions(+)
22
2 files changed, 16 insertions(+), 23 deletions(-)
23
22
24
diff --git a/include/hw/timer/cmsdk-apb-timer.h b/include/hw/timer/cmsdk-apb-timer.h
23
diff --git a/target/arm/translate.c b/target/arm/translate.c
25
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
26
--- a/include/hw/timer/cmsdk-apb-timer.h
25
--- a/target/arm/translate.c
27
+++ b/include/hw/timer/cmsdk-apb-timer.h
26
+++ b/target/arm/translate.c
28
@@ -XXX,XX +XXX,XX @@ struct CMSDKAPBTimer {
27
@@ -XXX,XX +XXX,XX @@ static bool valid_cp(DisasContext *s, int cp)
29
uint32_t intstatus;
28
* only cp14 and cp15 are valid, and other values aren't considered
30
};
29
* to be in the coprocessor-instruction space at all. v8M still
31
30
* permits coprocessors 0..7.
32
-/**
31
+ * For XScale, we must not decode the XScale cp0, cp1 space as
33
- * cmsdk_apb_timer_create - convenience function to create TYPE_CMSDK_APB_TIMER
32
+ * a standard coprocessor insn, because we want to fall through to
34
- * @addr: location in system memory to map registers
33
+ * the legacy disas_xscale_insn() decoder after decodetree is done.
35
- * @pclk_frq: frequency in Hz of the PCLK clock (used for calculating baud rate)
34
*/
36
- */
35
+ if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cp == 0 || cp == 1)) {
37
-static inline DeviceState *cmsdk_apb_timer_create(hwaddr addr,
36
+ return false;
38
- qemu_irq timerint,
39
- uint32_t pclk_frq)
40
-{
41
- DeviceState *dev;
42
- SysBusDevice *s;
43
-
44
- dev = qdev_new(TYPE_CMSDK_APB_TIMER);
45
- s = SYS_BUS_DEVICE(dev);
46
- qdev_prop_set_uint32(dev, "pclk-frq", pclk_frq);
47
- sysbus_realize_and_unref(s, &error_fatal);
48
- sysbus_mmio_map(s, 0, addr);
49
- sysbus_connect_irq(s, 0, timerint);
50
- return dev;
51
-}
52
-
53
#endif
54
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/hw/arm/mps2.c
57
+++ b/hw/arm/mps2.c
58
@@ -XXX,XX +XXX,XX @@ struct MPS2MachineState {
59
/* CMSDK APB subsystem */
60
CMSDKAPBDualTimer dualtimer;
61
CMSDKAPBWatchdog watchdog;
62
+ CMSDKAPBTimer timer[2];
63
};
64
65
#define TYPE_MPS2_MACHINE "mps2"
66
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
67
}
68
69
/* CMSDK APB subsystem */
70
- cmsdk_apb_timer_create(0x40000000, qdev_get_gpio_in(armv7m, 8), SYSCLK_FRQ);
71
- cmsdk_apb_timer_create(0x40001000, qdev_get_gpio_in(armv7m, 9), SYSCLK_FRQ);
72
+ for (i = 0; i < ARRAY_SIZE(mms->timer); i++) {
73
+ g_autofree char *name = g_strdup_printf("timer%d", i);
74
+ hwaddr base = 0x40000000 + i * 0x1000;
75
+ int irqno = 8 + i;
76
+ SysBusDevice *sbd;
77
+
78
+ object_initialize_child(OBJECT(mms), name, &mms->timer[i],
79
+ TYPE_CMSDK_APB_TIMER);
80
+ sbd = SYS_BUS_DEVICE(&mms->timer[i]);
81
+ qdev_prop_set_uint32(DEVICE(&mms->timer[i]), "pclk-frq", SYSCLK_FRQ);
82
+ sysbus_realize_and_unref(sbd, &error_fatal);
83
+ sysbus_mmio_map(sbd, 0, base);
84
+ sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(armv7m, irqno));
85
+ }
37
+ }
86
+
38
+
87
object_initialize_child(OBJECT(mms), "dualtimer", &mms->dualtimer,
39
if (arm_dc_feature(s, ARM_FEATURE_V8) &&
88
TYPE_CMSDK_APB_DUALTIMER);
40
!arm_dc_feature(s, ARM_FEATURE_M)) {
89
qdev_prop_set_uint32(DEVICE(&mms->dualtimer), "pclk-frq", SYSCLK_FRQ);
41
return cp >= 14;
90
--
42
--
91
2.20.1
43
2.20.1
92
44
93
45
diff view generated by jsdifflib
1
Remove all the code that sets frequency properties on the CMSDK
1
A copy-and-paste error meant that the return value for register offset 0x44
2
timer, dualtimer and watchdog devices and on the ARMSSE SoC device:
2
(the RX Status FIFO PEEK register) returned a byte from a bogus offset in
3
these properties are unused now that the devices rely on their Clock
3
the rx status FIFO. Fix the typo.
4
inputs instead.
5
4
5
Cc: qemu-stable@nongnu.org
6
Fixes: https://bugs.launchpad.net/qemu/+bug/1904954
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Luc Michel <luc@lmichel.fr>
9
Message-id: 20210108180401.2263-2-peter.maydell@linaro.org
9
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20210128114145.20536-24-peter.maydell@linaro.org
11
Message-id: 20210121190622.22000-24-peter.maydell@linaro.org
12
---
10
---
13
hw/arm/armsse.c | 7 -------
11
hw/net/lan9118.c | 2 +-
14
hw/arm/mps2-tz.c | 1 -
12
1 file changed, 1 insertion(+), 1 deletion(-)
15
hw/arm/mps2.c | 3 ---
16
hw/arm/musca.c | 1 -
17
hw/arm/stellaris.c | 3 ---
18
5 files changed, 15 deletions(-)
19
13
20
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
14
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
21
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/arm/armsse.c
16
--- a/hw/net/lan9118.c
23
+++ b/hw/arm/armsse.c
17
+++ b/hw/net/lan9118.c
24
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
18
@@ -XXX,XX +XXX,XX @@ static uint64_t lan9118_readl(void *opaque, hwaddr offset,
25
* it to the appropriate PPC port; then we can realize the PPC and
19
case 0x40:
26
* map its upstream ends to the right place in the container.
20
return rx_status_fifo_pop(s);
27
*/
21
case 0x44:
28
- qdev_prop_set_uint32(DEVICE(&s->timer0), "pclk-frq", s->mainclk_frq);
22
- return s->rx_status_fifo[s->tx_status_fifo_head];
29
qdev_connect_clock_in(DEVICE(&s->timer0), "pclk", s->mainclk);
23
+ return s->rx_status_fifo[s->rx_status_fifo_head];
30
if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer0), errp)) {
24
case 0x48:
31
return;
25
return tx_status_fifo_pop(s);
32
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
26
case 0x4c:
33
object_property_set_link(OBJECT(&s->apb_ppc0), "port[0]", OBJECT(mr),
34
&error_abort);
35
36
- qdev_prop_set_uint32(DEVICE(&s->timer1), "pclk-frq", s->mainclk_frq);
37
qdev_connect_clock_in(DEVICE(&s->timer1), "pclk", s->mainclk);
38
if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer1), errp)) {
39
return;
40
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
41
object_property_set_link(OBJECT(&s->apb_ppc0), "port[1]", OBJECT(mr),
42
&error_abort);
43
44
- qdev_prop_set_uint32(DEVICE(&s->dualtimer), "pclk-frq", s->mainclk_frq);
45
qdev_connect_clock_in(DEVICE(&s->dualtimer), "TIMCLK", s->mainclk);
46
if (!sysbus_realize(SYS_BUS_DEVICE(&s->dualtimer), errp)) {
47
return;
48
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
49
/* Devices behind APB PPC1:
50
* 0x4002f000: S32K timer
51
*/
52
- qdev_prop_set_uint32(DEVICE(&s->s32ktimer), "pclk-frq", S32KCLK);
53
qdev_connect_clock_in(DEVICE(&s->s32ktimer), "pclk", s->s32kclk);
54
if (!sysbus_realize(SYS_BUS_DEVICE(&s->s32ktimer), errp)) {
55
return;
56
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
57
qdev_connect_gpio_out(DEVICE(&s->nmi_orgate), 0,
58
qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0));
59
60
- qdev_prop_set_uint32(DEVICE(&s->s32kwatchdog), "wdogclk-frq", S32KCLK);
61
qdev_connect_clock_in(DEVICE(&s->s32kwatchdog), "WDOGCLK", s->s32kclk);
62
if (!sysbus_realize(SYS_BUS_DEVICE(&s->s32kwatchdog), errp)) {
63
return;
64
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
65
66
/* 0x40080000 .. 0x4008ffff : ARMSSE second Base peripheral region */
67
68
- qdev_prop_set_uint32(DEVICE(&s->nswatchdog), "wdogclk-frq", s->mainclk_frq);
69
qdev_connect_clock_in(DEVICE(&s->nswatchdog), "WDOGCLK", s->mainclk);
70
if (!sysbus_realize(SYS_BUS_DEVICE(&s->nswatchdog), errp)) {
71
return;
72
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
73
armsse_get_common_irq_in(s, 1));
74
sysbus_mmio_map(SYS_BUS_DEVICE(&s->nswatchdog), 0, 0x40081000);
75
76
- qdev_prop_set_uint32(DEVICE(&s->swatchdog), "wdogclk-frq", s->mainclk_frq);
77
qdev_connect_clock_in(DEVICE(&s->swatchdog), "WDOGCLK", s->mainclk);
78
if (!sysbus_realize(SYS_BUS_DEVICE(&s->swatchdog), errp)) {
79
return;
80
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/hw/arm/mps2-tz.c
83
+++ b/hw/arm/mps2-tz.c
84
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
85
object_property_set_link(OBJECT(&mms->iotkit), "memory",
86
OBJECT(system_memory), &error_abort);
87
qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", MPS2TZ_NUMIRQ);
88
- qdev_prop_set_uint32(iotkitdev, "MAINCLK_FRQ", SYSCLK_FRQ);
89
qdev_connect_clock_in(iotkitdev, "MAINCLK", mms->sysclk);
90
qdev_connect_clock_in(iotkitdev, "S32KCLK", mms->s32kclk);
91
sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
92
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
93
index XXXXXXX..XXXXXXX 100644
94
--- a/hw/arm/mps2.c
95
+++ b/hw/arm/mps2.c
96
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
97
object_initialize_child(OBJECT(mms), name, &mms->timer[i],
98
TYPE_CMSDK_APB_TIMER);
99
sbd = SYS_BUS_DEVICE(&mms->timer[i]);
100
- qdev_prop_set_uint32(DEVICE(&mms->timer[i]), "pclk-frq", SYSCLK_FRQ);
101
qdev_connect_clock_in(DEVICE(&mms->timer[i]), "pclk", mms->sysclk);
102
sysbus_realize_and_unref(sbd, &error_fatal);
103
sysbus_mmio_map(sbd, 0, base);
104
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
105
106
object_initialize_child(OBJECT(mms), "dualtimer", &mms->dualtimer,
107
TYPE_CMSDK_APB_DUALTIMER);
108
- qdev_prop_set_uint32(DEVICE(&mms->dualtimer), "pclk-frq", SYSCLK_FRQ);
109
qdev_connect_clock_in(DEVICE(&mms->dualtimer), "TIMCLK", mms->sysclk);
110
sysbus_realize(SYS_BUS_DEVICE(&mms->dualtimer), &error_fatal);
111
sysbus_connect_irq(SYS_BUS_DEVICE(&mms->dualtimer), 0,
112
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
113
sysbus_mmio_map(SYS_BUS_DEVICE(&mms->dualtimer), 0, 0x40002000);
114
object_initialize_child(OBJECT(mms), "watchdog", &mms->watchdog,
115
TYPE_CMSDK_APB_WATCHDOG);
116
- qdev_prop_set_uint32(DEVICE(&mms->watchdog), "wdogclk-frq", SYSCLK_FRQ);
117
qdev_connect_clock_in(DEVICE(&mms->watchdog), "WDOGCLK", mms->sysclk);
118
sysbus_realize(SYS_BUS_DEVICE(&mms->watchdog), &error_fatal);
119
sysbus_connect_irq(SYS_BUS_DEVICE(&mms->watchdog), 0,
120
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/hw/arm/musca.c
123
+++ b/hw/arm/musca.c
124
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
125
qdev_prop_set_uint32(ssedev, "EXP_NUMIRQ", mmc->num_irqs);
126
qdev_prop_set_uint32(ssedev, "init-svtor", mmc->init_svtor);
127
qdev_prop_set_uint32(ssedev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width);
128
- qdev_prop_set_uint32(ssedev, "MAINCLK_FRQ", SYSCLK_FRQ);
129
qdev_connect_clock_in(ssedev, "MAINCLK", mms->sysclk);
130
qdev_connect_clock_in(ssedev, "S32KCLK", mms->s32kclk);
131
/*
132
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
133
index XXXXXXX..XXXXXXX 100644
134
--- a/hw/arm/stellaris.c
135
+++ b/hw/arm/stellaris.c
136
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
137
if (board->dc1 & (1 << 3)) { /* watchdog present */
138
dev = qdev_new(TYPE_LUMINARY_WATCHDOG);
139
140
- /* system_clock_scale is valid now */
141
- uint32_t mainclk = NANOSECONDS_PER_SECOND / system_clock_scale;
142
- qdev_prop_set_uint32(dev, "wdogclk-frq", mainclk);
143
qdev_connect_clock_in(dev, "WDOGCLK",
144
qdev_get_clock_out(ssys_dev, "SYSCLK"));
145
146
--
27
--
147
2.20.1
28
2.20.1
148
29
149
30
diff view generated by jsdifflib
1
Use the MAINCLK Clock input to set the system_clock_scale variable
1
The lan9118 code mostly uses symbolic constants for register offsets;
2
rather than using the mainclk_frq property.
2
the exceptions are those which the datasheet doesn't give an official
3
symbolic name to.
4
5
Add some names for the registers which don't already have them, based
6
on the longer names they are given in the memory map.
3
7
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20210108180401.2263-3-peter.maydell@linaro.org
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
8
Message-id: 20210128114145.20536-23-peter.maydell@linaro.org
9
Message-id: 20210121190622.22000-23-peter.maydell@linaro.org
10
---
11
---
11
hw/arm/armsse.c | 24 +++++++++++++++++++-----
12
hw/net/lan9118.c | 24 ++++++++++++++++++------
12
1 file changed, 19 insertions(+), 5 deletions(-)
13
1 file changed, 18 insertions(+), 6 deletions(-)
13
14
14
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
15
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/armsse.c
17
--- a/hw/net/lan9118.c
17
+++ b/hw/arm/armsse.c
18
+++ b/hw/net/lan9118.c
18
@@ -XXX,XX +XXX,XX @@ static void armsse_forward_sec_resp_cfg(ARMSSE *s)
19
@@ -XXX,XX +XXX,XX @@ do { hw_error("lan9118: error: " fmt , ## __VA_ARGS__);} while (0)
19
qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in);
20
do { fprintf(stderr, "lan9118: error: " fmt , ## __VA_ARGS__);} while (0)
20
}
21
#endif
21
22
22
+static void armsse_mainclk_update(void *opaque)
23
+/* The tx and rx fifo ports are a range of aliased 32-bit registers */
23
+{
24
+#define RX_DATA_FIFO_PORT_FIRST 0x00
24
+ ARMSSE *s = ARM_SSE(opaque);
25
+#define RX_DATA_FIFO_PORT_LAST 0x1f
25
+ /*
26
+#define TX_DATA_FIFO_PORT_FIRST 0x20
26
+ * Set system_clock_scale from our Clock input; this is what
27
+#define TX_DATA_FIFO_PORT_LAST 0x3f
27
+ * controls the tick rate of the CPU SysTick timer.
28
+ */
29
+ system_clock_scale = clock_ticks_to_ns(s->mainclk, 1);
30
+}
31
+
28
+
32
static void armsse_init(Object *obj)
29
+#define RX_STATUS_FIFO_PORT 0x40
33
{
30
+#define RX_STATUS_FIFO_PEEK 0x44
34
ARMSSE *s = ARM_SSE(obj);
31
+#define TX_STATUS_FIFO_PORT 0x48
35
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
32
+#define TX_STATUS_FIFO_PEEK 0x4c
36
assert(info->sram_banks <= MAX_SRAM_BANKS);
33
+
37
assert(info->num_cpus <= SSE_MAX_CPUS);
34
#define CSR_ID_REV 0x50
38
35
#define CSR_IRQ_CFG 0x54
39
- s->mainclk = qdev_init_clock_in(DEVICE(s), "MAINCLK", NULL, NULL);
36
#define CSR_INT_STS 0x58
40
+ s->mainclk = qdev_init_clock_in(DEVICE(s), "MAINCLK",
37
@@ -XXX,XX +XXX,XX @@ static void lan9118_writel(void *opaque, hwaddr offset,
41
+ armsse_mainclk_update, s);
38
offset &= 0xff;
42
s->s32kclk = qdev_init_clock_in(DEVICE(s), "S32KCLK", NULL, NULL);
39
43
40
//DPRINTF("Write reg 0x%02x = 0x%08x\n", (int)offset, val);
44
memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
41
- if (offset >= 0x20 && offset < 0x40) {
45
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
42
+ if (offset >= TX_DATA_FIFO_PORT_FIRST &&
43
+ offset <= TX_DATA_FIFO_PORT_LAST) {
44
/* TX FIFO */
45
tx_fifo_push(s, val);
46
return;
46
return;
47
@@ -XXX,XX +XXX,XX @@ static uint64_t lan9118_readl(void *opaque, hwaddr offset,
48
lan9118_state *s = (lan9118_state *)opaque;
49
50
//DPRINTF("Read reg 0x%02x\n", (int)offset);
51
- if (offset < 0x20) {
52
+ if (offset <= RX_DATA_FIFO_PORT_LAST) {
53
/* RX FIFO */
54
return rx_fifo_pop(s);
47
}
55
}
48
56
switch (offset) {
49
- if (!s->mainclk_frq) {
57
- case 0x40:
50
- error_setg(errp, "MAINCLK_FRQ property was not set");
58
+ case RX_STATUS_FIFO_PORT:
51
- return;
59
return rx_status_fifo_pop(s);
52
+ if (!clock_has_source(s->mainclk)) {
60
- case 0x44:
53
+ error_setg(errp, "MAINCLK clock was not connected");
61
+ case RX_STATUS_FIFO_PEEK:
54
+ }
62
return s->rx_status_fifo[s->rx_status_fifo_head];
55
+ if (!clock_has_source(s->s32kclk)) {
63
- case 0x48:
56
+ error_setg(errp, "S32KCLK clock was not connected");
64
+ case TX_STATUS_FIFO_PORT:
57
}
65
return tx_status_fifo_pop(s);
58
66
- case 0x4c:
59
assert(info->num_cpus <= SSE_MAX_CPUS);
67
+ case TX_STATUS_FIFO_PEEK:
60
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
68
return s->tx_status_fifo[s->tx_status_fifo_head];
61
*/
69
case CSR_ID_REV:
62
sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->container);
70
return 0x01180001;
63
64
- system_clock_scale = NANOSECONDS_PER_SECOND / s->mainclk_frq;
65
+ /* Set initial system_clock_scale from MAINCLK */
66
+ armsse_mainclk_update(s);
67
}
68
69
static void armsse_idau_check(IDAUInterface *ii, uint32_t address,
70
--
71
--
71
2.20.1
72
2.20.1
72
73
73
74
diff view generated by jsdifflib
1
Switch the CMSDK APB dualtimer device over to using its Clock input;
1
From: Hao Wu <wuhaotsh@google.com>
2
the pclk-frq property is now ignored.
3
2
3
This patch allows NPCM7XX CLK module to compute clocks that are used by
4
other NPCM7XX modules.
5
6
Add a new struct NPCM7xxClockConverterState which represents a
7
single converter. Each clock converter in CLK module represents one
8
converter in NPCM7XX CLK Module(PLL, SEL or Divider). Each converter
9
takes one or more input clocks and converts them into one output clock.
10
They form a clock hierarchy in the CLK module and are responsible for
11
outputing clocks for various other modules in an NPCM7XX SoC.
12
13
Each converter has a function pointer called "convert" which represents
14
the unique logic for that converter.
15
16
The clock contains two initialization information: ConverterInitInfo and
17
ConverterConnectionInfo. They represent the vertices and edges in the
18
clock diagram respectively.
19
20
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
21
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
22
Signed-off-by: Hao Wu <wuhaotsh@google.com>
23
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
24
Message-id: 20210108190945.949196-2-wuhaotsh@google.com
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Luc Michel <luc@lmichel.fr>
6
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20210128114145.20536-20-peter.maydell@linaro.org
9
Message-id: 20210121190622.22000-20-peter.maydell@linaro.org
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
---
26
---
12
hw/timer/cmsdk-apb-dualtimer.c | 42 ++++++++++++++++++++++++++++++----
27
include/hw/misc/npcm7xx_clk.h | 140 +++++-
13
1 file changed, 37 insertions(+), 5 deletions(-)
28
hw/misc/npcm7xx_clk.c | 805 +++++++++++++++++++++++++++++++++-
29
2 files changed, 932 insertions(+), 13 deletions(-)
14
30
15
diff --git a/hw/timer/cmsdk-apb-dualtimer.c b/hw/timer/cmsdk-apb-dualtimer.c
31
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
16
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/timer/cmsdk-apb-dualtimer.c
33
--- a/include/hw/misc/npcm7xx_clk.h
18
+++ b/hw/timer/cmsdk-apb-dualtimer.c
34
+++ b/include/hw/misc/npcm7xx_clk.h
19
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_dualtimer_update(CMSDKAPBDualTimer *s)
35
@@ -XXX,XX +XXX,XX @@
20
qemu_set_irq(s->timerintc, timintc);
36
#define NPCM7XX_CLK_H
21
}
37
22
38
#include "exec/memory.h"
23
+static int cmsdk_dualtimermod_divisor(CMSDKAPBDualTimerModule *m)
39
+#include "hw/clock.h"
24
+{
40
#include "hw/sysbus.h"
25
+ /* Return the divisor set by the current CONTROL.PRESCALE value */
41
26
+ switch (FIELD_EX32(m->control, CONTROL, PRESCALE)) {
42
/*
27
+ case 0:
43
@@ -XXX,XX +XXX,XX @@
28
+ return 1;
44
29
+ case 1:
45
#define NPCM7XX_WATCHDOG_RESET_GPIO_IN "npcm7xx-clk-watchdog-reset-gpio-in"
30
+ return 16;
46
31
+ case 2:
47
-typedef struct NPCM7xxCLKState {
32
+ case 3: /* UNDEFINED, we treat like 2 (and complained when it was set) */
48
+/* Maximum amount of clock inputs in a SEL module. */
33
+ return 256;
49
+#define NPCM7XX_CLK_SEL_MAX_INPUT 5
50
+
51
+/* PLLs in CLK module. */
52
+typedef enum NPCM7xxClockPLL {
53
+ NPCM7XX_CLOCK_PLL0,
54
+ NPCM7XX_CLOCK_PLL1,
55
+ NPCM7XX_CLOCK_PLL2,
56
+ NPCM7XX_CLOCK_PLLG,
57
+ NPCM7XX_CLOCK_NR_PLLS,
58
+} NPCM7xxClockPLL;
59
+
60
+/* SEL/MUX in CLK module. */
61
+typedef enum NPCM7xxClockSEL {
62
+ NPCM7XX_CLOCK_PIXCKSEL,
63
+ NPCM7XX_CLOCK_MCCKSEL,
64
+ NPCM7XX_CLOCK_CPUCKSEL,
65
+ NPCM7XX_CLOCK_CLKOUTSEL,
66
+ NPCM7XX_CLOCK_UARTCKSEL,
67
+ NPCM7XX_CLOCK_TIMCKSEL,
68
+ NPCM7XX_CLOCK_SDCKSEL,
69
+ NPCM7XX_CLOCK_GFXMSEL,
70
+ NPCM7XX_CLOCK_SUCKSEL,
71
+ NPCM7XX_CLOCK_NR_SELS,
72
+} NPCM7xxClockSEL;
73
+
74
+/* Dividers in CLK module. */
75
+typedef enum NPCM7xxClockDivider {
76
+ NPCM7XX_CLOCK_PLL1D2, /* PLL1/2 */
77
+ NPCM7XX_CLOCK_PLL2D2, /* PLL2/2 */
78
+ NPCM7XX_CLOCK_MC_DIVIDER,
79
+ NPCM7XX_CLOCK_AXI_DIVIDER,
80
+ NPCM7XX_CLOCK_AHB_DIVIDER,
81
+ NPCM7XX_CLOCK_AHB3_DIVIDER,
82
+ NPCM7XX_CLOCK_SPI0_DIVIDER,
83
+ NPCM7XX_CLOCK_SPIX_DIVIDER,
84
+ NPCM7XX_CLOCK_APB1_DIVIDER,
85
+ NPCM7XX_CLOCK_APB2_DIVIDER,
86
+ NPCM7XX_CLOCK_APB3_DIVIDER,
87
+ NPCM7XX_CLOCK_APB4_DIVIDER,
88
+ NPCM7XX_CLOCK_APB5_DIVIDER,
89
+ NPCM7XX_CLOCK_CLKOUT_DIVIDER,
90
+ NPCM7XX_CLOCK_UART_DIVIDER,
91
+ NPCM7XX_CLOCK_TIMER_DIVIDER,
92
+ NPCM7XX_CLOCK_ADC_DIVIDER,
93
+ NPCM7XX_CLOCK_MMC_DIVIDER,
94
+ NPCM7XX_CLOCK_SDHC_DIVIDER,
95
+ NPCM7XX_CLOCK_GFXM_DIVIDER, /* divide by 3 */
96
+ NPCM7XX_CLOCK_UTMI_DIVIDER,
97
+ NPCM7XX_CLOCK_NR_DIVIDERS,
98
+} NPCM7xxClockConverter;
99
+
100
+typedef struct NPCM7xxCLKState NPCM7xxCLKState;
101
+
102
+/**
103
+ * struct NPCM7xxClockPLLState - A PLL module in CLK module.
104
+ * @name: The name of the module.
105
+ * @clk: The CLK module that owns this module.
106
+ * @clock_in: The input clock of this module.
107
+ * @clock_out: The output clock of this module.
108
+ * @reg: The control registers for this PLL module.
109
+ */
110
+typedef struct NPCM7xxClockPLLState {
111
+ DeviceState parent;
112
+
113
+ const char *name;
114
+ NPCM7xxCLKState *clk;
115
+ Clock *clock_in;
116
+ Clock *clock_out;
117
+
118
+ int reg;
119
+} NPCM7xxClockPLLState;
120
+
121
+/**
122
+ * struct NPCM7xxClockSELState - A SEL module in CLK module.
123
+ * @name: The name of the module.
124
+ * @clk: The CLK module that owns this module.
125
+ * @input_size: The size of inputs of this module.
126
+ * @clock_in: The input clocks of this module.
127
+ * @clock_out: The output clocks of this module.
128
+ * @offset: The offset of this module in the control register.
129
+ * @len: The length of this module in the control register.
130
+ */
131
+typedef struct NPCM7xxClockSELState {
132
+ DeviceState parent;
133
+
134
+ const char *name;
135
+ NPCM7xxCLKState *clk;
136
+ uint8_t input_size;
137
+ Clock *clock_in[NPCM7XX_CLK_SEL_MAX_INPUT];
138
+ Clock *clock_out;
139
+
140
+ int offset;
141
+ int len;
142
+} NPCM7xxClockSELState;
143
+
144
+/**
145
+ * struct NPCM7xxClockDividerState - A Divider module in CLK module.
146
+ * @name: The name of the module.
147
+ * @clk: The CLK module that owns this module.
148
+ * @clock_in: The input clock of this module.
149
+ * @clock_out: The output clock of this module.
150
+ * @divide: The function the divider uses to divide the input.
151
+ * @reg: The index of the control register that contains the divisor.
152
+ * @offset: The offset of the divisor in the control register.
153
+ * @len: The length of the divisor in the control register.
154
+ * @divisor: The divisor for a constant divisor
155
+ */
156
+typedef struct NPCM7xxClockDividerState {
157
+ DeviceState parent;
158
+
159
+ const char *name;
160
+ NPCM7xxCLKState *clk;
161
+ Clock *clock_in;
162
+ Clock *clock_out;
163
+
164
+ uint32_t (*divide)(struct NPCM7xxClockDividerState *s);
165
+ union {
166
+ struct {
167
+ int reg;
168
+ int offset;
169
+ int len;
170
+ };
171
+ int divisor;
172
+ };
173
+} NPCM7xxClockDividerState;
174
+
175
+struct NPCM7xxCLKState {
176
SysBusDevice parent;
177
178
MemoryRegion iomem;
179
180
+ /* Clock converters */
181
+ NPCM7xxClockPLLState plls[NPCM7XX_CLOCK_NR_PLLS];
182
+ NPCM7xxClockSELState sels[NPCM7XX_CLOCK_NR_SELS];
183
+ NPCM7xxClockDividerState dividers[NPCM7XX_CLOCK_NR_DIVIDERS];
184
+
185
uint32_t regs[NPCM7XX_CLK_NR_REGS];
186
187
/* Time reference for SECCNT and CNTR25M, initialized by power on reset */
188
int64_t ref_ns;
189
-} NPCM7xxCLKState;
190
+
191
+ /* The incoming reference clock. */
192
+ Clock *clkref;
193
+};
194
195
#define TYPE_NPCM7XX_CLK "npcm7xx-clk"
196
#define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), TYPE_NPCM7XX_CLK)
197
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
198
index XXXXXXX..XXXXXXX 100644
199
--- a/hw/misc/npcm7xx_clk.c
200
+++ b/hw/misc/npcm7xx_clk.c
201
@@ -XXX,XX +XXX,XX @@
202
203
#include "hw/misc/npcm7xx_clk.h"
204
#include "hw/timer/npcm7xx_timer.h"
205
+#include "hw/qdev-clock.h"
206
#include "migration/vmstate.h"
207
#include "qemu/error-report.h"
208
#include "qemu/log.h"
209
@@ -XXX,XX +XXX,XX @@
210
#include "trace.h"
211
#include "sysemu/watchdog.h"
212
213
+/*
214
+ * The reference clock hz, and the SECCNT and CNTR25M registers in this module,
215
+ * is always 25 MHz.
216
+ */
217
+#define NPCM7XX_CLOCK_REF_HZ (25000000)
218
+
219
+/* Register Field Definitions */
220
+#define NPCM7XX_CLK_WDRCR_CA9C BIT(0) /* Cortex A9 Cores */
221
+
222
#define PLLCON_LOKI BIT(31)
223
#define PLLCON_LOKS BIT(30)
224
#define PLLCON_PWDEN BIT(12)
225
+#define PLLCON_FBDV(con) extract32((con), 16, 12)
226
+#define PLLCON_OTDV2(con) extract32((con), 13, 3)
227
+#define PLLCON_OTDV1(con) extract32((con), 8, 3)
228
+#define PLLCON_INDV(con) extract32((con), 0, 6)
229
230
enum NPCM7xxCLKRegisters {
231
NPCM7XX_CLK_CLKEN1,
232
@@ -XXX,XX +XXX,XX @@ static const uint32_t cold_reset_values[NPCM7XX_CLK_NR_REGS] = {
233
[NPCM7XX_CLK_AHBCKFI] = 0x000000c8,
234
};
235
236
-/* Register Field Definitions */
237
-#define NPCM7XX_CLK_WDRCR_CA9C BIT(0) /* Cortex A9 Cores */
238
-
239
/* The number of watchdogs that can trigger a reset. */
240
#define NPCM7XX_NR_WATCHDOGS (3)
241
242
+/* Clock converter functions */
243
+
244
+#define TYPE_NPCM7XX_CLOCK_PLL "npcm7xx-clock-pll"
245
+#define NPCM7XX_CLOCK_PLL(obj) OBJECT_CHECK(NPCM7xxClockPLLState, \
246
+ (obj), TYPE_NPCM7XX_CLOCK_PLL)
247
+#define TYPE_NPCM7XX_CLOCK_SEL "npcm7xx-clock-sel"
248
+#define NPCM7XX_CLOCK_SEL(obj) OBJECT_CHECK(NPCM7xxClockSELState, \
249
+ (obj), TYPE_NPCM7XX_CLOCK_SEL)
250
+#define TYPE_NPCM7XX_CLOCK_DIVIDER "npcm7xx-clock-divider"
251
+#define NPCM7XX_CLOCK_DIVIDER(obj) OBJECT_CHECK(NPCM7xxClockDividerState, \
252
+ (obj), TYPE_NPCM7XX_CLOCK_DIVIDER)
253
+
254
+static void npcm7xx_clk_update_pll(void *opaque)
255
+{
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;
34
+ default:
329
+ default:
35
+ g_assert_not_reached();
330
+ g_assert_not_reached();
36
+ }
331
+ }
37
+}
332
+}
38
+
333
+
39
static void cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m,
334
+static void npcm7xx_clk_update_all_plls(NPCM7xxCLKState *clk)
40
uint32_t newctrl)
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)
41
{
843
{
42
@@ -XXX,XX +XXX,XX @@ static void cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m,
844
uint32_t reg = offset / sizeof(uint32_t);
43
default:
845
@@ -XXX,XX +XXX,XX @@ static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size)
44
g_assert_not_reached();
846
*
847
* The 4 LSBs are always zero: (1e9 / 640) << 4 = 25000000.
848
*/
849
- value = (((now_ns - s->ref_ns) / 640) << 4) % NPCM7XX_TIMER_REF_HZ;
850
+ value = (((now_ns - s->ref_ns) / 640) << 4) % NPCM7XX_CLOCK_REF_HZ;
851
break;
852
853
default:
854
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_write(void *opaque, hwaddr offset,
855
value |= (value & PLLCON_LOKS);
856
}
45
}
857
}
46
- ptimer_set_freq(m->timer, m->parent->pclk_frq / divisor);
858
+ /* Only update PLL when it is locked. */
47
+ ptimer_set_period_from_clock(m->timer, m->parent->timclk, divisor);
859
+ if (value & PLLCON_LOKI) {
48
}
860
+ npcm7xx_clk_update_pll(&s->plls[find_pll_by_reg(reg)]);
49
861
+ }
50
if (changed & R_CONTROL_MODE_MASK) {
862
+ break;
51
@@ -XXX,XX +XXX,XX @@ static void cmsdk_dualtimermod_reset(CMSDKAPBDualTimerModule *m)
863
+
52
* limit must both be set to 0xffff, so we wrap at 16 bits.
864
+ case NPCM7XX_CLK_CLKSEL:
53
*/
865
+ npcm7xx_clk_update_all_sels(s);
54
ptimer_set_limit(m->timer, 0xffff, 1);
866
+ break;
55
- ptimer_set_freq(m->timer, m->parent->pclk_frq);
867
+
56
+ ptimer_set_period_from_clock(m->timer, m->parent->timclk,
868
+ case NPCM7XX_CLK_CLKDIV1:
57
+ cmsdk_dualtimermod_divisor(m));
869
+ case NPCM7XX_CLK_CLKDIV2:
58
ptimer_transaction_commit(m->timer);
870
+ case NPCM7XX_CLK_CLKDIV3:
59
}
871
+ npcm7xx_clk_update_all_dividers(s);
60
872
break;
61
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_dualtimer_reset(DeviceState *dev)
873
62
s->timeritop = 0;
874
case NPCM7XX_CLK_CNTR25M:
63
}
875
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_enter_reset(Object *obj, ResetType type)
64
876
case RESET_TYPE_COLD:
65
+static void cmsdk_apb_dualtimer_clk_update(void *opaque)
877
memcpy(s->regs, cold_reset_values, sizeof(cold_reset_values));
66
+{
878
s->ref_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
67
+ CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque);
879
+ npcm7xx_clk_update_all_clocks(s);
68
+ int i;
69
+
70
+ for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
71
+ CMSDKAPBDualTimerModule *m = &s->timermod[i];
72
+ ptimer_transaction_begin(m->timer);
73
+ ptimer_set_period_from_clock(m->timer, m->parent->timclk,
74
+ cmsdk_dualtimermod_divisor(m));
75
+ ptimer_transaction_commit(m->timer);
76
+ }
77
+}
78
+
79
static void cmsdk_apb_dualtimer_init(Object *obj)
80
{
81
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
82
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_dualtimer_init(Object *obj)
83
for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
84
sysbus_init_irq(sbd, &s->timermod[i].timerint);
85
}
86
- s->timclk = qdev_init_clock_in(DEVICE(s), "TIMCLK", NULL, NULL);
87
+ s->timclk = qdev_init_clock_in(DEVICE(s), "TIMCLK",
88
+ cmsdk_apb_dualtimer_clk_update, s);
89
}
90
91
static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
92
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
93
CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(dev);
94
int i;
95
96
- if (s->pclk_frq == 0) {
97
- error_setg(errp, "CMSDK APB timer: pclk-frq property must be set");
98
+ if (!clock_has_source(s->timclk)) {
99
+ error_setg(errp, "CMSDK APB dualtimer: TIMCLK clock must be connected");
100
return;
880
return;
101
}
881
}
102
882
883
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_enter_reset(Object *obj, ResetType type)
884
__func__, type);
885
}
886
887
+static void npcm7xx_clk_init_clock_hierarchy(NPCM7xxCLKState *s)
888
+{
889
+ int i;
890
+
891
+ s->clkref = qdev_init_clock_in(DEVICE(s), "clkref", NULL, NULL);
892
+
893
+ /* First pass: init all converter modules */
894
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(pll_init_info_list) != NPCM7XX_CLOCK_NR_PLLS);
895
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(sel_init_info_list) != NPCM7XX_CLOCK_NR_SELS);
896
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(divider_init_info_list)
897
+ != NPCM7XX_CLOCK_NR_DIVIDERS);
898
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
899
+ object_initialize_child(OBJECT(s), pll_init_info_list[i].name,
900
+ &s->plls[i], TYPE_NPCM7XX_CLOCK_PLL);
901
+ npcm7xx_init_clock_pll(&s->plls[i], s,
902
+ &pll_init_info_list[i]);
903
+ }
904
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
905
+ object_initialize_child(OBJECT(s), sel_init_info_list[i].name,
906
+ &s->sels[i], TYPE_NPCM7XX_CLOCK_SEL);
907
+ npcm7xx_init_clock_sel(&s->sels[i], s,
908
+ &sel_init_info_list[i]);
909
+ }
910
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
911
+ object_initialize_child(OBJECT(s), divider_init_info_list[i].name,
912
+ &s->dividers[i], TYPE_NPCM7XX_CLOCK_DIVIDER);
913
+ npcm7xx_init_clock_divider(&s->dividers[i], s,
914
+ &divider_init_info_list[i]);
915
+ }
916
+
917
+ /* Second pass: connect converter modules */
918
+ npcm7xx_connect_clocks(s);
919
+
920
+ clock_update_hz(s->clkref, NPCM7XX_CLOCK_REF_HZ);
921
+}
922
+
923
static void npcm7xx_clk_init(Object *obj)
924
{
925
NPCM7xxCLKState *s = NPCM7XX_CLK(obj);
926
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_init(Object *obj)
927
memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s,
928
TYPE_NPCM7XX_CLK, 4 * KiB);
929
sysbus_init_mmio(&s->parent, &s->iomem);
930
- qdev_init_gpio_in_named(DEVICE(s), npcm7xx_clk_perform_watchdog_reset,
931
- NPCM7XX_WATCHDOG_RESET_GPIO_IN, NPCM7XX_NR_WATCHDOGS);
932
}
933
934
-static const VMStateDescription vmstate_npcm7xx_clk = {
935
- .name = "npcm7xx-clk",
936
+static int npcm7xx_clk_post_load(void *opaque, int version_id)
937
+{
938
+ if (version_id >= 1) {
939
+ NPCM7xxCLKState *clk = opaque;
940
+
941
+ npcm7xx_clk_update_all_clocks(clk);
942
+ }
943
+
944
+ return 0;
945
+}
946
+
947
+static void npcm7xx_clk_realize(DeviceState *dev, Error **errp)
948
+{
949
+ int i;
950
+ NPCM7xxCLKState *s = NPCM7XX_CLK(dev);
951
+
952
+ qdev_init_gpio_in_named(DEVICE(s), npcm7xx_clk_perform_watchdog_reset,
953
+ NPCM7XX_WATCHDOG_RESET_GPIO_IN, NPCM7XX_NR_WATCHDOGS);
954
+ npcm7xx_clk_init_clock_hierarchy(s);
955
+
956
+ /* Realize child devices */
957
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
958
+ if (!qdev_realize(DEVICE(&s->plls[i]), NULL, errp)) {
959
+ return;
960
+ }
961
+ }
962
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
963
+ if (!qdev_realize(DEVICE(&s->sels[i]), NULL, errp)) {
964
+ return;
965
+ }
966
+ }
967
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
968
+ if (!qdev_realize(DEVICE(&s->dividers[i]), NULL, errp)) {
969
+ return;
970
+ }
971
+ }
972
+}
973
+
974
+static const VMStateDescription vmstate_npcm7xx_clk_pll = {
975
+ .name = "npcm7xx-clock-pll",
976
.version_id = 0,
977
.minimum_version_id = 0,
978
- .fields = (VMStateField[]) {
979
- VMSTATE_UINT32_ARRAY(regs, NPCM7xxCLKState, NPCM7XX_CLK_NR_REGS),
980
- VMSTATE_INT64(ref_ns, NPCM7xxCLKState),
981
+ .fields = (VMStateField[]) {
982
+ VMSTATE_CLOCK(clock_in, NPCM7xxClockPLLState),
983
VMSTATE_END_OF_LIST(),
984
},
985
};
986
987
+static const VMStateDescription vmstate_npcm7xx_clk_sel = {
988
+ .name = "npcm7xx-clock-sel",
989
+ .version_id = 0,
990
+ .minimum_version_id = 0,
991
+ .fields = (VMStateField[]) {
992
+ VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(clock_in, NPCM7xxClockSELState,
993
+ NPCM7XX_CLK_SEL_MAX_INPUT, 0, vmstate_clock, Clock),
994
+ VMSTATE_END_OF_LIST(),
995
+ },
996
+};
997
+
998
+static const VMStateDescription vmstate_npcm7xx_clk_divider = {
999
+ .name = "npcm7xx-clock-divider",
1000
+ .version_id = 0,
1001
+ .minimum_version_id = 0,
1002
+ .fields = (VMStateField[]) {
1003
+ VMSTATE_CLOCK(clock_in, NPCM7xxClockDividerState),
1004
+ VMSTATE_END_OF_LIST(),
1005
+ },
1006
+};
1007
+
1008
+static const VMStateDescription vmstate_npcm7xx_clk = {
1009
+ .name = "npcm7xx-clk",
1010
+ .version_id = 1,
1011
+ .minimum_version_id = 1,
1012
+ .post_load = npcm7xx_clk_post_load,
1013
+ .fields = (VMStateField[]) {
1014
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxCLKState, NPCM7XX_CLK_NR_REGS),
1015
+ VMSTATE_INT64(ref_ns, NPCM7xxCLKState),
1016
+ VMSTATE_CLOCK(clkref, NPCM7xxCLKState),
1017
+ VMSTATE_END_OF_LIST(),
1018
+ },
1019
+};
1020
+
1021
+static void npcm7xx_clk_pll_class_init(ObjectClass *klass, void *data)
1022
+{
1023
+ DeviceClass *dc = DEVICE_CLASS(klass);
1024
+
1025
+ dc->desc = "NPCM7xx Clock PLL Module";
1026
+ dc->vmsd = &vmstate_npcm7xx_clk_pll;
1027
+}
1028
+
1029
+static void npcm7xx_clk_sel_class_init(ObjectClass *klass, void *data)
1030
+{
1031
+ DeviceClass *dc = DEVICE_CLASS(klass);
1032
+
1033
+ dc->desc = "NPCM7xx Clock SEL Module";
1034
+ dc->vmsd = &vmstate_npcm7xx_clk_sel;
1035
+}
1036
+
1037
+static void npcm7xx_clk_divider_class_init(ObjectClass *klass, void *data)
1038
+{
1039
+ DeviceClass *dc = DEVICE_CLASS(klass);
1040
+
1041
+ dc->desc = "NPCM7xx Clock Divider Module";
1042
+ dc->vmsd = &vmstate_npcm7xx_clk_divider;
1043
+}
1044
+
1045
static void npcm7xx_clk_class_init(ObjectClass *klass, void *data)
1046
{
1047
ResettableClass *rc = RESETTABLE_CLASS(klass);
1048
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_class_init(ObjectClass *klass, void *data)
1049
1050
dc->desc = "NPCM7xx Clock Control Registers";
1051
dc->vmsd = &vmstate_npcm7xx_clk;
1052
+ dc->realize = npcm7xx_clk_realize;
1053
rc->phases.enter = npcm7xx_clk_enter_reset;
1054
}
1055
1056
+static const TypeInfo npcm7xx_clk_pll_info = {
1057
+ .name = TYPE_NPCM7XX_CLOCK_PLL,
1058
+ .parent = TYPE_DEVICE,
1059
+ .instance_size = sizeof(NPCM7xxClockPLLState),
1060
+ .instance_init = npcm7xx_clk_pll_init,
1061
+ .class_init = npcm7xx_clk_pll_class_init,
1062
+};
1063
+
1064
+static const TypeInfo npcm7xx_clk_sel_info = {
1065
+ .name = TYPE_NPCM7XX_CLOCK_SEL,
1066
+ .parent = TYPE_DEVICE,
1067
+ .instance_size = sizeof(NPCM7xxClockSELState),
1068
+ .instance_init = npcm7xx_clk_sel_init,
1069
+ .class_init = npcm7xx_clk_sel_class_init,
1070
+};
1071
+
1072
+static const TypeInfo npcm7xx_clk_divider_info = {
1073
+ .name = TYPE_NPCM7XX_CLOCK_DIVIDER,
1074
+ .parent = TYPE_DEVICE,
1075
+ .instance_size = sizeof(NPCM7xxClockDividerState),
1076
+ .instance_init = npcm7xx_clk_divider_init,
1077
+ .class_init = npcm7xx_clk_divider_class_init,
1078
+};
1079
+
1080
static const TypeInfo npcm7xx_clk_info = {
1081
.name = TYPE_NPCM7XX_CLK,
1082
.parent = TYPE_SYS_BUS_DEVICE,
1083
@@ -XXX,XX +XXX,XX @@ static const TypeInfo npcm7xx_clk_info = {
1084
1085
static void npcm7xx_clk_register_type(void)
1086
{
1087
+ type_register_static(&npcm7xx_clk_pll_info);
1088
+ type_register_static(&npcm7xx_clk_sel_info);
1089
+ type_register_static(&npcm7xx_clk_divider_info);
1090
type_register_static(&npcm7xx_clk_info);
1091
}
1092
type_init(npcm7xx_clk_register_type);
103
--
1093
--
104
2.20.1
1094
2.20.1
105
1095
106
1096
diff view generated by jsdifflib
1
Create two input clocks on the ARMSSE devices, one for the normal
1
From: Hao Wu <wuhaotsh@google.com>
2
MAINCLK, and one for the 32KHz S32KCLK, and wire these up to the
3
appropriate devices. The old property-based clock frequency setting
4
will remain in place until conversion is complete.
5
2
6
This is a migration compatibility break for machines mps2-an505,
3
This patch makes NPCM7XX Timer to use a the timer clock generated by the
7
mps2-an521, musca-a, musca-b1.
4
CLK module instead of the magic number TIMER_REF_HZ.
8
5
6
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
7
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
8
Signed-off-by: Hao Wu <wuhaotsh@google.com>
9
Message-id: 20210108190945.949196-3-wuhaotsh@google.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Luc Michel <luc@lmichel.fr>
12
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Message-id: 20210128114145.20536-12-peter.maydell@linaro.org
14
Message-id: 20210121190622.22000-12-peter.maydell@linaro.org
15
---
12
---
16
include/hw/arm/armsse.h | 6 ++++++
13
include/hw/misc/npcm7xx_clk.h | 6 -----
17
hw/arm/armsse.c | 17 +++++++++++++++--
14
include/hw/timer/npcm7xx_timer.h | 1 +
18
2 files changed, 21 insertions(+), 2 deletions(-)
15
hw/arm/npcm7xx.c | 5 ++++
16
hw/timer/npcm7xx_timer.c | 39 +++++++++++++++-----------------
17
4 files changed, 24 insertions(+), 27 deletions(-)
19
18
20
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
19
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
21
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/arm/armsse.h
21
--- a/include/hw/misc/npcm7xx_clk.h
23
+++ b/include/hw/arm/armsse.h
22
+++ b/include/hw/misc/npcm7xx_clk.h
24
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@
25
* per-CPU identity and control register blocks
24
#include "hw/clock.h"
26
*
25
#include "hw/sysbus.h"
27
* QEMU interface:
26
28
+ * + Clock input "MAINCLK": clock for CPUs and most peripherals
27
-/*
29
+ * + Clock input "S32KCLK": slow 32KHz clock used for a few peripherals
28
- * The reference clock frequency for the timer modules, and the SECCNT and
30
* + QOM property "memory" is a MemoryRegion containing the devices provided
29
- * CNTR25M registers in this module, is always 25 MHz.
31
* by the board model.
30
- */
32
* + QOM property "MAINCLK_FRQ" is the frequency of the main system clock
31
-#define NPCM7XX_TIMER_REF_HZ (25000000)
32
-
33
/*
34
* Number of registers in our device state structure. Don't change this without
35
* incrementing the version_id in the vmstate.
36
diff --git a/include/hw/timer/npcm7xx_timer.h b/include/hw/timer/npcm7xx_timer.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/hw/timer/npcm7xx_timer.h
39
+++ b/include/hw/timer/npcm7xx_timer.h
40
@@ -XXX,XX +XXX,XX @@ struct NPCM7xxTimerCtrlState {
41
42
uint32_t tisr;
43
44
+ Clock *clock;
45
NPCM7xxTimer timer[NPCM7XX_TIMERS_PER_CTRL];
46
NPCM7xxWatchdogTimer watchdog_timer;
47
};
48
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/arm/npcm7xx.c
51
+++ b/hw/arm/npcm7xx.c
33
@@ -XXX,XX +XXX,XX @@
52
@@ -XXX,XX +XXX,XX @@
34
#include "hw/misc/armsse-mhu.h"
53
#include "hw/char/serial.h"
54
#include "hw/loader.h"
35
#include "hw/misc/unimp.h"
55
#include "hw/misc/unimp.h"
36
#include "hw/or-irq.h"
56
+#include "hw/qdev-clock.h"
37
+#include "hw/clock.h"
57
#include "hw/qdev-properties.h"
38
#include "hw/core/split-irq.h"
58
#include "qapi/error.h"
39
#include "hw/cpu/cluster.h"
59
#include "qemu/units.h"
40
#include "qom/object.h"
60
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
41
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
61
int first_irq;
42
62
int j;
43
uint32_t nsccfg;
63
44
64
+ /* Connect the timer clock. */
45
+ Clock *mainclk;
65
+ qdev_connect_clock_in(DEVICE(&s->tim[i]), "clock", qdev_get_clock_out(
46
+ Clock *s32kclk;
66
+ DEVICE(&s->clk), "timer-clock"));
47
+
67
+
48
/* Properties */
68
sysbus_realize(sbd, &error_abort);
49
MemoryRegion *board_memory;
69
sysbus_mmio_map(sbd, 0, npcm7xx_tim_addr[i]);
50
uint32_t exp_numirq;
70
51
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
71
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
52
index XXXXXXX..XXXXXXX 100644
72
index XXXXXXX..XXXXXXX 100644
53
--- a/hw/arm/armsse.c
73
--- a/hw/timer/npcm7xx_timer.c
54
+++ b/hw/arm/armsse.c
74
+++ b/hw/timer/npcm7xx_timer.c
55
@@ -XXX,XX +XXX,XX @@
75
@@ -XXX,XX +XXX,XX @@
56
#include "hw/arm/armsse.h"
76
#include "qemu/osdep.h"
57
#include "hw/arm/boot.h"
77
58
#include "hw/irq.h"
78
#include "hw/irq.h"
59
+#include "hw/qdev-clock.h"
79
+#include "hw/qdev-clock.h"
60
80
#include "hw/qdev-properties.h"
61
/* Format of the System Information block SYS_CONFIG register */
81
-#include "hw/misc/npcm7xx_clk.h"
62
typedef enum SysConfigFormat {
82
#include "hw/timer/npcm7xx_timer.h"
63
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
83
#include "migration/vmstate.h"
64
assert(info->sram_banks <= MAX_SRAM_BANKS);
84
#include "qemu/bitops.h"
65
assert(info->num_cpus <= SSE_MAX_CPUS);
85
@@ -XXX,XX +XXX,XX @@ static uint32_t npcm7xx_tcsr_prescaler(uint32_t tcsr)
66
86
/* Convert a timer cycle count to a time interval in nanoseconds. */
67
+ s->mainclk = qdev_init_clock_in(DEVICE(s), "MAINCLK", NULL, NULL);
87
static int64_t npcm7xx_timer_count_to_ns(NPCM7xxTimer *t, uint32_t count)
68
+ s->s32kclk = qdev_init_clock_in(DEVICE(s), "S32KCLK", NULL, NULL);
88
{
69
+
89
- int64_t ns = count;
70
memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
90
+ int64_t ticks = count;
71
91
72
for (i = 0; i < info->num_cpus; i++) {
92
- ns *= NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ;
73
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
93
- ns *= npcm7xx_tcsr_prescaler(t->tcsr);
74
* map its upstream ends to the right place in the container.
94
+ ticks *= npcm7xx_tcsr_prescaler(t->tcsr);
95
96
- return ns;
97
+ return clock_ticks_to_ns(t->ctrl->clock, ticks);
98
}
99
100
/* Convert a time interval in nanoseconds to a timer cycle count. */
101
static uint32_t npcm7xx_timer_ns_to_count(NPCM7xxTimer *t, int64_t ns)
102
{
103
- int64_t count;
104
-
105
- count = ns / (NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ);
106
- count /= npcm7xx_tcsr_prescaler(t->tcsr);
107
-
108
- return count;
109
+ return ns / clock_ticks_to_ns(t->ctrl->clock,
110
+ npcm7xx_tcsr_prescaler(t->tcsr));
111
}
112
113
static uint32_t npcm7xx_watchdog_timer_prescaler(const NPCM7xxWatchdogTimer *t)
114
@@ -XXX,XX +XXX,XX @@ static uint32_t npcm7xx_watchdog_timer_prescaler(const NPCM7xxWatchdogTimer *t)
115
static void npcm7xx_watchdog_timer_reset_cycles(NPCM7xxWatchdogTimer *t,
116
int64_t cycles)
117
{
118
- uint32_t prescaler = npcm7xx_watchdog_timer_prescaler(t);
119
- int64_t ns = (NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ) * cycles;
120
+ int64_t ticks = cycles * npcm7xx_watchdog_timer_prescaler(t);
121
+ int64_t ns = clock_ticks_to_ns(t->ctrl->clock, ticks);
122
123
/*
124
* The reset function always clears the current timer. The caller of the
125
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_watchdog_timer_reset_cycles(NPCM7xxWatchdogTimer *t,
75
*/
126
*/
76
qdev_prop_set_uint32(DEVICE(&s->timer0), "pclk-frq", s->mainclk_frq);
127
npcm7xx_timer_clear(&t->base_timer);
77
+ qdev_connect_clock_in(DEVICE(&s->timer0), "pclk", s->mainclk);
128
78
if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer0), errp)) {
129
- ns *= prescaler;
79
return;
130
t->base_timer.remaining_ns = ns;
80
}
131
}
81
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
132
82
&error_abort);
133
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_hold_reset(Object *obj)
83
134
qemu_irq_lower(s->watchdog_timer.irq);
84
qdev_prop_set_uint32(DEVICE(&s->timer1), "pclk-frq", s->mainclk_frq);
135
}
85
+ qdev_connect_clock_in(DEVICE(&s->timer1), "pclk", s->mainclk);
136
86
if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer1), errp)) {
137
-static void npcm7xx_timer_realize(DeviceState *dev, Error **errp)
87
return;
138
+static void npcm7xx_timer_init(Object *obj)
88
}
139
{
89
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
140
- NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(dev);
90
&error_abort);
141
- SysBusDevice *sbd = &s->parent;
91
142
+ NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(obj);
92
qdev_prop_set_uint32(DEVICE(&s->dualtimer), "pclk-frq", s->mainclk_frq);
143
+ DeviceState *dev = DEVICE(obj);
93
+ qdev_connect_clock_in(DEVICE(&s->dualtimer), "TIMCLK", s->mainclk);
144
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
94
if (!sysbus_realize(SYS_BUS_DEVICE(&s->dualtimer), errp)) {
145
int i;
95
return;
146
NPCM7xxWatchdogTimer *w;
96
}
147
97
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
148
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_realize(DeviceState *dev, Error **errp)
98
* 0x4002f000: S32K timer
149
npcm7xx_watchdog_timer_expired, w);
99
*/
150
sysbus_init_irq(sbd, &w->irq);
100
qdev_prop_set_uint32(DEVICE(&s->s32ktimer), "pclk-frq", S32KCLK);
151
101
+ qdev_connect_clock_in(DEVICE(&s->s32ktimer), "pclk", s->s32kclk);
152
- memory_region_init_io(&s->iomem, OBJECT(s), &npcm7xx_timer_ops, s,
102
if (!sysbus_realize(SYS_BUS_DEVICE(&s->s32ktimer), errp)) {
153
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_timer_ops, s,
103
return;
154
TYPE_NPCM7XX_TIMER, 4 * KiB);
104
}
155
sysbus_init_mmio(sbd, &s->iomem);
105
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
156
qdev_init_gpio_out_named(dev, &w->reset_signal,
106
qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0));
157
NPCM7XX_WATCHDOG_RESET_GPIO_OUT, 1);
107
158
+ s->clock = qdev_init_clock_in(dev, "clock", NULL, NULL);
108
qdev_prop_set_uint32(DEVICE(&s->s32kwatchdog), "wdogclk-frq", S32KCLK);
159
}
109
+ qdev_connect_clock_in(DEVICE(&s->s32kwatchdog), "WDOGCLK", s->s32kclk);
160
110
if (!sysbus_realize(SYS_BUS_DEVICE(&s->s32kwatchdog), errp)) {
161
static const VMStateDescription vmstate_npcm7xx_base_timer = {
111
return;
162
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_npcm7xx_watchdog_timer = {
112
}
163
113
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
164
static const VMStateDescription vmstate_npcm7xx_timer_ctrl = {
114
/* 0x40080000 .. 0x4008ffff : ARMSSE second Base peripheral region */
165
.name = "npcm7xx-timer-ctrl",
115
116
qdev_prop_set_uint32(DEVICE(&s->nswatchdog), "wdogclk-frq", s->mainclk_frq);
117
+ qdev_connect_clock_in(DEVICE(&s->nswatchdog), "WDOGCLK", s->mainclk);
118
if (!sysbus_realize(SYS_BUS_DEVICE(&s->nswatchdog), errp)) {
119
return;
120
}
121
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
122
sysbus_mmio_map(SYS_BUS_DEVICE(&s->nswatchdog), 0, 0x40081000);
123
124
qdev_prop_set_uint32(DEVICE(&s->swatchdog), "wdogclk-frq", s->mainclk_frq);
125
+ qdev_connect_clock_in(DEVICE(&s->swatchdog), "WDOGCLK", s->mainclk);
126
if (!sysbus_realize(SYS_BUS_DEVICE(&s->swatchdog), errp)) {
127
return;
128
}
129
@@ -XXX,XX +XXX,XX @@ static void armsse_idau_check(IDAUInterface *ii, uint32_t address,
130
131
static const VMStateDescription armsse_vmstate = {
132
.name = "iotkit",
133
- .version_id = 1,
166
- .version_id = 1,
134
- .minimum_version_id = 1,
167
- .minimum_version_id = 1,
135
+ .version_id = 2,
168
+ .version_id = 2,
136
+ .minimum_version_id = 2,
169
+ .minimum_version_id = 2,
137
.fields = (VMStateField[]) {
170
.fields = (VMStateField[]) {
138
+ VMSTATE_CLOCK(mainclk, ARMSSE),
171
VMSTATE_UINT32(tisr, NPCM7xxTimerCtrlState),
139
+ VMSTATE_CLOCK(s32kclk, ARMSSE),
172
+ VMSTATE_CLOCK(clock, NPCM7xxTimerCtrlState),
140
VMSTATE_UINT32(nsccfg, ARMSSE),
173
VMSTATE_STRUCT_ARRAY(timer, NPCM7xxTimerCtrlState,
141
VMSTATE_END_OF_LIST()
174
NPCM7XX_TIMERS_PER_CTRL, 0, vmstate_npcm7xx_timer,
142
}
175
NPCM7xxTimer),
176
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_class_init(ObjectClass *klass, void *data)
177
QEMU_BUILD_BUG_ON(NPCM7XX_TIMER_REGS_END > NPCM7XX_TIMER_NR_REGS);
178
179
dc->desc = "NPCM7xx Timer Controller";
180
- dc->realize = npcm7xx_timer_realize;
181
dc->vmsd = &vmstate_npcm7xx_timer_ctrl;
182
rc->phases.enter = npcm7xx_timer_enter_reset;
183
rc->phases.hold = npcm7xx_timer_hold_reset;
184
@@ -XXX,XX +XXX,XX @@ static const TypeInfo npcm7xx_timer_info = {
185
.parent = TYPE_SYS_BUS_DEVICE,
186
.instance_size = sizeof(NPCM7xxTimerCtrlState),
187
.class_init = npcm7xx_timer_class_init,
188
+ .instance_init = npcm7xx_timer_init,
189
};
190
191
static void npcm7xx_timer_register_type(void)
143
--
192
--
144
2.20.1
193
2.20.1
145
194
146
195
diff view generated by jsdifflib
1
Add a simple test of the CMSDK dual timer, since we're about to do
1
From: Hao Wu <wuhaotsh@google.com>
2
some refactoring of how it is clocked.
3
2
3
The ADC is part of NPCM7XX Module. Its behavior is controled by the
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.
6
7
Users can alter input value by using qom-set QMP command.
8
9
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
10
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
11
Signed-off-by: Hao Wu <wuhaotsh@google.com>
12
Message-id: 20210108190945.949196-4-wuhaotsh@google.com
13
[PMM: Added missing hw/adc/trace.h file]
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
8
Message-id: 20210128114145.20536-6-peter.maydell@linaro.org
9
Message-id: 20210121190622.22000-6-peter.maydell@linaro.org
10
---
16
---
11
tests/qtest/cmsdk-apb-dualtimer-test.c | 130 +++++++++++++++++++++++++
17
docs/system/arm/nuvoton.rst | 2 +-
12
MAINTAINERS | 1 +
18
meson.build | 1 +
13
tests/qtest/meson.build | 1 +
19
hw/adc/trace.h | 1 +
14
3 files changed, 132 insertions(+)
20
include/hw/adc/npcm7xx_adc.h | 69 ++++++
15
create mode 100644 tests/qtest/cmsdk-apb-dualtimer-test.c
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
16
34
17
diff --git a/tests/qtest/cmsdk-apb-dualtimer-test.c b/tests/qtest/cmsdk-apb-dualtimer-test.c
35
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
36
index XXXXXXX..XXXXXXX 100644
37
--- a/docs/system/arm/nuvoton.rst
38
+++ b/docs/system/arm/nuvoton.rst
39
@@ -XXX,XX +XXX,XX @@ Supported devices
40
* Random Number Generator (RNG)
41
* USB host (USBH)
42
* GPIO controller
43
+ * Analog to Digital Converter (ADC)
44
45
Missing devices
46
---------------
47
@@ -XXX,XX +XXX,XX @@ Missing devices
48
* USB device (USBD)
49
* SMBus controller (SMBF)
50
* Peripheral SPI controller (PSPI)
51
- * Analog to Digital Converter (ADC)
52
* SD/MMC host
53
* PECI interface
54
* Pulse Width Modulation (PWM)
55
diff --git a/meson.build b/meson.build
56
index XXXXXXX..XXXXXXX 100644
57
--- a/meson.build
58
+++ b/meson.build
59
@@ -XXX,XX +XXX,XX @@ if have_system
60
'chardev',
61
'hw/9pfs',
62
'hw/acpi',
63
+ 'hw/adc',
64
'hw/alpha',
65
'hw/arm',
66
'hw/audio',
67
diff --git a/hw/adc/trace.h b/hw/adc/trace.h
18
new file mode 100644
68
new file mode 100644
19
index XXXXXXX..XXXXXXX
69
index XXXXXXX..XXXXXXX
20
--- /dev/null
70
--- /dev/null
21
+++ b/tests/qtest/cmsdk-apb-dualtimer-test.c
71
+++ b/hw/adc/trace.h
72
@@ -0,0 +1 @@
73
+#include "trace/trace-hw_adc.h"
74
diff --git a/include/hw/adc/npcm7xx_adc.h b/include/hw/adc/npcm7xx_adc.h
75
new file mode 100644
76
index XXXXXXX..XXXXXXX
77
--- /dev/null
78
+++ b/include/hw/adc/npcm7xx_adc.h
22
@@ -XXX,XX +XXX,XX @@
79
@@ -XXX,XX +XXX,XX @@
23
+/*
80
+/*
24
+ * QTest testcase for the CMSDK APB dualtimer device
81
+ * Nuvoton NPCM7xx ADC Module
25
+ *
82
+ *
26
+ * Copyright (c) 2021 Linaro Limited
83
+ * Copyright 2020 Google LLC
27
+ *
84
+ *
28
+ * This program is free software; you can redistribute it and/or modify it
85
+ * This program is free software; you can redistribute it and/or modify it
29
+ * under the terms of the GNU General Public License as published by the
86
+ * under the terms of the GNU General Public License as published by the
30
+ * Free Software Foundation; either version 2 of the License, or
87
+ * Free Software Foundation; either version 2 of the License, or
31
+ * (at your option) any later version.
88
+ * (at your option) any later version.
32
+ *
89
+ *
33
+ * This program is distributed in the hope that it will be useful, but WITHOUT
90
+ * This program is distributed in the hope that it will be useful, but WITHOUT
34
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
91
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
35
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
92
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
36
+ * for more details.
93
+ * for more details.
37
+ */
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
+ */
38
+
190
+
39
+#include "qemu/osdep.h"
191
+#include "qemu/osdep.h"
40
+#include "libqtest-single.h"
192
+#include "hw/adc/npcm7xx_adc.h"
41
+
193
+#include "hw/qdev-clock.h"
42
+/* IoTKit/ARMSSE dualtimer; driven at 25MHz in mps2-an385, so 40ns per tick */
194
+#include "hw/qdev-properties.h"
43
+#define TIMER_BASE 0x40002000
195
+#include "hw/registerfields.h"
44
+
196
+#include "migration/vmstate.h"
45
+#define TIMER1LOAD 0
197
+#include "qemu/log.h"
46
+#define TIMER1VALUE 4
198
+#include "qemu/module.h"
47
+#define TIMER1CONTROL 8
199
+#include "qemu/timer.h"
48
+#define TIMER1INTCLR 0xc
200
+#include "qemu/units.h"
49
+#define TIMER1RIS 0x10
201
+#include "trace.h"
50
+#define TIMER1MIS 0x14
202
+
51
+#define TIMER1BGLOAD 0x18
203
+REG32(NPCM7XX_ADC_CON, 0x0)
52
+
204
+REG32(NPCM7XX_ADC_DATA, 0x4)
53
+#define TIMER2LOAD 0x20
205
+
54
+#define TIMER2VALUE 0x24
206
+/* Register field definitions. */
55
+#define TIMER2CONTROL 0x28
207
+#define NPCM7XX_ADC_CON_MUX(rv) extract32(rv, 24, 4)
56
+#define TIMER2INTCLR 0x2c
208
+#define NPCM7XX_ADC_CON_INT_EN BIT(21)
57
+#define TIMER2RIS 0x30
209
+#define NPCM7XX_ADC_CON_REFSEL BIT(19)
58
+#define TIMER2MIS 0x34
210
+#define NPCM7XX_ADC_CON_INT BIT(18)
59
+#define TIMER2BGLOAD 0x38
211
+#define NPCM7XX_ADC_CON_EN BIT(17)
60
+
212
+#define NPCM7XX_ADC_CON_RST BIT(16)
61
+#define CTRL_ENABLE (1 << 7)
213
+#define NPCM7XX_ADC_CON_CONV BIT(14)
62
+#define CTRL_PERIODIC (1 << 6)
214
+#define NPCM7XX_ADC_CON_DIV(rv) extract32(rv, 1, 8)
63
+#define CTRL_INTEN (1 << 5)
215
+
64
+#define CTRL_PRESCALE_1 (0 << 2)
216
+#define NPCM7XX_ADC_MAX_RESULT 1023
65
+#define CTRL_PRESCALE_16 (1 << 2)
217
+#define NPCM7XX_ADC_DEFAULT_IREF 2000000
66
+#define CTRL_PRESCALE_256 (2 << 2)
218
+#define NPCM7XX_ADC_CONV_CYCLES 20
67
+#define CTRL_32BIT (1 << 1)
219
+#define NPCM7XX_ADC_RESET_CYCLES 10
68
+#define CTRL_ONESHOT (1 << 0)
220
+#define NPCM7XX_ADC_R0_INPUT 500000
69
+
221
+#define NPCM7XX_ADC_R1_INPUT 1500000
70
+static void test_dualtimer(void)
222
+
71
+{
223
+static void npcm7xx_adc_reset(NPCM7xxADCState *s)
72
+ g_assert_true(readl(TIMER_BASE + TIMER1RIS) == 0);
224
+{
73
+
225
+ timer_del(&s->conv_timer);
74
+ /* Start timer: will fire after 40000 ns */
226
+ s->con = 0x000c0001;
75
+ writel(TIMER_BASE + TIMER1LOAD, 1000);
227
+ s->data = 0x00000000;
76
+ /* enable in free-running, wrapping, interrupt mode */
228
+}
77
+ writel(TIMER_BASE + TIMER1CONTROL, CTRL_ENABLE | CTRL_INTEN);
229
+
78
+
230
+static uint32_t npcm7xx_adc_convert(uint32_t input, uint32_t ref)
79
+ /* Step to just past the 500th tick and check VALUE */
231
+{
80
+ clock_step(500 * 40 + 1);
232
+ uint32_t result;
81
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER1RIS), ==, 0);
233
+
82
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER1VALUE), ==, 500);
234
+ result = input * (NPCM7XX_ADC_MAX_RESULT + 1) / ref;
83
+
235
+ if (result > NPCM7XX_ADC_MAX_RESULT) {
84
+ /* Just past the 1000th tick: timer should have fired */
236
+ result = NPCM7XX_ADC_MAX_RESULT;
85
+ clock_step(500 * 40);
237
+ }
86
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER1RIS), ==, 1);
238
+
87
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER1VALUE), ==, 0);
239
+ return result;
240
+}
241
+
242
+static uint32_t npcm7xx_adc_prescaler(NPCM7xxADCState *s)
243
+{
244
+ return 2 * (NPCM7XX_ADC_CON_DIV(s->con) + 1);
245
+}
246
+
247
+static void npcm7xx_adc_start_timer(Clock *clk, QEMUTimer *timer,
248
+ uint32_t cycles, uint32_t prescaler)
249
+{
250
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
251
+ int64_t ticks = cycles;
252
+ int64_t ns;
253
+
254
+ ticks *= prescaler;
255
+ ns = clock_ticks_to_ns(clk, ticks);
256
+ ns += now;
257
+ timer_mod(timer, ns);
258
+}
259
+
260
+static void npcm7xx_adc_start_convert(NPCM7xxADCState *s)
261
+{
262
+ uint32_t prescaler = npcm7xx_adc_prescaler(s);
263
+
264
+ npcm7xx_adc_start_timer(s->clock, &s->conv_timer, NPCM7XX_ADC_CONV_CYCLES,
265
+ prescaler);
266
+}
267
+
268
+static void npcm7xx_adc_convert_done(void *opaque)
269
+{
270
+ NPCM7xxADCState *s = opaque;
271
+ uint32_t input = NPCM7XX_ADC_CON_MUX(s->con);
272
+ uint32_t ref = (s->con & NPCM7XX_ADC_CON_REFSEL)
273
+ ? s->iref : s->vref;
274
+
275
+ if (input >= NPCM7XX_ADC_NUM_INPUTS) {
276
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid input: %u\n",
277
+ __func__, input);
278
+ return;
279
+ }
280
+ s->data = npcm7xx_adc_convert(s->adci[input], ref);
281
+ if (s->con & NPCM7XX_ADC_CON_INT_EN) {
282
+ s->con |= NPCM7XX_ADC_CON_INT;
283
+ qemu_irq_raise(s->irq);
284
+ }
285
+ s->con &= ~NPCM7XX_ADC_CON_CONV;
286
+}
287
+
288
+static void npcm7xx_adc_calibrate(NPCM7xxADCState *adc)
289
+{
290
+ adc->calibration_r_values[0] = npcm7xx_adc_convert(NPCM7XX_ADC_R0_INPUT,
291
+ adc->iref);
292
+ adc->calibration_r_values[1] = npcm7xx_adc_convert(NPCM7XX_ADC_R1_INPUT,
293
+ adc->iref);
294
+}
295
+
296
+static void npcm7xx_adc_write_con(NPCM7xxADCState *s, uint32_t new_con)
297
+{
298
+ uint32_t old_con = s->con;
299
+
300
+ /* Write ADC_INT to 1 to clear it */
301
+ if (new_con & NPCM7XX_ADC_CON_INT) {
302
+ new_con &= ~NPCM7XX_ADC_CON_INT;
303
+ qemu_irq_lower(s->irq);
304
+ } else if (old_con & NPCM7XX_ADC_CON_INT) {
305
+ new_con |= NPCM7XX_ADC_CON_INT;
306
+ }
307
+
308
+ s->con = new_con;
309
+
310
+ if (s->con & NPCM7XX_ADC_CON_RST) {
311
+ npcm7xx_adc_reset(s);
312
+ return;
313
+ }
314
+
315
+ if ((s->con & NPCM7XX_ADC_CON_EN)) {
316
+ if (s->con & NPCM7XX_ADC_CON_CONV) {
317
+ if (!(old_con & NPCM7XX_ADC_CON_CONV)) {
318
+ npcm7xx_adc_start_convert(s);
319
+ }
320
+ } else {
321
+ timer_del(&s->conv_timer);
322
+ }
323
+ }
324
+}
325
+
326
+static uint64_t npcm7xx_adc_read(void *opaque, hwaddr offset, unsigned size)
327
+{
328
+ uint64_t value = 0;
329
+ NPCM7xxADCState *s = opaque;
330
+
331
+ switch (offset) {
332
+ case A_NPCM7XX_ADC_CON:
333
+ value = s->con;
334
+ break;
335
+
336
+ case A_NPCM7XX_ADC_DATA:
337
+ value = s->data;
338
+ break;
339
+
340
+ default:
341
+ qemu_log_mask(LOG_GUEST_ERROR,
342
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
343
+ __func__, offset);
344
+ break;
345
+ }
346
+
347
+ trace_npcm7xx_adc_read(DEVICE(s)->canonical_path, offset, value);
348
+ return value;
349
+}
350
+
351
+static void npcm7xx_adc_write(void *opaque, hwaddr offset, uint64_t v,
352
+ unsigned size)
353
+{
354
+ NPCM7xxADCState *s = opaque;
355
+
356
+ trace_npcm7xx_adc_write(DEVICE(s)->canonical_path, offset, v);
357
+ switch (offset) {
358
+ case A_NPCM7XX_ADC_CON:
359
+ npcm7xx_adc_write_con(s, v);
360
+ break;
361
+
362
+ case A_NPCM7XX_ADC_DATA:
363
+ qemu_log_mask(LOG_GUEST_ERROR,
364
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
365
+ __func__, offset);
366
+ break;
367
+
368
+ default:
369
+ qemu_log_mask(LOG_GUEST_ERROR,
370
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
371
+ __func__, offset);
372
+ break;
373
+ }
374
+
375
+}
376
+
377
+static const struct MemoryRegionOps npcm7xx_adc_ops = {
378
+ .read = npcm7xx_adc_read,
379
+ .write = npcm7xx_adc_write,
380
+ .endianness = DEVICE_LITTLE_ENDIAN,
381
+ .valid = {
382
+ .min_access_size = 4,
383
+ .max_access_size = 4,
384
+ .unaligned = false,
385
+ },
386
+};
387
+
388
+static void npcm7xx_adc_enter_reset(Object *obj, ResetType type)
389
+{
390
+ NPCM7xxADCState *s = NPCM7XX_ADC(obj);
391
+
392
+ npcm7xx_adc_reset(s);
393
+}
394
+
395
+static void npcm7xx_adc_hold_reset(Object *obj)
396
+{
397
+ NPCM7xxADCState *s = NPCM7XX_ADC(obj);
398
+
399
+ qemu_irq_lower(s->irq);
400
+}
401
+
402
+static void npcm7xx_adc_init(Object *obj)
403
+{
404
+ NPCM7xxADCState *s = NPCM7XX_ADC(obj);
405
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
406
+ int i;
407
+
408
+ sysbus_init_irq(sbd, &s->irq);
409
+
410
+ timer_init_ns(&s->conv_timer, QEMU_CLOCK_VIRTUAL,
411
+ npcm7xx_adc_convert_done, s);
412
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_adc_ops, s,
413
+ TYPE_NPCM7XX_ADC, 4 * KiB);
414
+ sysbus_init_mmio(sbd, &s->iomem);
415
+ s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL);
416
+
417
+ for (i = 0; i < NPCM7XX_ADC_NUM_INPUTS; ++i) {
418
+ object_property_add_uint32_ptr(obj, "adci[*]",
419
+ &s->adci[i], OBJ_PROP_FLAG_WRITE);
420
+ }
421
+ object_property_add_uint32_ptr(obj, "vref",
422
+ &s->vref, OBJ_PROP_FLAG_WRITE);
423
+ npcm7xx_adc_calibrate(s);
424
+}
425
+
426
+static const VMStateDescription vmstate_npcm7xx_adc = {
427
+ .name = "npcm7xx-adc",
428
+ .version_id = 0,
429
+ .minimum_version_id = 0,
430
+ .fields = (VMStateField[]) {
431
+ VMSTATE_TIMER(conv_timer, NPCM7xxADCState),
432
+ VMSTATE_UINT32(con, NPCM7xxADCState),
433
+ VMSTATE_UINT32(data, NPCM7xxADCState),
434
+ VMSTATE_CLOCK(clock, NPCM7xxADCState),
435
+ VMSTATE_UINT32_ARRAY(adci, NPCM7xxADCState, NPCM7XX_ADC_NUM_INPUTS),
436
+ VMSTATE_UINT32(vref, NPCM7xxADCState),
437
+ VMSTATE_UINT32(iref, NPCM7xxADCState),
438
+ VMSTATE_UINT16_ARRAY(calibration_r_values, NPCM7xxADCState,
439
+ NPCM7XX_ADC_NUM_CALIB),
440
+ VMSTATE_END_OF_LIST(),
441
+ },
442
+};
443
+
444
+static Property npcm7xx_timer_properties[] = {
445
+ DEFINE_PROP_UINT32("iref", NPCM7xxADCState, iref, NPCM7XX_ADC_DEFAULT_IREF),
446
+ DEFINE_PROP_END_OF_LIST(),
447
+};
448
+
449
+static void npcm7xx_adc_class_init(ObjectClass *klass, void *data)
450
+{
451
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
452
+ DeviceClass *dc = DEVICE_CLASS(klass);
453
+
454
+ dc->desc = "NPCM7xx ADC Module";
455
+ dc->vmsd = &vmstate_npcm7xx_adc;
456
+ rc->phases.enter = npcm7xx_adc_enter_reset;
457
+ rc->phases.hold = npcm7xx_adc_hold_reset;
458
+
459
+ device_class_set_props(dc, npcm7xx_timer_properties);
460
+}
461
+
462
+static const TypeInfo npcm7xx_adc_info = {
463
+ .name = TYPE_NPCM7XX_ADC,
464
+ .parent = TYPE_SYS_BUS_DEVICE,
465
+ .instance_size = sizeof(NPCM7xxADCState),
466
+ .class_init = npcm7xx_adc_class_init,
467
+ .instance_init = npcm7xx_adc_init,
468
+};
469
+
470
+static void npcm7xx_adc_register_types(void)
471
+{
472
+ type_register_static(&npcm7xx_adc_info);
473
+}
474
+
475
+type_init(npcm7xx_adc_register_types);
476
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
477
index XXXXXXX..XXXXXXX 100644
478
--- a/hw/arm/npcm7xx.c
479
+++ b/hw/arm/npcm7xx.c
480
@@ -XXX,XX +XXX,XX @@
481
#define NPCM7XX_EHCI_BA (0xf0806000)
482
#define NPCM7XX_OHCI_BA (0xf0807000)
483
484
+/* ADC Module */
485
+#define NPCM7XX_ADC_BA (0xf000c000)
486
+
487
/* Internal AHB SRAM */
488
#define NPCM7XX_RAM3_BA (0xc0008000)
489
#define NPCM7XX_RAM3_SZ (4 * KiB)
490
@@ -XXX,XX +XXX,XX @@
491
#define NPCM7XX_ROM_BA (0xffff0000)
492
#define NPCM7XX_ROM_SZ (64 * KiB)
493
494
+
495
/* Clock configuration values to be fixed up when bypassing bootloader */
496
497
/* Run PLL1 at 1600 MHz */
498
@@ -XXX,XX +XXX,XX @@
499
* interrupts.
500
*/
501
enum NPCM7xxInterrupt {
502
+ NPCM7XX_ADC_IRQ = 0,
503
NPCM7XX_UART0_IRQ = 2,
504
NPCM7XX_UART1_IRQ,
505
NPCM7XX_UART2_IRQ,
506
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init_fuses(NPCM7xxState *s)
507
sizeof(value));
508
}
509
510
+static void npcm7xx_write_adc_calibration(NPCM7xxState *s)
511
+{
512
+ /* Both ADC and the fuse array must have realized. */
513
+ QEMU_BUILD_BUG_ON(sizeof(s->adc.calibration_r_values) != 4);
514
+ npcm7xx_otp_array_write(&s->fuse_array, s->adc.calibration_r_values,
515
+ NPCM7XX_FUSE_ADC_CALIB, sizeof(s->adc.calibration_r_values));
516
+}
517
+
518
static qemu_irq npcm7xx_irq(NPCM7xxState *s, int n)
519
{
520
return qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
521
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
522
TYPE_NPCM7XX_FUSE_ARRAY);
523
object_initialize_child(obj, "mc", &s->mc, TYPE_NPCM7XX_MC);
524
object_initialize_child(obj, "rng", &s->rng, TYPE_NPCM7XX_RNG);
525
+ object_initialize_child(obj, "adc", &s->adc, TYPE_NPCM7XX_ADC);
526
527
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
528
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
529
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
530
sysbus_realize(SYS_BUS_DEVICE(&s->mc), &error_abort);
531
sysbus_mmio_map(SYS_BUS_DEVICE(&s->mc), 0, NPCM7XX_MC_BA);
532
533
+ /* ADC Modules. Cannot fail. */
534
+ qdev_connect_clock_in(DEVICE(&s->adc), "clock", qdev_get_clock_out(
535
+ DEVICE(&s->clk), "adc-clock"));
536
+ sysbus_realize(SYS_BUS_DEVICE(&s->adc), &error_abort);
537
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->adc), 0, NPCM7XX_ADC_BA);
538
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->adc), 0,
539
+ npcm7xx_irq(s, NPCM7XX_ADC_IRQ));
540
+ npcm7xx_write_adc_calibration(s);
541
+
542
/* Timer Modules (TIM). Cannot fail. */
543
QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
544
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
545
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
546
create_unimplemented_device("npcm7xx.vdmx", 0xe0800000, 4 * KiB);
547
create_unimplemented_device("npcm7xx.pcierc", 0xe1000000, 64 * KiB);
548
create_unimplemented_device("npcm7xx.kcs", 0xf0007000, 4 * KiB);
549
- create_unimplemented_device("npcm7xx.adc", 0xf000c000, 4 * KiB);
550
create_unimplemented_device("npcm7xx.gfxi", 0xf000e000, 4 * KiB);
551
create_unimplemented_device("npcm7xx.gpio[0]", 0xf0010000, 4 * KiB);
552
create_unimplemented_device("npcm7xx.gpio[1]", 0xf0011000, 4 * KiB);
553
diff --git a/tests/qtest/npcm7xx_adc-test.c b/tests/qtest/npcm7xx_adc-test.c
554
new file mode 100644
555
index XXXXXXX..XXXXXXX
556
--- /dev/null
557
+++ b/tests/qtest/npcm7xx_adc-test.c
558
@@ -XXX,XX +XXX,XX @@
559
+/*
560
+ * QTests for Nuvoton NPCM7xx ADCModules.
561
+ *
562
+ * Copyright 2020 Google LLC
563
+ *
564
+ * This program is free software; you can redistribute it and/or modify it
565
+ * under the terms of the GNU General Public License as published by the
566
+ * Free Software Foundation; either version 2 of the License, or
567
+ * (at your option) any later version.
568
+ *
569
+ * This program is distributed in the hope that it will be useful, but WITHOUT
570
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
571
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
572
+ * for more details.
573
+ */
574
+
575
+#include "qemu/osdep.h"
576
+#include "qemu/bitops.h"
577
+#include "qemu/timer.h"
578
+#include "libqos/libqtest.h"
579
+#include "qapi/qmp/qdict.h"
580
+
581
+#define REF_HZ (25000000)
582
+
583
+#define CON_OFFSET 0x0
584
+#define DATA_OFFSET 0x4
585
+
586
+#define NUM_INPUTS 8
587
+#define DEFAULT_IREF 2000000
588
+#define CONV_CYCLES 20
589
+#define RESET_CYCLES 10
590
+#define R0_INPUT 500000
591
+#define R1_INPUT 1500000
592
+#define MAX_RESULT 1023
593
+
594
+#define DEFAULT_CLKDIV 5
595
+
596
+#define FUSE_ARRAY_BA 0xf018a000
597
+#define FCTL_OFFSET 0x14
598
+#define FST_OFFSET 0x0
599
+#define FADDR_OFFSET 0x4
600
+#define FDATA_OFFSET 0x8
601
+#define ADC_CALIB_ADDR 24
602
+#define FUSE_READ 0x2
603
+
604
+/* Register field definitions. */
605
+#define CON_MUX(rv) ((rv) << 24)
606
+#define CON_INT_EN BIT(21)
607
+#define CON_REFSEL BIT(19)
608
+#define CON_INT BIT(18)
609
+#define CON_EN BIT(17)
610
+#define CON_RST BIT(16)
611
+#define CON_CONV BIT(14)
612
+#define CON_DIV(rv) extract32(rv, 1, 8)
613
+
614
+#define FST_RDST BIT(1)
615
+#define FDATA_MASK 0xff
616
+
617
+#define MAX_ERROR 10000
618
+#define MIN_CALIB_INPUT 100000
619
+#define MAX_CALIB_INPUT 1800000
620
+
621
+static const uint32_t input_list[] = {
622
+ 100000,
623
+ 500000,
624
+ 1000000,
625
+ 1500000,
626
+ 1800000,
627
+ 2000000,
628
+};
629
+
630
+static const uint32_t vref_list[] = {
631
+ 2000000,
632
+ 2200000,
633
+ 2500000,
634
+};
635
+
636
+static const uint32_t iref_list[] = {
637
+ 1800000,
638
+ 1900000,
639
+ 2000000,
640
+ 2100000,
641
+ 2200000,
642
+};
643
+
644
+static const uint32_t div_list[] = {0, 1, 3, 7, 15};
645
+
646
+typedef struct ADC {
647
+ int irq;
648
+ uint64_t base_addr;
649
+} ADC;
650
+
651
+ADC adc = {
652
+ .irq = 0,
653
+ .base_addr = 0xf000c000
654
+};
655
+
656
+static uint32_t adc_read_con(QTestState *qts, const ADC *adc)
657
+{
658
+ return qtest_readl(qts, adc->base_addr + CON_OFFSET);
659
+}
660
+
661
+static void adc_write_con(QTestState *qts, const ADC *adc, uint32_t value)
662
+{
663
+ qtest_writel(qts, adc->base_addr + CON_OFFSET, value);
664
+}
665
+
666
+static uint32_t adc_read_data(QTestState *qts, const ADC *adc)
667
+{
668
+ return qtest_readl(qts, adc->base_addr + DATA_OFFSET);
669
+}
670
+
671
+static uint32_t adc_calibrate(uint32_t measured, uint32_t *rv)
672
+{
673
+ return R0_INPUT + (R1_INPUT - R0_INPUT) * (int32_t)(measured - rv[0])
674
+ / (int32_t)(rv[1] - rv[0]);
675
+}
676
+
677
+static void adc_qom_set(QTestState *qts, const ADC *adc,
678
+ const char *name, uint32_t value)
679
+{
680
+ QDict *response;
681
+ const char *path = "/machine/soc/adc";
682
+
683
+ g_test_message("Setting properties %s of %s with value %u",
684
+ name, path, value);
685
+ response = qtest_qmp(qts, "{ 'execute': 'qom-set',"
686
+ " 'arguments': { 'path': %s, 'property': %s, 'value': %u}}",
687
+ path, name, value);
688
+ /* The qom set message returns successfully. */
689
+ g_assert_true(qdict_haskey(response, "return"));
690
+}
691
+
692
+static void adc_write_input(QTestState *qts, const ADC *adc,
693
+ uint32_t index, uint32_t value)
694
+{
695
+ char name[100];
696
+
697
+ sprintf(name, "adci[%u]", index);
698
+ adc_qom_set(qts, adc, name, value);
699
+}
700
+
701
+static void adc_write_vref(QTestState *qts, const ADC *adc, uint32_t value)
702
+{
703
+ adc_qom_set(qts, adc, "vref", value);
704
+}
705
+
706
+static uint32_t adc_calculate_output(uint32_t input, uint32_t ref)
707
+{
708
+ uint32_t output;
709
+
710
+ g_assert_cmpuint(input, <=, ref);
711
+ output = (input * (MAX_RESULT + 1)) / ref;
712
+ if (output > MAX_RESULT) {
713
+ output = MAX_RESULT;
714
+ }
715
+
716
+ return output;
717
+}
718
+
719
+static uint32_t adc_prescaler(QTestState *qts, const ADC *adc)
720
+{
721
+ uint32_t div = extract32(adc_read_con(qts, adc), 1, 8);
722
+
723
+ return 2 * (div + 1);
724
+}
725
+
726
+static int64_t adc_calculate_steps(uint32_t cycles, uint32_t prescale,
727
+ uint32_t clkdiv)
728
+{
729
+ return (NANOSECONDS_PER_SECOND / (REF_HZ >> clkdiv)) * cycles * prescale;
730
+}
731
+
732
+static void adc_wait_conv_finished(QTestState *qts, const ADC *adc,
733
+ uint32_t clkdiv)
734
+{
735
+ uint32_t prescaler = adc_prescaler(qts, adc);
88
+
736
+
89
+ /*
737
+ /*
90
+ * We are in free-running wrapping 16-bit mode, so on the following
738
+ * ADC should takes roughly 20 cycles to convert one sample. So we assert it
91
+ * tick VALUE should have wrapped round to 0xffff.
739
+ * should take 10~30 cycles here.
92
+ */
740
+ */
93
+ clock_step(40);
741
+ qtest_clock_step(qts, adc_calculate_steps(CONV_CYCLES / 2, prescaler,
94
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER1VALUE), ==, 0xffff);
742
+ clkdiv));
95
+
743
+ /* ADC is still converting. */
96
+ /* Check that any write to INTCLR clears interrupt */
744
+ g_assert_true(adc_read_con(qts, adc) & CON_CONV);
97
+ writel(TIMER_BASE + TIMER1INTCLR, 1);
745
+ qtest_clock_step(qts, adc_calculate_steps(CONV_CYCLES, prescaler, clkdiv));
98
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER1RIS), ==, 0);
746
+ /* ADC has finished conversion. */
99
+
747
+ g_assert_false(adc_read_con(qts, adc) & CON_CONV);
100
+ /* Turn off the timer */
748
+}
101
+ writel(TIMER_BASE + TIMER1CONTROL, 0);
749
+
102
+}
750
+/* Check ADC can be reset to default value. */
103
+
751
+static void test_init(gconstpointer adc_p)
104
+static void test_prescale(void)
752
+{
105
+{
753
+ const ADC *adc = adc_p;
106
+ g_assert_true(readl(TIMER_BASE + TIMER2RIS) == 0);
754
+
107
+
755
+ QTestState *qts = qtest_init("-machine quanta-gsj");
108
+ /* Start timer: will fire after 40 * 256 * 1000 == 1024000 ns */
756
+ adc_write_con(qts, adc, CON_REFSEL | CON_INT);
109
+ writel(TIMER_BASE + TIMER2LOAD, 1000);
757
+ g_assert_cmphex(adc_read_con(qts, adc), ==, CON_REFSEL);
110
+ /* enable in periodic, wrapping, interrupt mode, prescale 256 */
758
+ qtest_quit(qts);
111
+ writel(TIMER_BASE + TIMER2CONTROL,
759
+}
112
+ CTRL_ENABLE | CTRL_INTEN | CTRL_PERIODIC | CTRL_PRESCALE_256);
760
+
113
+
761
+/* Check ADC can convert from an internal reference. */
114
+ /* Step to just past the 500th tick and check VALUE */
762
+static void test_convert_internal(gconstpointer adc_p)
115
+ clock_step(40 * 256 * 501);
763
+{
116
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER2RIS), ==, 0);
764
+ const ADC *adc = adc_p;
117
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER2VALUE), ==, 500);
765
+ uint32_t index, input, output, expected_output;
118
+
766
+ QTestState *qts = qtest_init("-machine quanta-gsj");
119
+ /* Just past the 1000th tick: timer should have fired */
767
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
120
+ clock_step(40 * 256 * 500);
768
+
121
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER2RIS), ==, 1);
769
+ for (index = 0; index < NUM_INPUTS; ++index) {
122
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER2VALUE), ==, 0);
770
+ for (size_t i = 0; i < ARRAY_SIZE(input_list); ++i) {
123
+
771
+ input = input_list[i];
124
+ /* In periodic mode the tick VALUE now reloads */
772
+ expected_output = adc_calculate_output(input, DEFAULT_IREF);
125
+ clock_step(40 * 256);
773
+
126
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER2VALUE), ==, 1000);
774
+ adc_write_input(qts, adc, index, input);
127
+
775
+ adc_write_con(qts, adc, CON_MUX(index) | CON_REFSEL | CON_INT |
128
+ /* Check that any write to INTCLR clears interrupt */
776
+ CON_EN | CON_CONV);
129
+ writel(TIMER_BASE + TIMER2INTCLR, 1);
777
+ adc_wait_conv_finished(qts, adc, DEFAULT_CLKDIV);
130
+ g_assert_cmpuint(readl(TIMER_BASE + TIMER2RIS), ==, 0);
778
+ g_assert_cmphex(adc_read_con(qts, adc), ==, CON_MUX(index) |
131
+
779
+ CON_REFSEL | CON_EN);
132
+ /* Turn off the timer */
780
+ g_assert_false(qtest_get_irq(qts, adc->irq));
133
+ writel(TIMER_BASE + TIMER2CONTROL, 0);
781
+ output = adc_read_data(qts, adc);
134
+}
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)
135
+
922
+
136
+int main(int argc, char **argv)
923
+int main(int argc, char **argv)
137
+{
924
+{
138
+ int r;
139
+
140
+ g_test_init(&argc, &argv, NULL);
925
+ g_test_init(&argc, &argv, NULL);
141
+
926
+
142
+ qtest_start("-machine mps2-an385");
927
+ add_test(init, &adc);
143
+
928
+ add_test(convert_internal, &adc);
144
+ qtest_add_func("/cmsdk-apb-dualtimer/dualtimer", test_dualtimer);
929
+ add_test(convert_external, &adc);
145
+ qtest_add_func("/cmsdk-apb-dualtimer/prescale", test_prescale);
930
+ add_test(interrupt, &adc);
146
+
931
+ add_test(reset, &adc);
147
+ r = g_test_run();
932
+ add_test(calibrate, &adc);
148
+
933
+
149
+ qtest_end();
934
+ return g_test_run();
150
+
935
+}
151
+ return r;
936
diff --git a/hw/adc/meson.build b/hw/adc/meson.build
152
+}
153
diff --git a/MAINTAINERS b/MAINTAINERS
154
index XXXXXXX..XXXXXXX 100644
937
index XXXXXXX..XXXXXXX 100644
155
--- a/MAINTAINERS
938
--- a/hw/adc/meson.build
156
+++ b/MAINTAINERS
939
+++ b/hw/adc/meson.build
157
@@ -XXX,XX +XXX,XX @@ F: include/hw/timer/cmsdk-apb-timer.h
940
@@ -1 +1,2 @@
158
F: tests/qtest/cmsdk-apb-timer-test.c
941
softmmu_ss.add(when: 'CONFIG_STM32F2XX_ADC', if_true: files('stm32f2xx_adc.c'))
159
F: hw/timer/cmsdk-apb-dualtimer.c
942
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_adc.c'))
160
F: include/hw/timer/cmsdk-apb-dualtimer.h
943
diff --git a/hw/adc/trace-events b/hw/adc/trace-events
161
+F: tests/qtest/cmsdk-apb-dualtimer-test.c
944
new file mode 100644
162
F: hw/char/cmsdk-apb-uart.c
945
index XXXXXXX..XXXXXXX
163
F: include/hw/char/cmsdk-apb-uart.h
946
--- /dev/null
164
F: hw/watchdog/cmsdk-apb-watchdog.c
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
165
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
954
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
166
index XXXXXXX..XXXXXXX 100644
955
index XXXXXXX..XXXXXXX 100644
167
--- a/tests/qtest/meson.build
956
--- a/tests/qtest/meson.build
168
+++ b/tests/qtest/meson.build
957
+++ b/tests/qtest/meson.build
169
@@ -XXX,XX +XXX,XX @@ qtests_npcm7xx = \
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',
170
'npcm7xx_timer-test',
966
'npcm7xx_timer-test',
171
'npcm7xx_watchdog_timer-test']
967
'npcm7xx_watchdog_timer-test']
172
qtests_arm = \
173
+ (config_all_devices.has_key('CONFIG_CMSDK_APB_DUALTIMER') ? ['cmsdk-apb-dualtimer-test'] : []) + \
174
(config_all_devices.has_key('CONFIG_CMSDK_APB_TIMER') ? ['cmsdk-apb-timer-test'] : []) + \
175
(config_all_devices.has_key('CONFIG_CMSDK_APB_WATCHDOG') ? ['cmsdk-apb-watchdog-test'] : []) + \
176
(config_all_devices.has_key('CONFIG_PFLASH_CFI02') ? ['pflash-cfi02-test'] : []) + \
177
--
968
--
178
2.20.1
969
2.20.1
179
970
180
971
diff view generated by jsdifflib
1
From: Mihai Carabas <mihai.carabas@oracle.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
To ease the PCI device addition in next patches, split the code as follows:
3
The PWM module is part of NPCM7XX module. Each NPCM7XX module has two
4
- generic code (read/write/setup) is being kept in pvpanic.c
4
identical PWM modules. Each module contains 4 PWM entries. Each PWM has
5
- ISA dependent code moved to pvpanic-isa.c
5
two outputs: frequency and duty_cycle. Both are computed using inputs
6
from software side.
6
7
7
Also, rename:
8
This module does not model detail pulse signals since it is expensive.
8
- ISA_PVPANIC_DEVICE -> PVPANIC_ISA_DEVICE.
9
It also does not model interrupts and watchdogs that are dependant on
9
- TYPE_PVPANIC -> TYPE_PVPANIC_ISA.
10
the detail models. The interfaces for these are left in the module so
10
- MemoryRegion io -> mr.
11
that anyone in need for these functionalities can implement on their
11
- pvpanic_ioport_* in pvpanic_*.
12
own.
12
13
13
Update the build system with the new files and config structure.
14
The user can read the duty cycle and frequency using qom-get command.
14
15
15
Signed-off-by: Mihai Carabas <mihai.carabas@oracle.com>
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
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
22
---
19
include/hw/misc/pvpanic.h | 23 +++++++++-
23
docs/system/arm/nuvoton.rst | 2 +-
20
hw/misc/pvpanic-isa.c | 94 +++++++++++++++++++++++++++++++++++++++
24
include/hw/arm/npcm7xx.h | 2 +
21
hw/misc/pvpanic.c | 85 +++--------------------------------
25
include/hw/misc/npcm7xx_pwm.h | 105 +++++++
22
hw/i386/Kconfig | 2 +-
26
hw/arm/npcm7xx.c | 26 +-
23
hw/misc/Kconfig | 6 ++-
27
hw/misc/npcm7xx_pwm.c | 550 ++++++++++++++++++++++++++++++++++
24
hw/misc/meson.build | 3 +-
28
hw/misc/meson.build | 1 +
25
tests/qtest/meson.build | 2 +-
29
hw/misc/trace-events | 6 +
26
7 files changed, 130 insertions(+), 85 deletions(-)
30
7 files changed, 689 insertions(+), 3 deletions(-)
27
create mode 100644 hw/misc/pvpanic-isa.c
31
create mode 100644 include/hw/misc/npcm7xx_pwm.h
32
create mode 100644 hw/misc/npcm7xx_pwm.c
28
33
29
diff --git a/include/hw/misc/pvpanic.h b/include/hw/misc/pvpanic.h
34
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
30
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
31
--- a/include/hw/misc/pvpanic.h
36
--- a/docs/system/arm/nuvoton.rst
32
+++ b/include/hw/misc/pvpanic.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
33
@@ -XXX,XX +XXX,XX @@
58
@@ -XXX,XX +XXX,XX @@
34
59
#include "hw/mem/npcm7xx_mc.h"
35
#include "qom/object.h"
60
#include "hw/misc/npcm7xx_clk.h"
36
61
#include "hw/misc/npcm7xx_gcr.h"
37
-#define TYPE_PVPANIC "pvpanic"
62
+#include "hw/misc/npcm7xx_pwm.h"
38
+#define TYPE_PVPANIC_ISA_DEVICE "pvpanic"
63
#include "hw/misc/npcm7xx_rng.h"
39
64
#include "hw/nvram/npcm7xx_otp.h"
40
#define PVPANIC_IOPORT_PROP "ioport"
65
#include "hw/timer/npcm7xx_timer.h"
41
66
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
42
+/* The bit of supported pv event, TODO: include uapi header and remove this */
67
NPCM7xxCLKState clk;
43
+#define PVPANIC_F_PANICKED 0
68
NPCM7xxTimerCtrlState tim[3];
44
+#define PVPANIC_F_CRASHLOADED 1
69
NPCM7xxADCState adc;
45
+
70
+ NPCM7xxPWMState pwm[2];
46
+/* The pv event value */
71
NPCM7xxOTPState key_storage;
47
+#define PVPANIC_PANICKED (1 << PVPANIC_F_PANICKED)
72
NPCM7xxOTPState fuse_array;
48
+#define PVPANIC_CRASHLOADED (1 << PVPANIC_F_CRASHLOADED)
73
NPCM7xxMCState mc;
49
+
74
diff --git a/include/hw/misc/npcm7xx_pwm.h b/include/hw/misc/npcm7xx_pwm.h
50
+/*
51
+ * PVPanicState for any device type
52
+ */
53
+typedef struct PVPanicState PVPanicState;
54
+struct PVPanicState {
55
+ MemoryRegion mr;
56
+ uint8_t events;
57
+};
58
+
59
+void pvpanic_setup_io(PVPanicState *s, DeviceState *dev, unsigned size);
60
+
61
static inline uint16_t pvpanic_port(void)
62
{
63
- Object *o = object_resolve_path_type("", TYPE_PVPANIC, NULL);
64
+ Object *o = object_resolve_path_type("", TYPE_PVPANIC_ISA_DEVICE, NULL);
65
if (!o) {
66
return 0;
67
}
68
diff --git a/hw/misc/pvpanic-isa.c b/hw/misc/pvpanic-isa.c
69
new file mode 100644
75
new file mode 100644
70
index XXXXXXX..XXXXXXX
76
index XXXXXXX..XXXXXXX
71
--- /dev/null
77
--- /dev/null
72
+++ b/hw/misc/pvpanic-isa.c
78
+++ b/include/hw/misc/npcm7xx_pwm.h
73
@@ -XXX,XX +XXX,XX @@
79
@@ -XXX,XX +XXX,XX @@
74
+/*
80
+/*
75
+ * QEMU simulated pvpanic device.
81
+ * Nuvoton NPCM7xx PWM Module
76
+ *
82
+ *
77
+ * Copyright Fujitsu, Corp. 2013
83
+ * Copyright 2020 Google LLC
78
+ *
84
+ *
79
+ * Authors:
85
+ * This program is free software; you can redistribute it and/or modify it
80
+ * Wen Congyang <wency@cn.fujitsu.com>
86
+ * under the terms of the GNU General Public License as published by the
81
+ * Hu Tao <hutao@cn.fujitsu.com>
87
+ * Free Software Foundation; either version 2 of the License, or
88
+ * (at your option) any later version.
82
+ *
89
+ *
83
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
90
+ * This program is distributed in the hope that it will be useful, but WITHOUT
84
+ * See the COPYING file in the top-level directory.
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_PWM_H
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
186
index XXXXXXX..XXXXXXX 100644
187
--- a/hw/arm/npcm7xx.c
188
+++ b/hw/arm/npcm7xx.c
189
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
190
NPCM7XX_WDG2_IRQ, /* Timer Module 2 Watchdog */
191
NPCM7XX_EHCI_IRQ = 61,
192
NPCM7XX_OHCI_IRQ = 62,
193
+ NPCM7XX_PWM0_IRQ = 93, /* PWM module 0 */
194
+ NPCM7XX_PWM1_IRQ, /* PWM module 1 */
195
NPCM7XX_GPIO0_IRQ = 116,
196
NPCM7XX_GPIO1_IRQ,
197
NPCM7XX_GPIO2_IRQ,
198
@@ -XXX,XX +XXX,XX @@ static const hwaddr npcm7xx_fiu3_flash_addr[] = {
199
0xb8000000, /* CS3 */
200
};
201
202
+/* Register base address for each PWM Module */
203
+static const hwaddr npcm7xx_pwm_addr[] = {
204
+ 0xf0103000,
205
+ 0xf0104000,
206
+};
207
+
208
static const struct {
209
hwaddr regs_addr;
210
uint32_t unconnected_pins;
211
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
212
object_initialize_child(obj, npcm7xx_fiu[i].name, &s->fiu[i],
213
TYPE_NPCM7XX_FIU);
214
}
215
+
216
+ for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
217
+ object_initialize_child(obj, "pwm[*]", &s->pwm[i], TYPE_NPCM7XX_PWM);
218
+ }
219
}
220
221
static void npcm7xx_realize(DeviceState *dev, Error **errp)
222
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
223
sysbus_connect_irq(SYS_BUS_DEVICE(&s->ohci), 0,
224
npcm7xx_irq(s, NPCM7XX_OHCI_IRQ));
225
226
+ /* PWM Modules. Cannot fail. */
227
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_pwm_addr) != ARRAY_SIZE(s->pwm));
228
+ for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
229
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->pwm[i]);
230
+
231
+ qdev_connect_clock_in(DEVICE(&s->pwm[i]), "clock", qdev_get_clock_out(
232
+ DEVICE(&s->clk), "apb3-clock"));
233
+ sysbus_realize(sbd, &error_abort);
234
+ sysbus_mmio_map(sbd, 0, npcm7xx_pwm_addr[i]);
235
+ sysbus_connect_irq(sbd, i, npcm7xx_irq(s, NPCM7XX_PWM0_IRQ + i));
236
+ }
237
+
238
/*
239
* Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
240
* specified, but this is a programming error.
241
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
242
create_unimplemented_device("npcm7xx.peci", 0xf0100000, 4 * KiB);
243
create_unimplemented_device("npcm7xx.siox[1]", 0xf0101000, 4 * KiB);
244
create_unimplemented_device("npcm7xx.siox[2]", 0xf0102000, 4 * KiB);
245
- create_unimplemented_device("npcm7xx.pwm[0]", 0xf0103000, 4 * KiB);
246
- create_unimplemented_device("npcm7xx.pwm[1]", 0xf0104000, 4 * KiB);
247
create_unimplemented_device("npcm7xx.mft[0]", 0xf0180000, 4 * KiB);
248
create_unimplemented_device("npcm7xx.mft[1]", 0xf0181000, 4 * KiB);
249
create_unimplemented_device("npcm7xx.mft[2]", 0xf0182000, 4 * KiB);
250
diff --git a/hw/misc/npcm7xx_pwm.c b/hw/misc/npcm7xx_pwm.c
251
new file mode 100644
252
index XXXXXXX..XXXXXXX
253
--- /dev/null
254
+++ b/hw/misc/npcm7xx_pwm.c
255
@@ -XXX,XX +XXX,XX @@
256
+/*
257
+ * Nuvoton NPCM7xx PWM Module
85
+ *
258
+ *
259
+ * Copyright 2020 Google LLC
260
+ *
261
+ * This program is free software; you can redistribute it and/or modify it
262
+ * under the terms of the GNU General Public License as published by the
263
+ * Free Software Foundation; either version 2 of the License, or
264
+ * (at your option) any later version.
265
+ *
266
+ * This program is distributed in the hope that it will be useful, but WITHOUT
267
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
268
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
269
+ * for more details.
86
+ */
270
+ */
87
+
271
+
88
+#include "qemu/osdep.h"
272
+#include "qemu/osdep.h"
273
+#include "hw/irq.h"
274
+#include "hw/qdev-clock.h"
275
+#include "hw/qdev-properties.h"
276
+#include "hw/misc/npcm7xx_pwm.h"
277
+#include "hw/registerfields.h"
278
+#include "migration/vmstate.h"
279
+#include "qemu/bitops.h"
280
+#include "qemu/error-report.h"
89
+#include "qemu/log.h"
281
+#include "qemu/log.h"
90
+#include "qemu/module.h"
282
+#include "qemu/module.h"
91
+#include "sysemu/runstate.h"
283
+#include "qemu/units.h"
92
+
284
+#include "trace.h"
93
+#include "hw/nvram/fw_cfg.h"
285
+
94
+#include "hw/qdev-properties.h"
286
+REG32(NPCM7XX_PWM_PPR, 0x00);
95
+#include "hw/misc/pvpanic.h"
287
+REG32(NPCM7XX_PWM_CSR, 0x04);
96
+#include "qom/object.h"
288
+REG32(NPCM7XX_PWM_PCR, 0x08);
97
+#include "hw/isa/isa.h"
289
+REG32(NPCM7XX_PWM_CNR0, 0x0c);
98
+
290
+REG32(NPCM7XX_PWM_CMR0, 0x10);
99
+OBJECT_DECLARE_SIMPLE_TYPE(PVPanicISAState, PVPANIC_ISA_DEVICE)
291
+REG32(NPCM7XX_PWM_PDR0, 0x14);
100
+
292
+REG32(NPCM7XX_PWM_CNR1, 0x18);
101
+/*
293
+REG32(NPCM7XX_PWM_CMR1, 0x1c);
102
+ * PVPanicISAState for ISA device and
294
+REG32(NPCM7XX_PWM_PDR1, 0x20);
103
+ * use ioport.
295
+REG32(NPCM7XX_PWM_CNR2, 0x24);
104
+ */
296
+REG32(NPCM7XX_PWM_CMR2, 0x28);
105
+struct PVPanicISAState {
297
+REG32(NPCM7XX_PWM_PDR2, 0x2c);
106
+ ISADevice parent_obj;
298
+REG32(NPCM7XX_PWM_CNR3, 0x30);
107
+
299
+REG32(NPCM7XX_PWM_CMR3, 0x34);
108
+ uint16_t ioport;
300
+REG32(NPCM7XX_PWM_PDR3, 0x38);
109
+ PVPanicState pvpanic;
301
+REG32(NPCM7XX_PWM_PIER, 0x3c);
302
+REG32(NPCM7XX_PWM_PIIR, 0x40);
303
+REG32(NPCM7XX_PWM_PWDR0, 0x44);
304
+REG32(NPCM7XX_PWM_PWDR1, 0x48);
305
+REG32(NPCM7XX_PWM_PWDR2, 0x4c);
306
+REG32(NPCM7XX_PWM_PWDR3, 0x50);
307
+
308
+/* Register field definitions. */
309
+#define NPCM7XX_PPR(rv, index) extract32((rv), npcm7xx_ppr_base[index], 8)
310
+#define NPCM7XX_CSR(rv, index) extract32((rv), npcm7xx_csr_base[index], 3)
311
+#define NPCM7XX_CH(rv, index) extract32((rv), npcm7xx_ch_base[index], 4)
312
+#define NPCM7XX_CH_EN BIT(0)
313
+#define NPCM7XX_CH_INV BIT(2)
314
+#define NPCM7XX_CH_MOD BIT(3)
315
+
316
+/* Offset of each PWM channel's prescaler in the PPR register. */
317
+static const int npcm7xx_ppr_base[] = { 0, 0, 8, 8 };
318
+/* Offset of each PWM channel's clock selector in the CSR register. */
319
+static const int npcm7xx_csr_base[] = { 0, 4, 8, 12 };
320
+/* Offset of each PWM channel's control variable in the PCR register. */
321
+static const int npcm7xx_ch_base[] = { 0, 8, 12, 16 };
322
+
323
+static uint32_t npcm7xx_pwm_calculate_freq(NPCM7xxPWM *p)
324
+{
325
+ uint32_t ppr;
326
+ uint32_t csr;
327
+ uint32_t freq;
328
+
329
+ if (!p->running) {
330
+ return 0;
331
+ }
332
+
333
+ csr = NPCM7XX_CSR(p->module->csr, p->index);
334
+ ppr = NPCM7XX_PPR(p->module->ppr, p->index);
335
+ freq = clock_get_hz(p->module->clock);
336
+ freq /= ppr + 1;
337
+ /* csr can only be 0~4 */
338
+ if (csr > 4) {
339
+ qemu_log_mask(LOG_GUEST_ERROR,
340
+ "%s: invalid csr value %u\n",
341
+ __func__, csr);
342
+ csr = 4;
343
+ }
344
+ /* freq won't be changed if csr == 4. */
345
+ if (csr < 4) {
346
+ freq >>= csr + 1;
347
+ }
348
+
349
+ return freq / (p->cnr + 1);
350
+}
351
+
352
+static uint32_t npcm7xx_pwm_calculate_duty(NPCM7xxPWM *p)
353
+{
354
+ uint64_t duty;
355
+
356
+ if (p->running) {
357
+ if (p->cnr == 0) {
358
+ duty = 0;
359
+ } else if (p->cmr >= p->cnr) {
360
+ duty = NPCM7XX_PWM_MAX_DUTY;
361
+ } else {
362
+ duty = NPCM7XX_PWM_MAX_DUTY * (p->cmr + 1) / (p->cnr + 1);
363
+ }
364
+ } else {
365
+ duty = 0;
366
+ }
367
+
368
+ if (p->inverted) {
369
+ duty = NPCM7XX_PWM_MAX_DUTY - duty;
370
+ }
371
+
372
+ return duty;
373
+}
374
+
375
+static void npcm7xx_pwm_update_freq(NPCM7xxPWM *p)
376
+{
377
+ uint32_t freq = npcm7xx_pwm_calculate_freq(p);
378
+
379
+ if (freq != p->freq) {
380
+ trace_npcm7xx_pwm_update_freq(DEVICE(p->module)->canonical_path,
381
+ p->index, p->freq, freq);
382
+ p->freq = freq;
383
+ }
384
+}
385
+
386
+static void npcm7xx_pwm_update_duty(NPCM7xxPWM *p)
387
+{
388
+ uint32_t duty = npcm7xx_pwm_calculate_duty(p);
389
+
390
+ if (duty != p->duty) {
391
+ trace_npcm7xx_pwm_update_duty(DEVICE(p->module)->canonical_path,
392
+ p->index, p->duty, duty);
393
+ p->duty = duty;
394
+ }
395
+}
396
+
397
+static void npcm7xx_pwm_update_output(NPCM7xxPWM *p)
398
+{
399
+ npcm7xx_pwm_update_freq(p);
400
+ npcm7xx_pwm_update_duty(p);
401
+}
402
+
403
+static void npcm7xx_pwm_write_ppr(NPCM7xxPWMState *s, uint32_t new_ppr)
404
+{
405
+ int i;
406
+ uint32_t old_ppr = s->ppr;
407
+
408
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_ppr_base) != NPCM7XX_PWM_PER_MODULE);
409
+ s->ppr = new_ppr;
410
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
411
+ if (NPCM7XX_PPR(old_ppr, i) != NPCM7XX_PPR(new_ppr, i)) {
412
+ npcm7xx_pwm_update_freq(&s->pwm[i]);
413
+ }
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
+ },
110
+};
687
+};
111
+
688
+
112
+static void pvpanic_isa_initfn(Object *obj)
689
+static void npcm7xx_pwm_enter_reset(Object *obj, ResetType type)
113
+{
690
+{
114
+ PVPanicISAState *s = PVPANIC_ISA_DEVICE(obj);
691
+ NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
115
+
692
+ int i;
116
+ pvpanic_setup_io(&s->pvpanic, DEVICE(s), 1);
693
+
117
+}
694
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
118
+
695
+ NPCM7xxPWM *p = &s->pwm[i];
119
+static void pvpanic_isa_realizefn(DeviceState *dev, Error **errp)
696
+
120
+{
697
+ p->cnr = 0x00000000;
121
+ ISADevice *d = ISA_DEVICE(dev);
698
+ p->cmr = 0x00000000;
122
+ PVPanicISAState *s = PVPANIC_ISA_DEVICE(dev);
699
+ p->pdr = 0x00000000;
123
+ PVPanicState *ps = &s->pvpanic;
700
+ p->pwdr = 0x00000000;
124
+ FWCfgState *fw_cfg = fw_cfg_find();
701
+ }
125
+ uint16_t *pvpanic_port;
702
+
126
+
703
+ s->ppr = 0x00000000;
127
+ if (!fw_cfg) {
704
+ s->csr = 0x00000000;
128
+ return;
705
+ s->pcr = 0x00000000;
129
+ }
706
+ s->pier = 0x00000000;
130
+
707
+ s->piir = 0x00000000;
131
+ pvpanic_port = g_malloc(sizeof(*pvpanic_port));
708
+}
132
+ *pvpanic_port = cpu_to_le16(s->ioport);
709
+
133
+ fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", pvpanic_port,
710
+static void npcm7xx_pwm_hold_reset(Object *obj)
134
+ sizeof(*pvpanic_port));
711
+{
135
+
712
+ NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
136
+ isa_register_ioport(d, &ps->mr, s->ioport);
713
+ int i;
137
+}
714
+
138
+
715
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
139
+static Property pvpanic_isa_properties[] = {
716
+ qemu_irq_lower(s->pwm[i].irq);
140
+ DEFINE_PROP_UINT16(PVPANIC_IOPORT_PROP, PVPanicISAState, ioport, 0x505),
717
+ }
141
+ DEFINE_PROP_UINT8("events", PVPanicISAState, pvpanic.events, PVPANIC_PANICKED | PVPANIC_CRASHLOADED),
718
+}
142
+ DEFINE_PROP_END_OF_LIST(),
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
+ },
143
+};
762
+};
144
+
763
+
145
+static void pvpanic_isa_class_init(ObjectClass *klass, void *data)
764
+static const VMStateDescription vmstate_npcm7xx_pwm_module = {
146
+{
765
+ .name = "npcm7xx-pwm-module",
766
+ .version_id = 0,
767
+ .minimum_version_id = 0,
768
+ .fields = (VMStateField[]) {
769
+ VMSTATE_CLOCK(clock, NPCM7xxPWMState),
770
+ VMSTATE_STRUCT_ARRAY(pwm, NPCM7xxPWMState,
771
+ NPCM7XX_PWM_PER_MODULE, 0, vmstate_npcm7xx_pwm,
772
+ NPCM7xxPWM),
773
+ VMSTATE_UINT32(ppr, NPCM7xxPWMState),
774
+ VMSTATE_UINT32(csr, NPCM7xxPWMState),
775
+ VMSTATE_UINT32(pcr, NPCM7xxPWMState),
776
+ VMSTATE_UINT32(pier, NPCM7xxPWMState),
777
+ VMSTATE_UINT32(piir, NPCM7xxPWMState),
778
+ VMSTATE_END_OF_LIST(),
779
+ },
780
+};
781
+
782
+static void npcm7xx_pwm_class_init(ObjectClass *klass, void *data)
783
+{
784
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
147
+ DeviceClass *dc = DEVICE_CLASS(klass);
785
+ DeviceClass *dc = DEVICE_CLASS(klass);
148
+
786
+
149
+ dc->realize = pvpanic_isa_realizefn;
787
+ dc->desc = "NPCM7xx PWM Controller";
150
+ device_class_set_props(dc, pvpanic_isa_properties);
788
+ dc->vmsd = &vmstate_npcm7xx_pwm_module;
151
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
789
+ rc->phases.enter = npcm7xx_pwm_enter_reset;
152
+}
790
+ rc->phases.hold = npcm7xx_pwm_hold_reset;
153
+
791
+}
154
+static TypeInfo pvpanic_isa_info = {
792
+
155
+ .name = TYPE_PVPANIC_ISA_DEVICE,
793
+static const TypeInfo npcm7xx_pwm_info = {
156
+ .parent = TYPE_ISA_DEVICE,
794
+ .name = TYPE_NPCM7XX_PWM,
157
+ .instance_size = sizeof(PVPanicISAState),
795
+ .parent = TYPE_SYS_BUS_DEVICE,
158
+ .instance_init = pvpanic_isa_initfn,
796
+ .instance_size = sizeof(NPCM7xxPWMState),
159
+ .class_init = pvpanic_isa_class_init,
797
+ .class_init = npcm7xx_pwm_class_init,
798
+ .instance_init = npcm7xx_pwm_init,
160
+};
799
+};
161
+
800
+
162
+static void pvpanic_register_types(void)
801
+static void npcm7xx_pwm_register_type(void)
163
+{
802
+{
164
+ type_register_static(&pvpanic_isa_info);
803
+ type_register_static(&npcm7xx_pwm_info);
165
+}
804
+}
166
+
805
+type_init(npcm7xx_pwm_register_type);
167
+type_init(pvpanic_register_types)
168
diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c
169
index XXXXXXX..XXXXXXX 100644
170
--- a/hw/misc/pvpanic.c
171
+++ b/hw/misc/pvpanic.c
172
@@ -XXX,XX +XXX,XX @@
173
#include "hw/misc/pvpanic.h"
174
#include "qom/object.h"
175
176
-/* The bit of supported pv event, TODO: include uapi header and remove this */
177
-#define PVPANIC_F_PANICKED 0
178
-#define PVPANIC_F_CRASHLOADED 1
179
-
180
-/* The pv event value */
181
-#define PVPANIC_PANICKED (1 << PVPANIC_F_PANICKED)
182
-#define PVPANIC_CRASHLOADED (1 << PVPANIC_F_CRASHLOADED)
183
-
184
-typedef struct PVPanicState PVPanicState;
185
-DECLARE_INSTANCE_CHECKER(PVPanicState, ISA_PVPANIC_DEVICE,
186
- TYPE_PVPANIC)
187
-
188
static void handle_event(int event)
189
{
190
static bool logged;
191
@@ -XXX,XX +XXX,XX @@ static void handle_event(int event)
192
}
193
}
194
195
-#include "hw/isa/isa.h"
196
-
197
-struct PVPanicState {
198
- ISADevice parent_obj;
199
-
200
- MemoryRegion io;
201
- uint16_t ioport;
202
- uint8_t events;
203
-};
204
-
205
/* return supported events on read */
206
-static uint64_t pvpanic_ioport_read(void *opaque, hwaddr addr, unsigned size)
207
+static uint64_t pvpanic_read(void *opaque, hwaddr addr, unsigned size)
208
{
209
PVPanicState *pvp = opaque;
210
return pvp->events;
211
}
212
213
-static void pvpanic_ioport_write(void *opaque, hwaddr addr, uint64_t val,
214
+static void pvpanic_write(void *opaque, hwaddr addr, uint64_t val,
215
unsigned size)
216
{
217
handle_event(val);
218
}
219
220
static const MemoryRegionOps pvpanic_ops = {
221
- .read = pvpanic_ioport_read,
222
- .write = pvpanic_ioport_write,
223
+ .read = pvpanic_read,
224
+ .write = pvpanic_write,
225
.impl = {
226
.min_access_size = 1,
227
.max_access_size = 1,
228
},
229
};
230
231
-static void pvpanic_isa_initfn(Object *obj)
232
+void pvpanic_setup_io(PVPanicState *s, DeviceState *dev, unsigned size)
233
{
234
- PVPanicState *s = ISA_PVPANIC_DEVICE(obj);
235
-
236
- memory_region_init_io(&s->io, OBJECT(s), &pvpanic_ops, s, "pvpanic", 1);
237
+ memory_region_init_io(&s->mr, OBJECT(dev), &pvpanic_ops, s, "pvpanic", size);
238
}
239
-
240
-static void pvpanic_isa_realizefn(DeviceState *dev, Error **errp)
241
-{
242
- ISADevice *d = ISA_DEVICE(dev);
243
- PVPanicState *s = ISA_PVPANIC_DEVICE(dev);
244
- FWCfgState *fw_cfg = fw_cfg_find();
245
- uint16_t *pvpanic_port;
246
-
247
- if (!fw_cfg) {
248
- return;
249
- }
250
-
251
- pvpanic_port = g_malloc(sizeof(*pvpanic_port));
252
- *pvpanic_port = cpu_to_le16(s->ioport);
253
- fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", pvpanic_port,
254
- sizeof(*pvpanic_port));
255
-
256
- isa_register_ioport(d, &s->io, s->ioport);
257
-}
258
-
259
-static Property pvpanic_isa_properties[] = {
260
- DEFINE_PROP_UINT16(PVPANIC_IOPORT_PROP, PVPanicState, ioport, 0x505),
261
- DEFINE_PROP_UINT8("events", PVPanicState, events, PVPANIC_PANICKED | PVPANIC_CRASHLOADED),
262
- DEFINE_PROP_END_OF_LIST(),
263
-};
264
-
265
-static void pvpanic_isa_class_init(ObjectClass *klass, void *data)
266
-{
267
- DeviceClass *dc = DEVICE_CLASS(klass);
268
-
269
- dc->realize = pvpanic_isa_realizefn;
270
- device_class_set_props(dc, pvpanic_isa_properties);
271
- set_bit(DEVICE_CATEGORY_MISC, dc->categories);
272
-}
273
-
274
-static TypeInfo pvpanic_isa_info = {
275
- .name = TYPE_PVPANIC,
276
- .parent = TYPE_ISA_DEVICE,
277
- .instance_size = sizeof(PVPanicState),
278
- .instance_init = pvpanic_isa_initfn,
279
- .class_init = pvpanic_isa_class_init,
280
-};
281
-
282
-static void pvpanic_register_types(void)
283
-{
284
- type_register_static(&pvpanic_isa_info);
285
-}
286
-
287
-type_init(pvpanic_register_types)
288
diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
289
index XXXXXXX..XXXXXXX 100644
290
--- a/hw/i386/Kconfig
291
+++ b/hw/i386/Kconfig
292
@@ -XXX,XX +XXX,XX @@ config PC
293
imply ISA_DEBUG
294
imply PARALLEL
295
imply PCI_DEVICES
296
- imply PVPANIC
297
+ imply PVPANIC_ISA
298
imply QXL
299
imply SEV
300
imply SGA
301
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
302
index XXXXXXX..XXXXXXX 100644
303
--- a/hw/misc/Kconfig
304
+++ b/hw/misc/Kconfig
305
@@ -XXX,XX +XXX,XX @@ config IOTKIT_SYSCTL
306
config IOTKIT_SYSINFO
307
bool
308
309
-config PVPANIC
310
+config PVPANIC_COMMON
311
+ bool
312
+
313
+config PVPANIC_ISA
314
bool
315
depends on ISA_BUS
316
+ select PVPANIC_COMMON
317
318
config AUX
319
bool
320
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
806
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
321
index XXXXXXX..XXXXXXX 100644
807
index XXXXXXX..XXXXXXX 100644
322
--- a/hw/misc/meson.build
808
--- a/hw/misc/meson.build
323
+++ b/hw/misc/meson.build
809
+++ b/hw/misc/meson.build
324
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_EMC141X', if_true: files('emc141x.c'))
810
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c'))
325
softmmu_ss.add(when: 'CONFIG_UNIMP', if_true: files('unimp.c'))
811
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
326
softmmu_ss.add(when: 'CONFIG_EMPTY_SLOT', if_true: files('empty_slot.c'))
812
'npcm7xx_clk.c',
327
softmmu_ss.add(when: 'CONFIG_LED', if_true: files('led.c'))
813
'npcm7xx_gcr.c',
328
+softmmu_ss.add(when: 'CONFIG_PVPANIC_COMMON', if_true: files('pvpanic.c'))
814
+ 'npcm7xx_pwm.c',
329
815
'npcm7xx_rng.c',
330
# ARM devices
816
))
331
softmmu_ss.add(when: 'CONFIG_PL310', if_true: files('arm_l2x0.c'))
817
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files(
332
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_IOTKIT_SYSINFO', if_true: files('iotkit-sysinfo.c')
818
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
333
softmmu_ss.add(when: 'CONFIG_ARMSSE_CPUID', if_true: files('armsse-cpuid.c'))
334
softmmu_ss.add(when: 'CONFIG_ARMSSE_MHU', if_true: files('armsse-mhu.c'))
335
336
-softmmu_ss.add(when: 'CONFIG_PVPANIC', if_true: files('pvpanic.c'))
337
+softmmu_ss.add(when: 'CONFIG_PVPANIC_ISA', if_true: files('pvpanic-isa.c'))
338
softmmu_ss.add(when: 'CONFIG_AUX', if_true: files('auxbus.c'))
339
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_scu.c', 'aspeed_sdmc.c', 'aspeed_xdma.c'))
340
softmmu_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-sysreg.c'))
341
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
342
index XXXXXXX..XXXXXXX 100644
819
index XXXXXXX..XXXXXXX 100644
343
--- a/tests/qtest/meson.build
820
--- a/hw/misc/trace-events
344
+++ b/tests/qtest/meson.build
821
+++ b/hw/misc/trace-events
345
@@ -XXX,XX +XXX,XX @@ qtests_i386 = \
822
@@ -XXX,XX +XXX,XX @@ npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " valu
346
(config_host.has_key('CONFIG_LINUX') and \
823
npcm7xx_rng_read(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
347
config_all_devices.has_key('CONFIG_ISA_IPMI_BT') ? ['ipmi-bt-test'] : []) + \
824
npcm7xx_rng_write(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
348
(config_all_devices.has_key('CONFIG_WDT_IB700') ? ['wdt_ib700-test'] : []) + \
825
349
- (config_all_devices.has_key('CONFIG_PVPANIC') ? ['pvpanic-test'] : []) + \
826
+# npcm7xx_pwm.c
350
+ (config_all_devices.has_key('CONFIG_PVPANIC_ISA') ? ['pvpanic-test'] : []) + \
827
+npcm7xx_pwm_read(const char *id, uint64_t offset, uint32_t value) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
351
(config_all_devices.has_key('CONFIG_HDA') ? ['intel-hda-test'] : []) + \
828
+npcm7xx_pwm_write(const char *id, uint64_t offset, uint32_t value) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
352
(config_all_devices.has_key('CONFIG_I82801B11') ? ['i82801b11-test'] : []) + \
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"
353
(config_all_devices.has_key('CONFIG_IOH3420') ? ['ioh3420-test'] : []) + \
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"
831
+
832
# stm32f4xx_syscfg.c
833
stm32f4xx_syscfg_set_irq(int gpio, int line, int level) "Interupt: GPIO: %d, Line: %d; Level: %d"
834
stm32f4xx_pulse_exti(int irq) "Pulse EXTI: %d"
354
--
835
--
355
2.20.1
836
2.20.1
356
837
357
838
diff view generated by jsdifflib
1
Add a simple test of the CMSDK APB timer, since we're about to do
1
From: Hao Wu <wuhaotsh@google.com>
2
some refactoring of how it is clocked.
3
2
3
We add a qtest for the PWM in the previous patch. It proves it works as
4
expected.
5
6
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
7
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
8
Signed-off-by: Hao Wu <wuhaotsh@google.com>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20210108190945.949196-6-wuhaotsh@google.com
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Luc Michel <luc@lmichel.fr>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20210128114145.20536-4-peter.maydell@linaro.org
9
Message-id: 20210121190622.22000-4-peter.maydell@linaro.org
10
---
12
---
11
tests/qtest/cmsdk-apb-timer-test.c | 75 ++++++++++++++++++++++++++++++
13
tests/qtest/npcm7xx_pwm-test.c | 490 +++++++++++++++++++++++++++++++++
12
MAINTAINERS | 1 +
14
tests/qtest/meson.build | 1 +
13
tests/qtest/meson.build | 1 +
15
2 files changed, 491 insertions(+)
14
3 files changed, 77 insertions(+)
16
create mode 100644 tests/qtest/npcm7xx_pwm-test.c
15
create mode 100644 tests/qtest/cmsdk-apb-timer-test.c
16
17
17
diff --git a/tests/qtest/cmsdk-apb-timer-test.c b/tests/qtest/cmsdk-apb-timer-test.c
18
diff --git a/tests/qtest/npcm7xx_pwm-test.c b/tests/qtest/npcm7xx_pwm-test.c
18
new file mode 100644
19
new file mode 100644
19
index XXXXXXX..XXXXXXX
20
index XXXXXXX..XXXXXXX
20
--- /dev/null
21
--- /dev/null
21
+++ b/tests/qtest/cmsdk-apb-timer-test.c
22
+++ b/tests/qtest/npcm7xx_pwm-test.c
22
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@
23
+/*
24
+/*
24
+ * QTest testcase for the CMSDK APB timer device
25
+ * QTests for Nuvoton NPCM7xx PWM Modules.
25
+ *
26
+ *
26
+ * Copyright (c) 2021 Linaro Limited
27
+ * Copyright 2020 Google LLC
27
+ *
28
+ *
28
+ * This program is free software; you can redistribute it and/or modify it
29
+ * This program is free software; you can redistribute it and/or modify it
29
+ * under the terms of the GNU General Public License as published by the
30
+ * under the terms of the GNU General Public License as published by the
30
+ * Free Software Foundation; either version 2 of the License, or
31
+ * Free Software Foundation; either version 2 of the License, or
31
+ * (at your option) any later version.
32
+ * (at your option) any later version.
...
...
35
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
36
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
36
+ * for more details.
37
+ * for more details.
37
+ */
38
+ */
38
+
39
+
39
+#include "qemu/osdep.h"
40
+#include "qemu/osdep.h"
40
+#include "libqtest-single.h"
41
+#include "qemu/bitops.h"
41
+
42
+#include "libqos/libqtest.h"
42
+/* IoTKit/ARMSSE-200 timer0; driven at 25MHz in mps2-an385, so 40ns per tick */
43
+#include "qapi/qmp/qdict.h"
43
+#define TIMER_BASE 0x40000000
44
+#include "qapi/qmp/qnum.h"
44
+
45
+
45
+#define CTRL 0
46
+#define REF_HZ 25000000
46
+#define VALUE 4
47
+
47
+#define RELOAD 8
48
+/* Register field definitions. */
48
+#define INTSTATUS 0xc
49
+#define CH_EN BIT(0)
49
+
50
+#define CH_INV BIT(2)
50
+static void test_timer(void)
51
+#define CH_MOD BIT(3)
51
+{
52
+
52
+ g_assert_true(readl(TIMER_BASE + INTSTATUS) == 0);
53
+/* Registers shared between all PWMs in a module */
53
+
54
+#define PPR 0x00
54
+ /* Start timer: will fire after 40 * 1000 == 40000 ns */
55
+#define CSR 0x04
55
+ writel(TIMER_BASE + RELOAD, 1000);
56
+#define PCR 0x08
56
+ writel(TIMER_BASE + CTRL, 9);
57
+#define PIER 0x3c
57
+
58
+#define PIIR 0x40
58
+ /* Step to just past the 500th tick and check VALUE */
59
+
59
+ clock_step(40 * 500 + 1);
60
+/* CLK module related */
60
+ g_assert_cmpuint(readl(TIMER_BASE + INTSTATUS), ==, 0);
61
+#define CLK_BA 0xf0801000
61
+ g_assert_cmpuint(readl(TIMER_BASE + VALUE), ==, 500);
62
+#define CLKSEL 0x04
62
+
63
+#define CLKDIV1 0x08
63
+ /* Just past the 1000th tick: timer should have fired */
64
+#define CLKDIV2 0x2c
64
+ clock_step(40 * 500);
65
+#define PLLCON0 0x0c
65
+ g_assert_cmpuint(readl(TIMER_BASE + INTSTATUS), ==, 1);
66
+#define PLLCON1 0x10
66
+ g_assert_cmpuint(readl(TIMER_BASE + VALUE), ==, 0);
67
+#define PLL_INDV(rv) extract32((rv), 0, 6)
67
+
68
+#define PLL_FBDV(rv) extract32((rv), 16, 12)
68
+ /* VALUE reloads at the following tick */
69
+#define PLL_OTDV1(rv) extract32((rv), 8, 3)
69
+ clock_step(40);
70
+#define PLL_OTDV2(rv) extract32((rv), 13, 3)
70
+ g_assert_cmpuint(readl(TIMER_BASE + VALUE), ==, 1000);
71
+#define APB3CKDIV(rv) extract32((rv), 28, 2)
71
+
72
+#define CLK2CKDIV(rv) extract32((rv), 0, 1)
72
+ /* Check write-1-to-clear behaviour of INTSTATUS */
73
+#define CLK4CKDIV(rv) extract32((rv), 26, 2)
73
+ writel(TIMER_BASE + INTSTATUS, 0);
74
+#define CPUCKSEL(rv) extract32((rv), 0, 2)
74
+ g_assert_cmpuint(readl(TIMER_BASE + INTSTATUS), ==, 1);
75
+
75
+ writel(TIMER_BASE + INTSTATUS, 1);
76
+#define MAX_DUTY 1000000
76
+ g_assert_cmpuint(readl(TIMER_BASE + INTSTATUS), ==, 0);
77
+
77
+
78
+typedef struct PWMModule {
78
+ /* Turn off the timer */
79
+ int irq;
79
+ writel(TIMER_BASE + CTRL, 0);
80
+ uint64_t base_addr;
80
+}
81
+} PWMModule;
82
+
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);
251
+ break;
252
+ case 1:
253
+ pllcon = qtest_readl(qts, CLK_BA + PLLCON1);
254
+ freq = get_pll(pllcon);
255
+ break;
256
+ case 2:
257
+ break;
258
+ case 3:
259
+ break;
260
+ default:
261
+ g_assert_not_reached();
262
+ }
263
+
264
+ freq >>= (CLK2CKDIV(clkdiv1) + CLK4CKDIV(clkdiv1) + APB3CKDIV(clkdiv2));
265
+
266
+ return freq;
267
+}
268
+
269
+static uint32_t pwm_selector(uint32_t csr)
270
+{
271
+ switch (csr) {
272
+ case 0:
273
+ return 2;
274
+ case 1:
275
+ return 4;
276
+ case 2:
277
+ return 8;
278
+ case 3:
279
+ return 16;
280
+ case 4:
281
+ return 1;
282
+ default:
283
+ g_assert_not_reached();
284
+ }
285
+}
286
+
287
+static uint64_t pwm_compute_freq(QTestState *qts, uint32_t ppr, uint32_t csr,
288
+ uint32_t cnr)
289
+{
290
+ return read_pclk(qts) / ((ppr + 1) * pwm_selector(csr) * (cnr + 1));
291
+}
292
+
293
+static uint64_t pwm_compute_duty(uint32_t cnr, uint32_t cmr, bool inverted)
294
+{
295
+ uint64_t duty;
296
+
297
+ if (cnr == 0) {
298
+ /* PWM is stopped. */
299
+ duty = 0;
300
+ } else if (cmr >= cnr) {
301
+ duty = MAX_DUTY;
302
+ } else {
303
+ duty = MAX_DUTY * (cmr + 1) / (cnr + 1);
304
+ }
305
+
306
+ if (inverted) {
307
+ duty = MAX_DUTY - duty;
308
+ }
309
+
310
+ return duty;
311
+}
312
+
313
+static uint32_t pwm_read(QTestState *qts, const TestData *td, unsigned offset)
314
+{
315
+ return qtest_readl(qts, td->module->base_addr + offset);
316
+}
317
+
318
+static void pwm_write(QTestState *qts, const TestData *td, unsigned offset,
319
+ uint32_t value)
320
+{
321
+ qtest_writel(qts, td->module->base_addr + offset, value);
322
+}
323
+
324
+static uint32_t pwm_read_ppr(QTestState *qts, const TestData *td)
325
+{
326
+ return extract32(pwm_read(qts, td, PPR), ppr_base[pwm_index(td->pwm)], 8);
327
+}
328
+
329
+static void pwm_write_ppr(QTestState *qts, const TestData *td, uint32_t value)
330
+{
331
+ pwm_write(qts, td, PPR, value << ppr_base[pwm_index(td->pwm)]);
332
+}
333
+
334
+static uint32_t pwm_read_csr(QTestState *qts, const TestData *td)
335
+{
336
+ return extract32(pwm_read(qts, td, CSR), csr_base[pwm_index(td->pwm)], 3);
337
+}
338
+
339
+static void pwm_write_csr(QTestState *qts, const TestData *td, uint32_t value)
340
+{
341
+ pwm_write(qts, td, CSR, value << csr_base[pwm_index(td->pwm)]);
342
+}
343
+
344
+static uint32_t pwm_read_pcr(QTestState *qts, const TestData *td)
345
+{
346
+ return extract32(pwm_read(qts, td, PCR), pcr_base[pwm_index(td->pwm)], 4);
347
+}
348
+
349
+static void pwm_write_pcr(QTestState *qts, const TestData *td, uint32_t value)
350
+{
351
+ pwm_write(qts, td, PCR, value << pcr_base[pwm_index(td->pwm)]);
352
+}
353
+
354
+static uint32_t pwm_read_cnr(QTestState *qts, const TestData *td)
355
+{
356
+ return pwm_read(qts, td, td->pwm->cnr_offset);
357
+}
358
+
359
+static void pwm_write_cnr(QTestState *qts, const TestData *td, uint32_t value)
360
+{
361
+ pwm_write(qts, td, td->pwm->cnr_offset, value);
362
+}
363
+
364
+static uint32_t pwm_read_cmr(QTestState *qts, const TestData *td)
365
+{
366
+ return pwm_read(qts, td, td->pwm->cmr_offset);
367
+}
368
+
369
+static void pwm_write_cmr(QTestState *qts, const TestData *td, uint32_t value)
370
+{
371
+ pwm_write(qts, td, td->pwm->cmr_offset, value);
372
+}
373
+
374
+/* Check pwm registers can be reset to default value */
375
+static void test_init(gconstpointer test_data)
376
+{
377
+ const TestData *td = test_data;
378
+ QTestState *qts = qtest_init("-machine quanta-gsj");
379
+ int module = pwm_module_index(td->module);
380
+ int pwm = pwm_index(td->pwm);
381
+
382
+ g_assert_cmpuint(pwm_get_freq(qts, module, pwm), ==, 0);
383
+ g_assert_cmpuint(pwm_get_duty(qts, module, pwm), ==, 0);
384
+
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)
81
+
492
+
82
+int main(int argc, char **argv)
493
+int main(int argc, char **argv)
83
+{
494
+{
84
+ int r;
495
+ TestData test_data_list[ARRAY_SIZE(pwm_module_list) * ARRAY_SIZE(pwm_list)];
85
+
496
+
86
+ g_test_init(&argc, &argv, NULL);
497
+ g_test_init(&argc, &argv, NULL);
87
+
498
+
88
+ qtest_start("-machine mps2-an385");
499
+ for (int i = 0; i < ARRAY_SIZE(pwm_module_list); ++i) {
89
+
500
+ for (int j = 0; j < ARRAY_SIZE(pwm_list); ++j) {
90
+ qtest_add_func("/cmsdk-apb-timer/timer", test_timer);
501
+ TestData *td = &test_data_list[i * ARRAY_SIZE(pwm_list) + j];
91
+
502
+
92
+ r = g_test_run();
503
+ td->module = &pwm_module_list[i];
93
+
504
+ td->pwm = &pwm_list[j];
94
+ qtest_end();
505
+
95
+
506
+ add_test(init, td);
96
+ return r;
507
+ add_test(oneshot, td);
97
+}
508
+ add_test(toggle, td);
98
diff --git a/MAINTAINERS b/MAINTAINERS
509
+ }
99
index XXXXXXX..XXXXXXX 100644
510
+ }
100
--- a/MAINTAINERS
511
+
101
+++ b/MAINTAINERS
512
+ return g_test_run();
102
@@ -XXX,XX +XXX,XX @@ F: include/hw/rtc/pl031.h
513
+}
103
F: include/hw/arm/primecell.h
104
F: hw/timer/cmsdk-apb-timer.c
105
F: include/hw/timer/cmsdk-apb-timer.h
106
+F: tests/qtest/cmsdk-apb-timer-test.c
107
F: hw/timer/cmsdk-apb-dualtimer.c
108
F: include/hw/timer/cmsdk-apb-dualtimer.h
109
F: hw/char/cmsdk-apb-uart.c
110
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
514
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
111
index XXXXXXX..XXXXXXX 100644
515
index XXXXXXX..XXXXXXX 100644
112
--- a/tests/qtest/meson.build
516
--- a/tests/qtest/meson.build
113
+++ b/tests/qtest/meson.build
517
+++ b/tests/qtest/meson.build
114
@@ -XXX,XX +XXX,XX @@ qtests_npcm7xx = \
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',
115
'npcm7xx_timer-test',
524
'npcm7xx_timer-test',
116
'npcm7xx_watchdog_timer-test']
525
'npcm7xx_watchdog_timer-test']
117
qtests_arm = \
118
+ (config_all_devices.has_key('CONFIG_CMSDK_APB_TIMER') ? ['cmsdk-apb-timer-test'] : []) + \
119
(config_all_devices.has_key('CONFIG_PFLASH_CFI02') ? ['pflash-cfi02-test'] : []) + \
120
(config_all_devices.has_key('CONFIG_NPCM7XX') ? qtests_npcm7xx : []) + \
121
['arm-cpu-features',
122
--
526
--
123
2.20.1
527
2.20.1
124
528
125
529
diff view generated by jsdifflib
1
From: Hao Wu <wuhaotsh@google.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
Fix potential overflow problem when calculating pwm_duty.
3
A device shouldn't access its parent object which is QOM internal.
4
1. Ensure p->cmr and p->cnr to be from [0,65535], according to the
4
Instead it should use type cast for this purporse. This patch fixes this
5
hardware specification.
5
issue for all NPCM7XX Devices.
6
2. Changed duty to uint32_t. However, since MAX_DUTY * (p->cmr+1)
7
can excceed UINT32_MAX, we convert them to uint64_t in computation
8
and converted them back to uint32_t.
9
(duty is guaranteed to be <= MAX_DUTY so it won't overflow.)
10
6
11
Fixes: CID 1442342
12
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Doug Evans <dje@google.com>
14
Signed-off-by: Hao Wu <wuhaotsh@google.com>
7
Signed-off-by: Hao Wu <wuhaotsh@google.com>
15
Message-id: 20210127011142.2122790-1-wuhaotsh@google.com
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20210108190945.949196-7-wuhaotsh@google.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
11
---
19
hw/misc/npcm7xx_pwm.c | 23 +++++++++++++++++++----
12
hw/arm/npcm7xx_boards.c | 2 +-
20
tests/qtest/npcm7xx_pwm-test.c | 4 ++--
13
hw/mem/npcm7xx_mc.c | 2 +-
21
2 files changed, 21 insertions(+), 6 deletions(-)
14
hw/misc/npcm7xx_clk.c | 2 +-
15
hw/misc/npcm7xx_gcr.c | 2 +-
16
hw/misc/npcm7xx_rng.c | 2 +-
17
hw/nvram/npcm7xx_otp.c | 2 +-
18
hw/ssi/npcm7xx_fiu.c | 2 +-
19
7 files changed, 7 insertions(+), 7 deletions(-)
22
20
23
diff --git a/hw/misc/npcm7xx_pwm.c b/hw/misc/npcm7xx_pwm.c
21
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
24
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/misc/npcm7xx_pwm.c
23
--- a/hw/arm/npcm7xx_boards.c
26
+++ b/hw/misc/npcm7xx_pwm.c
24
+++ b/hw/arm/npcm7xx_boards.c
27
@@ -XXX,XX +XXX,XX @@ REG32(NPCM7XX_PWM_PWDR3, 0x50);
25
@@ -XXX,XX +XXX,XX @@ static NPCM7xxState *npcm7xx_create_soc(MachineState *machine,
28
#define NPCM7XX_CH_INV BIT(2)
26
uint32_t hw_straps)
29
#define NPCM7XX_CH_MOD BIT(3)
30
31
+#define NPCM7XX_MAX_CMR 65535
32
+#define NPCM7XX_MAX_CNR 65535
33
+
34
/* Offset of each PWM channel's prescaler in the PPR register. */
35
static const int npcm7xx_ppr_base[] = { 0, 0, 8, 8 };
36
/* Offset of each PWM channel's clock selector in the CSR register. */
37
@@ -XXX,XX +XXX,XX @@ static uint32_t npcm7xx_pwm_calculate_freq(NPCM7xxPWM *p)
38
39
static uint32_t npcm7xx_pwm_calculate_duty(NPCM7xxPWM *p)
40
{
27
{
41
- uint64_t duty;
28
NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_GET_CLASS(machine);
42
+ uint32_t duty;
29
- MachineClass *mc = &nmc->parent;
43
30
+ MachineClass *mc = MACHINE_CLASS(nmc);
44
if (p->running) {
31
Object *obj;
45
if (p->cnr == 0) {
32
46
@@ -XXX,XX +XXX,XX @@ static uint32_t npcm7xx_pwm_calculate_duty(NPCM7xxPWM *p)
33
if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
47
} else if (p->cmr >= p->cnr) {
34
diff --git a/hw/mem/npcm7xx_mc.c b/hw/mem/npcm7xx_mc.c
48
duty = NPCM7XX_PWM_MAX_DUTY;
49
} else {
50
- duty = NPCM7XX_PWM_MAX_DUTY * (p->cmr + 1) / (p->cnr + 1);
51
+ duty = (uint64_t)NPCM7XX_PWM_MAX_DUTY * (p->cmr + 1) / (p->cnr + 1);
52
}
53
} else {
54
duty = 0;
55
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_pwm_write(void *opaque, hwaddr offset,
56
case A_NPCM7XX_PWM_CNR2:
57
case A_NPCM7XX_PWM_CNR3:
58
p = &s->pwm[npcm7xx_cnr_index(offset)];
59
- p->cnr = value;
60
+ if (value > NPCM7XX_MAX_CNR) {
61
+ qemu_log_mask(LOG_GUEST_ERROR,
62
+ "%s: invalid cnr value: %u", __func__, value);
63
+ p->cnr = NPCM7XX_MAX_CNR;
64
+ } else {
65
+ p->cnr = value;
66
+ }
67
npcm7xx_pwm_update_output(p);
68
break;
69
70
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_pwm_write(void *opaque, hwaddr offset,
71
case A_NPCM7XX_PWM_CMR2:
72
case A_NPCM7XX_PWM_CMR3:
73
p = &s->pwm[npcm7xx_cmr_index(offset)];
74
- p->cmr = value;
75
+ if (value > NPCM7XX_MAX_CMR) {
76
+ qemu_log_mask(LOG_GUEST_ERROR,
77
+ "%s: invalid cmr value: %u", __func__, value);
78
+ p->cmr = NPCM7XX_MAX_CMR;
79
+ } else {
80
+ p->cmr = value;
81
+ }
82
npcm7xx_pwm_update_output(p);
83
break;
84
85
diff --git a/tests/qtest/npcm7xx_pwm-test.c b/tests/qtest/npcm7xx_pwm-test.c
86
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
87
--- a/tests/qtest/npcm7xx_pwm-test.c
36
--- a/hw/mem/npcm7xx_mc.c
88
+++ b/tests/qtest/npcm7xx_pwm-test.c
37
+++ b/hw/mem/npcm7xx_mc.c
89
@@ -XXX,XX +XXX,XX @@ static uint64_t pwm_compute_freq(QTestState *qts, uint32_t ppr, uint32_t csr,
38
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_mc_realize(DeviceState *dev, Error **errp)
90
39
91
static uint64_t pwm_compute_duty(uint32_t cnr, uint32_t cmr, bool inverted)
40
memory_region_init_io(&s->mmio, OBJECT(s), &npcm7xx_mc_ops, s, "regs",
41
NPCM7XX_MC_REGS_SIZE);
42
- sysbus_init_mmio(&s->parent, &s->mmio);
43
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio);
44
}
45
46
static void npcm7xx_mc_class_init(ObjectClass *klass, void *data)
47
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/misc/npcm7xx_clk.c
50
+++ b/hw/misc/npcm7xx_clk.c
51
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_init(Object *obj)
52
53
memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s,
54
TYPE_NPCM7XX_CLK, 4 * KiB);
55
- sysbus_init_mmio(&s->parent, &s->iomem);
56
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
57
}
58
59
static int npcm7xx_clk_post_load(void *opaque, int version_id)
60
diff --git a/hw/misc/npcm7xx_gcr.c b/hw/misc/npcm7xx_gcr.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/hw/misc/npcm7xx_gcr.c
63
+++ b/hw/misc/npcm7xx_gcr.c
64
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_gcr_init(Object *obj)
65
66
memory_region_init_io(&s->iomem, obj, &npcm7xx_gcr_ops, s,
67
TYPE_NPCM7XX_GCR, 4 * KiB);
68
- sysbus_init_mmio(&s->parent, &s->iomem);
69
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
70
}
71
72
static const VMStateDescription vmstate_npcm7xx_gcr = {
73
diff --git a/hw/misc/npcm7xx_rng.c b/hw/misc/npcm7xx_rng.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/misc/npcm7xx_rng.c
76
+++ b/hw/misc/npcm7xx_rng.c
77
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_rng_init(Object *obj)
78
79
memory_region_init_io(&s->iomem, obj, &npcm7xx_rng_ops, s, "regs",
80
NPCM7XX_RNG_REGS_SIZE);
81
- sysbus_init_mmio(&s->parent, &s->iomem);
82
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
83
}
84
85
static const VMStateDescription vmstate_npcm7xx_rng = {
86
diff --git a/hw/nvram/npcm7xx_otp.c b/hw/nvram/npcm7xx_otp.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/hw/nvram/npcm7xx_otp.c
89
+++ b/hw/nvram/npcm7xx_otp.c
90
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_otp_realize(DeviceState *dev, Error **errp)
92
{
91
{
93
- uint64_t duty;
92
NPCM7xxOTPClass *oc = NPCM7XX_OTP_GET_CLASS(dev);
94
+ uint32_t duty;
93
NPCM7xxOTPState *s = NPCM7XX_OTP(dev);
95
94
- SysBusDevice *sbd = &s->parent;
96
if (cnr == 0) {
95
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
97
/* PWM is stopped. */
96
98
@@ -XXX,XX +XXX,XX @@ static uint64_t pwm_compute_duty(uint32_t cnr, uint32_t cmr, bool inverted)
97
memset(s->array, 0, sizeof(s->array));
99
} else if (cmr >= cnr) {
98
100
duty = MAX_DUTY;
99
diff --git a/hw/ssi/npcm7xx_fiu.c b/hw/ssi/npcm7xx_fiu.c
101
} else {
100
index XXXXXXX..XXXXXXX 100644
102
- duty = MAX_DUTY * (cmr + 1) / (cnr + 1);
101
--- a/hw/ssi/npcm7xx_fiu.c
103
+ duty = (uint64_t)MAX_DUTY * (cmr + 1) / (cnr + 1);
102
+++ b/hw/ssi/npcm7xx_fiu.c
104
}
103
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_fiu_hold_reset(Object *obj)
105
104
static void npcm7xx_fiu_realize(DeviceState *dev, Error **errp)
106
if (inverted) {
105
{
106
NPCM7xxFIUState *s = NPCM7XX_FIU(dev);
107
- SysBusDevice *sbd = &s->parent;
108
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
109
int i;
110
111
if (s->cs_count <= 0) {
107
--
112
--
108
2.20.1
113
2.20.1
109
114
110
115
diff view generated by jsdifflib
Deleted patch
1
Move the preadv availability check to meson.build. This is what we
2
want to be doing for host-OS-feature-checks anyway, but it also fixes
3
a problem with building for macOS with the most recent XCode SDK on a
4
Catalina host.
5
1
6
On that configuration, 'preadv()' is provided as a weak symbol, so
7
that programs can be built with optional support for it and make a
8
runtime availability check to see whether the preadv() they have is a
9
working one or one which they must not call because it will
10
runtime-assert. QEMU's configure test passes (unless you're building
11
with --enable-werror) because the test program using preadv()
12
compiles, but then QEMU crashes at runtime when preadv() is called,
13
with errors like:
14
15
dyld: lazy symbol binding failed: Symbol not found: _preadv
16
Referenced from: /Users/pm215/src/qemu/./build/x86/tests/test-replication
17
Expected in: /usr/lib/libSystem.B.dylib
18
19
dyld: Symbol not found: _preadv
20
Referenced from: /Users/pm215/src/qemu/./build/x86/tests/test-replication
21
Expected in: /usr/lib/libSystem.B.dylib
22
23
Meson's own function availability check has a special case for macOS
24
which adds '-Wl,-no_weak_imports' to the compiler flags, which forces
25
the test to require the real function, not the macOS-version-too-old
26
stub.
27
28
So this commit fixes the bug where macOS builds on Catalina currently
29
require --disable-werror.
30
31
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
32
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
33
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
34
Message-id: 20210126155846.17109-1-peter.maydell@linaro.org
35
---
36
configure | 16 ----------------
37
meson.build | 4 +++-
38
2 files changed, 3 insertions(+), 17 deletions(-)
39
40
diff --git a/configure b/configure
41
index XXXXXXX..XXXXXXX 100755
42
--- a/configure
43
+++ b/configure
44
@@ -XXX,XX +XXX,XX @@ if compile_prog "" "" ; then
45
iovec=yes
46
fi
47
48
-##########################################
49
-# preadv probe
50
-cat > $TMPC <<EOF
51
-#include <sys/types.h>
52
-#include <sys/uio.h>
53
-#include <unistd.h>
54
-int main(void) { return preadv(0, 0, 0, 0); }
55
-EOF
56
-preadv=no
57
-if compile_prog "" "" ; then
58
- preadv=yes
59
-fi
60
-
61
##########################################
62
# fdt probe
63
64
@@ -XXX,XX +XXX,XX @@ fi
65
if test "$iovec" = "yes" ; then
66
echo "CONFIG_IOVEC=y" >> $config_host_mak
67
fi
68
-if test "$preadv" = "yes" ; then
69
- echo "CONFIG_PREADV=y" >> $config_host_mak
70
-fi
71
if test "$membarrier" = "yes" ; then
72
echo "CONFIG_MEMBARRIER=y" >> $config_host_mak
73
fi
74
diff --git a/meson.build b/meson.build
75
index XXXXXXX..XXXXXXX 100644
76
--- a/meson.build
77
+++ b/meson.build
78
@@ -XXX,XX +XXX,XX @@ config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
79
config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
80
config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
81
82
+config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
83
+
84
ignored = ['CONFIG_QEMU_INTERP_PREFIX'] # actually per-target
85
arrays = ['CONFIG_AUDIO_DRIVERS', 'CONFIG_BDRV_RW_WHITELIST', 'CONFIG_BDRV_RO_WHITELIST']
86
strings = ['HOST_DSOSUF', 'CONFIG_IASL']
87
@@ -XXX,XX +XXX,XX @@ summary_info += {'PIE': get_option('b_pie')}
88
summary_info += {'static build': config_host.has_key('CONFIG_STATIC')}
89
summary_info += {'malloc trim support': has_malloc_trim}
90
summary_info += {'membarrier': config_host.has_key('CONFIG_MEMBARRIER')}
91
-summary_info += {'preadv support': config_host.has_key('CONFIG_PREADV')}
92
+summary_info += {'preadv support': config_host_data.get('CONFIG_PREADV')}
93
summary_info += {'fdatasync': config_host.has_key('CONFIG_FDATASYNC')}
94
summary_info += {'madvise': config_host.has_key('CONFIG_MADVISE')}
95
summary_info += {'posix_madvise': config_host.has_key('CONFIG_POSIX_MADVISE')}
96
--
97
2.20.1
98
99
diff view generated by jsdifflib
1
From: Joelle van Dyne <j@getutm.app>
1
From: Roman Bolshakov <r.bolshakov@yadro.com>
2
2
3
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
3
ui/cocoa.m:1188:44: warning: 'openFile:' is deprecated: first deprecated in macOS 11.0 - Use -[NSWorkspace openURL:] instead.
4
Signed-off-by: Joelle van Dyne <j@getutm.app>
4
[-Wdeprecated-declarations]
5
Message-id: 20210126012457.39046-9-j@getutm.app
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
^
11
12
Signed-off-by: Roman Bolshakov <r.bolshakov@yadro.com>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20210102150718.47618-1-r.bolshakov@yadro.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
16
---
8
configure | 5 ++++-
17
ui/cocoa.m | 5 ++++-
9
1 file changed, 4 insertions(+), 1 deletion(-)
18
1 file changed, 4 insertions(+), 1 deletion(-)
10
19
11
diff --git a/configure b/configure
20
diff --git a/ui/cocoa.m b/ui/cocoa.m
12
index XXXXXXX..XXXXXXX 100755
21
index XXXXXXX..XXXXXXX 100644
13
--- a/configure
22
--- a/ui/cocoa.m
14
+++ b/configure
23
+++ b/ui/cocoa.m
15
@@ -XXX,XX +XXX,XX @@ if test "$cross_compile" = "yes"; then
24
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
16
echo "system = 'darwin'" >> $cross
25
/* Where to look for local files */
17
fi
26
NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"docs/"};
18
case "$ARCH" in
27
NSString *full_file_path;
19
- i386|x86_64)
28
+ NSURL *full_file_url;
20
+ i386)
29
21
echo "cpu_family = 'x86'" >> $cross
30
/* iterate thru the possible paths until the file is found */
22
;;
31
int index;
23
+ x86_64)
32
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
24
+ echo "cpu_family = 'x86_64'" >> $cross
33
full_file_path = [full_file_path stringByDeletingLastPathComponent];
25
+ ;;
34
full_file_path = [NSString stringWithFormat: @"%@/%@%@", full_file_path,
26
ppc64le)
35
path_array[index], filename];
27
echo "cpu_family = 'ppc64'" >> $cross
36
- if ([[NSWorkspace sharedWorkspace] openFile: full_file_path] == YES) {
28
;;
37
+ full_file_url = [NSURL fileURLWithPath: full_file_path
38
+ isDirectory: false];
39
+ if ([[NSWorkspace sharedWorkspace] openURL: full_file_url] == YES) {
40
return;
41
}
42
}
29
--
43
--
30
2.20.1
44
2.20.1
31
45
32
46
diff view generated by jsdifflib
Deleted patch
1
From: Joelle van Dyne <j@getutm.app>
2
1
3
On iOS there is no CoreAudio, so we should not assume Darwin always
4
has it.
5
6
Signed-off-by: Joelle van Dyne <j@getutm.app>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20210126012457.39046-11-j@getutm.app
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
configure | 35 +++++++++++++++++++++++++++++++++--
12
1 file changed, 33 insertions(+), 2 deletions(-)
13
14
diff --git a/configure b/configure
15
index XXXXXXX..XXXXXXX 100755
16
--- a/configure
17
+++ b/configure
18
@@ -XXX,XX +XXX,XX @@ fdt="auto"
19
netmap="no"
20
sdl="auto"
21
sdl_image="auto"
22
+coreaudio="auto"
23
virtiofsd="auto"
24
virtfs="auto"
25
libudev="auto"
26
@@ -XXX,XX +XXX,XX @@ Darwin)
27
QEMU_CFLAGS="-arch x86_64 $QEMU_CFLAGS"
28
QEMU_LDFLAGS="-arch x86_64 $QEMU_LDFLAGS"
29
fi
30
- audio_drv_list="coreaudio try-sdl"
31
+ audio_drv_list="try-coreaudio try-sdl"
32
audio_possible_drivers="coreaudio sdl"
33
# Disable attempts to use ObjectiveC features in os/object.h since they
34
# won't work when we're compiling with gcc as a C compiler.
35
@@ -XXX,XX +XXX,XX @@ EOF
36
fi
37
fi
38
39
+##########################################
40
+# detect CoreAudio
41
+if test "$coreaudio" != "no" ; then
42
+ coreaudio_libs="-framework CoreAudio"
43
+ cat > $TMPC << EOF
44
+#include <CoreAudio/CoreAudio.h>
45
+int main(void)
46
+{
47
+ return (int)AudioGetCurrentHostTime();
48
+}
49
+EOF
50
+ if compile_prog "" "$coreaudio_libs" ; then
51
+ coreaudio=yes
52
+ else
53
+ coreaudio=no
54
+ fi
55
+fi
56
+
57
##########################################
58
# Sound support libraries probe
59
60
@@ -XXX,XX +XXX,XX @@ for drv in $audio_drv_list; do
61
fi
62
;;
63
64
- coreaudio)
65
+ coreaudio | try-coreaudio)
66
+ if test "$coreaudio" = "no"; then
67
+ if test "$drv" = "try-coreaudio"; then
68
+ audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-coreaudio//')
69
+ else
70
+ error_exit "$drv check failed" \
71
+ "Make sure to have the $drv is available."
72
+ fi
73
+ else
74
coreaudio_libs="-framework CoreAudio"
75
+ if test "$drv" = "try-coreaudio"; then
76
+ audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-coreaudio/coreaudio/')
77
+ fi
78
+ fi
79
;;
80
81
dsound)
82
--
83
2.20.1
84
85
diff view generated by jsdifflib
Deleted patch
1
From: Joelle van Dyne <j@getutm.app>
2
1
3
A workaround added in early days of 64-bit OSX forced x86_64 if the
4
host machine had 64-bit support. This creates issues when cross-
5
compiling for ARM64. Additionally, the user can always use --cpu=* to
6
manually set the host CPU and therefore this workaround should be
7
removed.
8
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Joelle van Dyne <j@getutm.app>
11
Message-id: 20210126012457.39046-12-j@getutm.app
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
configure | 11 -----------
15
1 file changed, 11 deletions(-)
16
17
diff --git a/configure b/configure
18
index XXXXXXX..XXXXXXX 100755
19
--- a/configure
20
+++ b/configure
21
@@ -XXX,XX +XXX,XX @@ fi
22
# the correct CPU with the --cpu option.
23
case $targetos in
24
Darwin)
25
- # on Leopard most of the system is 32-bit, so we have to ask the kernel if we can
26
- # run 64-bit userspace code.
27
- # If the user didn't specify a CPU explicitly and the kernel says this is
28
- # 64 bit hw, then assume x86_64. Otherwise fall through to the usual detection code.
29
- if test -z "$cpu" && test "$(sysctl -n hw.optional.x86_64)" = "1"; then
30
- cpu="x86_64"
31
- fi
32
HOST_DSOSUF=".dylib"
33
;;
34
SunOS)
35
@@ -XXX,XX +XXX,XX @@ OpenBSD)
36
Darwin)
37
bsd="yes"
38
darwin="yes"
39
- if [ "$cpu" = "x86_64" ] ; then
40
- QEMU_CFLAGS="-arch x86_64 $QEMU_CFLAGS"
41
- QEMU_LDFLAGS="-arch x86_64 $QEMU_LDFLAGS"
42
- fi
43
audio_drv_list="try-coreaudio try-sdl"
44
audio_possible_drivers="coreaudio sdl"
45
# Disable attempts to use ObjectiveC features in os/object.h since they
46
--
47
2.20.1
48
49
diff view generated by jsdifflib
Deleted patch
1
From: Alexander Graf <agraf@csgraf.de>
2
1
3
In macOS 11, QEMU only gets access to Hypervisor.framework if it has the
4
respective entitlement. Add an entitlement template and automatically self
5
sign and apply the entitlement in the build.
6
7
Signed-off-by: Alexander Graf <agraf@csgraf.de>
8
Reviewed-by: Roman Bolshakov <r.bolshakov@yadro.com>
9
Tested-by: Roman Bolshakov <r.bolshakov@yadro.com>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
meson.build | 29 +++++++++++++++++++++++++----
13
accel/hvf/entitlements.plist | 8 ++++++++
14
scripts/entitlement.sh | 13 +++++++++++++
15
3 files changed, 46 insertions(+), 4 deletions(-)
16
create mode 100644 accel/hvf/entitlements.plist
17
create mode 100755 scripts/entitlement.sh
18
19
diff --git a/meson.build b/meson.build
20
index XXXXXXX..XXXXXXX 100644
21
--- a/meson.build
22
+++ b/meson.build
23
@@ -XXX,XX +XXX,XX @@ foreach target : target_dirs
24
}]
25
endif
26
foreach exe: execs
27
- emulators += {exe['name']:
28
- executable(exe['name'], exe['sources'],
29
- install: true,
30
+ exe_name = exe['name']
31
+ exe_sign = 'CONFIG_HVF' in config_target
32
+ if exe_sign
33
+ exe_name += '-unsigned'
34
+ endif
35
+
36
+ emulator = executable(exe_name, exe['sources'],
37
+ install: not exe_sign,
38
c_args: c_args,
39
dependencies: arch_deps + deps + exe['dependencies'],
40
objects: lib.extract_all_objects(recursive: true),
41
@@ -XXX,XX +XXX,XX @@ foreach target : target_dirs
42
link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []),
43
link_args: link_args,
44
gui_app: exe['gui'])
45
- }
46
+
47
+ if exe_sign
48
+ emulators += {exe['name'] : custom_target(exe['name'],
49
+ install: true,
50
+ install_dir: get_option('bindir'),
51
+ depends: emulator,
52
+ output: exe['name'],
53
+ command: [
54
+ meson.current_source_dir() / 'scripts/entitlement.sh',
55
+ meson.current_build_dir() / exe_name,
56
+ meson.current_build_dir() / exe['name'],
57
+ meson.current_source_dir() / 'accel/hvf/entitlements.plist'
58
+ ])
59
+ }
60
+ else
61
+ emulators += {exe['name']: emulator}
62
+ endif
63
64
if 'CONFIG_TRACE_SYSTEMTAP' in config_host
65
foreach stp: [
66
diff --git a/accel/hvf/entitlements.plist b/accel/hvf/entitlements.plist
67
new file mode 100644
68
index XXXXXXX..XXXXXXX
69
--- /dev/null
70
+++ b/accel/hvf/entitlements.plist
71
@@ -XXX,XX +XXX,XX @@
72
+<?xml version="1.0" encoding="UTF-8"?>
73
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
74
+<plist version="1.0">
75
+<dict>
76
+ <key>com.apple.security.hypervisor</key>
77
+ <true/>
78
+</dict>
79
+</plist>
80
diff --git a/scripts/entitlement.sh b/scripts/entitlement.sh
81
new file mode 100755
82
index XXXXXXX..XXXXXXX
83
--- /dev/null
84
+++ b/scripts/entitlement.sh
85
@@ -XXX,XX +XXX,XX @@
86
+#!/bin/sh -e
87
+#
88
+# Helper script for the build process to apply entitlements
89
+
90
+SRC="$1"
91
+DST="$2"
92
+ENTITLEMENT="$3"
93
+
94
+trap 'rm "$DST.tmp"' exit
95
+cp -af "$SRC" "$DST.tmp"
96
+codesign --entitlements "$ENTITLEMENT" --force -s - "$DST.tmp"
97
+mv "$DST.tmp" "$DST"
98
+trap '' exit
99
--
100
2.20.1
101
102
diff view generated by jsdifflib
Deleted patch
1
From: Mihai Carabas <mihai.carabas@oracle.com>
2
1
3
Add PCI interface support for PVPANIC device. Create a new file pvpanic-pci.c
4
where the PCI specific routines reside and update the build system with the new
5
files and config structure.
6
7
Signed-off-by: Mihai Carabas <mihai.carabas@oracle.com>
8
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Mihai Carabas <mihai.carabas@oracle.com>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
docs/specs/pci-ids.txt | 1 +
14
include/hw/misc/pvpanic.h | 1 +
15
include/hw/pci/pci.h | 1 +
16
hw/misc/pvpanic-pci.c | 94 +++++++++++++++++++++++++++++++++++++++
17
hw/misc/Kconfig | 6 +++
18
hw/misc/meson.build | 1 +
19
6 files changed, 104 insertions(+)
20
create mode 100644 hw/misc/pvpanic-pci.c
21
22
diff --git a/docs/specs/pci-ids.txt b/docs/specs/pci-ids.txt
23
index XXXXXXX..XXXXXXX 100644
24
--- a/docs/specs/pci-ids.txt
25
+++ b/docs/specs/pci-ids.txt
26
@@ -XXX,XX +XXX,XX @@ PCI devices (other than virtio):
27
1b36:000d PCI xhci usb host adapter
28
1b36:000f mdpy (mdev sample device), linux/samples/vfio-mdev/mdpy.c
29
1b36:0010 PCIe NVMe device (-device nvme)
30
+1b36:0011 PCI PVPanic device (-device pvpanic-pci)
31
32
All these devices are documented in docs/specs.
33
34
diff --git a/include/hw/misc/pvpanic.h b/include/hw/misc/pvpanic.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/include/hw/misc/pvpanic.h
37
+++ b/include/hw/misc/pvpanic.h
38
@@ -XXX,XX +XXX,XX @@
39
#include "qom/object.h"
40
41
#define TYPE_PVPANIC_ISA_DEVICE "pvpanic"
42
+#define TYPE_PVPANIC_PCI_DEVICE "pvpanic-pci"
43
44
#define PVPANIC_IOPORT_PROP "ioport"
45
46
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
47
index XXXXXXX..XXXXXXX 100644
48
--- a/include/hw/pci/pci.h
49
+++ b/include/hw/pci/pci.h
50
@@ -XXX,XX +XXX,XX @@ extern bool pci_available;
51
#define PCI_DEVICE_ID_REDHAT_PCIE_BRIDGE 0x000e
52
#define PCI_DEVICE_ID_REDHAT_MDPY 0x000f
53
#define PCI_DEVICE_ID_REDHAT_NVME 0x0010
54
+#define PCI_DEVICE_ID_REDHAT_PVPANIC 0x0011
55
#define PCI_DEVICE_ID_REDHAT_QXL 0x0100
56
57
#define FMT_PCIBUS PRIx64
58
diff --git a/hw/misc/pvpanic-pci.c b/hw/misc/pvpanic-pci.c
59
new file mode 100644
60
index XXXXXXX..XXXXXXX
61
--- /dev/null
62
+++ b/hw/misc/pvpanic-pci.c
63
@@ -XXX,XX +XXX,XX @@
64
+/*
65
+ * QEMU simulated PCI pvpanic device.
66
+ *
67
+ * Copyright (C) 2020 Oracle
68
+ *
69
+ * Authors:
70
+ * Mihai Carabas <mihai.carabas@oracle.com>
71
+ *
72
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
73
+ * See the COPYING file in the top-level directory.
74
+ *
75
+ */
76
+
77
+#include "qemu/osdep.h"
78
+#include "qemu/log.h"
79
+#include "qemu/module.h"
80
+#include "sysemu/runstate.h"
81
+
82
+#include "hw/nvram/fw_cfg.h"
83
+#include "hw/qdev-properties.h"
84
+#include "migration/vmstate.h"
85
+#include "hw/misc/pvpanic.h"
86
+#include "qom/object.h"
87
+#include "hw/pci/pci.h"
88
+
89
+OBJECT_DECLARE_SIMPLE_TYPE(PVPanicPCIState, PVPANIC_PCI_DEVICE)
90
+
91
+/*
92
+ * PVPanicPCIState for PCI device
93
+ */
94
+typedef struct PVPanicPCIState {
95
+ PCIDevice dev;
96
+ PVPanicState pvpanic;
97
+} PVPanicPCIState;
98
+
99
+static const VMStateDescription vmstate_pvpanic_pci = {
100
+ .name = "pvpanic-pci",
101
+ .version_id = 1,
102
+ .minimum_version_id = 1,
103
+ .fields = (VMStateField[]) {
104
+ VMSTATE_PCI_DEVICE(dev, PVPanicPCIState),
105
+ VMSTATE_END_OF_LIST()
106
+ }
107
+};
108
+
109
+static void pvpanic_pci_realizefn(PCIDevice *dev, Error **errp)
110
+{
111
+ PVPanicPCIState *s = PVPANIC_PCI_DEVICE(dev);
112
+ PVPanicState *ps = &s->pvpanic;
113
+
114
+ pvpanic_setup_io(&s->pvpanic, DEVICE(s), 2);
115
+
116
+ pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &ps->mr);
117
+}
118
+
119
+static Property pvpanic_pci_properties[] = {
120
+ DEFINE_PROP_UINT8("events", PVPanicPCIState, pvpanic.events, PVPANIC_PANICKED | PVPANIC_CRASHLOADED),
121
+ DEFINE_PROP_END_OF_LIST(),
122
+};
123
+
124
+static void pvpanic_pci_class_init(ObjectClass *klass, void *data)
125
+{
126
+ DeviceClass *dc = DEVICE_CLASS(klass);
127
+ PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass);
128
+
129
+ device_class_set_props(dc, pvpanic_pci_properties);
130
+
131
+ pc->realize = pvpanic_pci_realizefn;
132
+ pc->vendor_id = PCI_VENDOR_ID_REDHAT;
133
+ pc->device_id = PCI_DEVICE_ID_REDHAT_PVPANIC;
134
+ pc->revision = 1;
135
+ pc->class_id = PCI_CLASS_SYSTEM_OTHER;
136
+ dc->vmsd = &vmstate_pvpanic_pci;
137
+
138
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
139
+}
140
+
141
+static TypeInfo pvpanic_pci_info = {
142
+ .name = TYPE_PVPANIC_PCI_DEVICE,
143
+ .parent = TYPE_PCI_DEVICE,
144
+ .instance_size = sizeof(PVPanicPCIState),
145
+ .class_init = pvpanic_pci_class_init,
146
+ .interfaces = (InterfaceInfo[]) {
147
+ { INTERFACE_CONVENTIONAL_PCI_DEVICE },
148
+ { }
149
+ }
150
+};
151
+
152
+static void pvpanic_register_types(void)
153
+{
154
+ type_register_static(&pvpanic_pci_info);
155
+}
156
+
157
+type_init(pvpanic_register_types);
158
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
159
index XXXXXXX..XXXXXXX 100644
160
--- a/hw/misc/Kconfig
161
+++ b/hw/misc/Kconfig
162
@@ -XXX,XX +XXX,XX @@ config IOTKIT_SYSINFO
163
config PVPANIC_COMMON
164
bool
165
166
+config PVPANIC_PCI
167
+ bool
168
+ default y if PCI_DEVICES
169
+ depends on PCI
170
+ select PVPANIC_COMMON
171
+
172
config PVPANIC_ISA
173
bool
174
depends on ISA_BUS
175
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
176
index XXXXXXX..XXXXXXX 100644
177
--- a/hw/misc/meson.build
178
+++ b/hw/misc/meson.build
179
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_ARMSSE_CPUID', if_true: files('armsse-cpuid.c'))
180
softmmu_ss.add(when: 'CONFIG_ARMSSE_MHU', if_true: files('armsse-mhu.c'))
181
182
softmmu_ss.add(when: 'CONFIG_PVPANIC_ISA', if_true: files('pvpanic-isa.c'))
183
+softmmu_ss.add(when: 'CONFIG_PVPANIC_PCI', if_true: files('pvpanic-pci.c'))
184
softmmu_ss.add(when: 'CONFIG_AUX', if_true: files('auxbus.c'))
185
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_scu.c', 'aspeed_sdmc.c', 'aspeed_xdma.c'))
186
softmmu_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-sysreg.c'))
187
--
188
2.20.1
189
190
diff view generated by jsdifflib
Deleted patch
1
From: Mihai Carabas <mihai.carabas@oracle.com>
2
1
3
Add a test case for pvpanic-pci device. The scenario is the same as pvpanic
4
ISA device, but is using the PCI bus.
5
6
Signed-off-by: Mihai Carabas <mihai.carabas@oracle.com>
7
Acked-by: Thomas Huth <thuth@redhat.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Mihai Carabas <mihai.carabas@oracle.com>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
tests/qtest/pvpanic-pci-test.c | 94 ++++++++++++++++++++++++++++++++++
13
tests/qtest/meson.build | 1 +
14
2 files changed, 95 insertions(+)
15
create mode 100644 tests/qtest/pvpanic-pci-test.c
16
17
diff --git a/tests/qtest/pvpanic-pci-test.c b/tests/qtest/pvpanic-pci-test.c
18
new file mode 100644
19
index XXXXXXX..XXXXXXX
20
--- /dev/null
21
+++ b/tests/qtest/pvpanic-pci-test.c
22
@@ -XXX,XX +XXX,XX @@
23
+/*
24
+ * QTest testcase for PV Panic PCI device
25
+ *
26
+ * Copyright (C) 2020 Oracle
27
+ *
28
+ * Authors:
29
+ * Mihai Carabas <mihai.carabas@oracle.com>
30
+ *
31
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
32
+ * See the COPYING file in the top-level directory.
33
+ *
34
+ */
35
+
36
+#include "qemu/osdep.h"
37
+#include "libqos/libqtest.h"
38
+#include "qapi/qmp/qdict.h"
39
+#include "libqos/pci.h"
40
+#include "libqos/pci-pc.h"
41
+#include "hw/pci/pci_regs.h"
42
+
43
+static void test_panic_nopause(void)
44
+{
45
+ uint8_t val;
46
+ QDict *response, *data;
47
+ QTestState *qts;
48
+ QPCIBus *pcibus;
49
+ QPCIDevice *dev;
50
+ QPCIBar bar;
51
+
52
+ qts = qtest_init("-device pvpanic-pci,addr=04.0 -action panic=none");
53
+ pcibus = qpci_new_pc(qts, NULL);
54
+ dev = qpci_device_find(pcibus, QPCI_DEVFN(0x4, 0x0));
55
+ qpci_device_enable(dev);
56
+ bar = qpci_iomap(dev, 0, NULL);
57
+
58
+ qpci_memread(dev, bar, 0, &val, sizeof(val));
59
+ g_assert_cmpuint(val, ==, 3);
60
+
61
+ val = 1;
62
+ qpci_memwrite(dev, bar, 0, &val, sizeof(val));
63
+
64
+ response = qtest_qmp_eventwait_ref(qts, "GUEST_PANICKED");
65
+ g_assert(qdict_haskey(response, "data"));
66
+ data = qdict_get_qdict(response, "data");
67
+ g_assert(qdict_haskey(data, "action"));
68
+ g_assert_cmpstr(qdict_get_str(data, "action"), ==, "run");
69
+ qobject_unref(response);
70
+
71
+ qtest_quit(qts);
72
+}
73
+
74
+static void test_panic(void)
75
+{
76
+ uint8_t val;
77
+ QDict *response, *data;
78
+ QTestState *qts;
79
+ QPCIBus *pcibus;
80
+ QPCIDevice *dev;
81
+ QPCIBar bar;
82
+
83
+ qts = qtest_init("-device pvpanic-pci,addr=04.0 -action panic=pause");
84
+ pcibus = qpci_new_pc(qts, NULL);
85
+ dev = qpci_device_find(pcibus, QPCI_DEVFN(0x4, 0x0));
86
+ qpci_device_enable(dev);
87
+ bar = qpci_iomap(dev, 0, NULL);
88
+
89
+ qpci_memread(dev, bar, 0, &val, sizeof(val));
90
+ g_assert_cmpuint(val, ==, 3);
91
+
92
+ val = 1;
93
+ qpci_memwrite(dev, bar, 0, &val, sizeof(val));
94
+
95
+ response = qtest_qmp_eventwait_ref(qts, "GUEST_PANICKED");
96
+ g_assert(qdict_haskey(response, "data"));
97
+ data = qdict_get_qdict(response, "data");
98
+ g_assert(qdict_haskey(data, "action"));
99
+ g_assert_cmpstr(qdict_get_str(data, "action"), ==, "pause");
100
+ qobject_unref(response);
101
+
102
+ qtest_quit(qts);
103
+}
104
+
105
+int main(int argc, char **argv)
106
+{
107
+ int ret;
108
+
109
+ g_test_init(&argc, &argv, NULL);
110
+ qtest_add_func("/pvpanic-pci/panic", test_panic);
111
+ qtest_add_func("/pvpanic-pci/panic-nopause", test_panic_nopause);
112
+
113
+ ret = g_test_run();
114
+
115
+ return ret;
116
+}
117
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
118
index XXXXXXX..XXXXXXX 100644
119
--- a/tests/qtest/meson.build
120
+++ b/tests/qtest/meson.build
121
@@ -XXX,XX +XXX,XX @@ qtests_i386 = \
122
config_all_devices.has_key('CONFIG_ISA_IPMI_BT') ? ['ipmi-bt-test'] : []) + \
123
(config_all_devices.has_key('CONFIG_WDT_IB700') ? ['wdt_ib700-test'] : []) + \
124
(config_all_devices.has_key('CONFIG_PVPANIC_ISA') ? ['pvpanic-test'] : []) + \
125
+ (config_all_devices.has_key('CONFIG_PVPANIC_PCI') ? ['pvpanic-pci-test'] : []) + \
126
(config_all_devices.has_key('CONFIG_HDA') ? ['intel-hda-test'] : []) + \
127
(config_all_devices.has_key('CONFIG_I82801B11') ? ['i82801b11-test'] : []) + \
128
(config_all_devices.has_key('CONFIG_IOH3420') ? ['ioh3420-test'] : []) + \
129
--
130
2.20.1
131
132
diff view generated by jsdifflib
Deleted patch
1
The ptimer API currently provides two methods for setting the period:
2
ptimer_set_period(), which takes a period in nanoseconds, and
3
ptimer_set_freq(), which takes a frequency in Hz. Neither of these
4
lines up nicely with the Clock API, because although both the Clock
5
and the ptimer track the frequency using a representation of whole
6
and fractional nanoseconds, conversion via either period-in-ns or
7
frequency-in-Hz will introduce a rounding error.
8
1
9
Add a new function ptimer_set_period_from_clock() which takes the
10
Clock object directly to avoid the rounding issues. This includes a
11
facility for the user to specify that there is a frequency divider
12
between the Clock proper and the timer, as some timer devices like
13
the CMSDK APB dualtimer need this.
14
15
To avoid having to drag in clock.h from ptimer.h we add the Clock
16
type to typedefs.h.
17
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Luc Michel <luc@lmichel.fr>
20
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
21
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
22
Message-id: 20210128114145.20536-2-peter.maydell@linaro.org
23
Message-id: 20210121190622.22000-2-peter.maydell@linaro.org
24
---
25
include/hw/ptimer.h | 22 ++++++++++++++++++++++
26
include/qemu/typedefs.h | 1 +
27
hw/core/ptimer.c | 34 ++++++++++++++++++++++++++++++++++
28
3 files changed, 57 insertions(+)
29
30
diff --git a/include/hw/ptimer.h b/include/hw/ptimer.h
31
index XXXXXXX..XXXXXXX 100644
32
--- a/include/hw/ptimer.h
33
+++ b/include/hw/ptimer.h
34
@@ -XXX,XX +XXX,XX @@ void ptimer_transaction_commit(ptimer_state *s);
35
*/
36
void ptimer_set_period(ptimer_state *s, int64_t period);
37
38
+/**
39
+ * ptimer_set_period_from_clock - Set counter increment from a Clock
40
+ * @s: ptimer to configure
41
+ * @clk: pointer to Clock object to take period from
42
+ * @divisor: value to scale the clock frequency down by
43
+ *
44
+ * If the ptimer is being driven from a Clock, this is the preferred
45
+ * way to tell the ptimer about the period, because it avoids any
46
+ * possible rounding errors that might happen if the internal
47
+ * representation of the Clock period was converted to either a period
48
+ * in ns or a frequency in Hz.
49
+ *
50
+ * If the ptimer should run at the same frequency as the clock,
51
+ * pass 1 as the @divisor; if the ptimer should run at half the
52
+ * frequency, pass 2, and so on.
53
+ *
54
+ * This function will assert if it is called outside a
55
+ * ptimer_transaction_begin/commit block.
56
+ */
57
+void ptimer_set_period_from_clock(ptimer_state *s, const Clock *clock,
58
+ unsigned int divisor);
59
+
60
/**
61
* ptimer_set_freq - Set counter frequency in Hz
62
* @s: ptimer to configure
63
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
64
index XXXXXXX..XXXXXXX 100644
65
--- a/include/qemu/typedefs.h
66
+++ b/include/qemu/typedefs.h
67
@@ -XXX,XX +XXX,XX @@ typedef struct BlockDriverState BlockDriverState;
68
typedef struct BusClass BusClass;
69
typedef struct BusState BusState;
70
typedef struct Chardev Chardev;
71
+typedef struct Clock Clock;
72
typedef struct CompatProperty CompatProperty;
73
typedef struct CoMutex CoMutex;
74
typedef struct CPUAddressSpace CPUAddressSpace;
75
diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/hw/core/ptimer.c
78
+++ b/hw/core/ptimer.c
79
@@ -XXX,XX +XXX,XX @@
80
#include "sysemu/qtest.h"
81
#include "block/aio.h"
82
#include "sysemu/cpus.h"
83
+#include "hw/clock.h"
84
85
#define DELTA_ADJUST 1
86
#define DELTA_NO_ADJUST -1
87
@@ -XXX,XX +XXX,XX @@ void ptimer_set_period(ptimer_state *s, int64_t period)
88
}
89
}
90
91
+/* Set counter increment interval from a Clock */
92
+void ptimer_set_period_from_clock(ptimer_state *s, const Clock *clk,
93
+ unsigned int divisor)
94
+{
95
+ /*
96
+ * The raw clock period is a 64-bit value in units of 2^-32 ns;
97
+ * put another way it's a 32.32 fixed-point ns value. Our internal
98
+ * representation of the period is 64.32 fixed point ns, so
99
+ * the conversion is simple.
100
+ */
101
+ uint64_t raw_period = clock_get(clk);
102
+ uint64_t period_frac;
103
+
104
+ assert(s->in_transaction);
105
+ s->delta = ptimer_get_count(s);
106
+ s->period = extract64(raw_period, 32, 32);
107
+ period_frac = extract64(raw_period, 0, 32);
108
+ /*
109
+ * divisor specifies a possible frequency divisor between the
110
+ * clock and the timer, so it is a multiplier on the period.
111
+ * We do the multiply after splitting the raw period out into
112
+ * period and frac to avoid having to do a 32*64->96 multiply.
113
+ */
114
+ s->period *= divisor;
115
+ period_frac *= divisor;
116
+ s->period += extract64(period_frac, 32, 32);
117
+ s->period_frac = (uint32_t)period_frac;
118
+
119
+ if (s->enabled) {
120
+ s->need_reload = true;
121
+ }
122
+}
123
+
124
/* Set counter frequency in Hz. */
125
void ptimer_set_freq(ptimer_state *s, uint32_t freq)
126
{
127
--
128
2.20.1
129
130
diff view generated by jsdifflib
Deleted patch
1
Add a function for checking whether a clock has a source. This is
2
useful for devices which have input clocks that must be wired up by
3
the board as it allows them to fail in realize rather than ploughing
4
on with a zero-period clock.
5
1
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20210128114145.20536-3-peter.maydell@linaro.org
11
Message-id: 20210121190622.22000-3-peter.maydell@linaro.org
12
---
13
docs/devel/clocks.rst | 16 ++++++++++++++++
14
include/hw/clock.h | 15 +++++++++++++++
15
2 files changed, 31 insertions(+)
16
17
diff --git a/docs/devel/clocks.rst b/docs/devel/clocks.rst
18
index XXXXXXX..XXXXXXX 100644
19
--- a/docs/devel/clocks.rst
20
+++ b/docs/devel/clocks.rst
21
@@ -XXX,XX +XXX,XX @@ object during device instance init. For example:
22
/* set initial value to 10ns / 100MHz */
23
clock_set_ns(clk, 10);
24
25
+To enforce that the clock is wired up by the board code, you can
26
+call ``clock_has_source()`` in your device's realize method:
27
+
28
+.. code-block:: c
29
+
30
+ if (!clock_has_source(s->clk)) {
31
+ error_setg(errp, "MyDevice: clk input must be connected");
32
+ return;
33
+ }
34
+
35
+Note that this only checks that the clock has been wired up; it is
36
+still possible that the output clock connected to it is disabled
37
+or has not yet been configured, in which case the period will be
38
+zero. You should use the clock callback to find out when the clock
39
+period changes.
40
+
41
Fetching clock frequency/period
42
-------------------------------
43
44
diff --git a/include/hw/clock.h b/include/hw/clock.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/hw/clock.h
47
+++ b/include/hw/clock.h
48
@@ -XXX,XX +XXX,XX @@ void clock_clear_callback(Clock *clk);
49
*/
50
void clock_set_source(Clock *clk, Clock *src);
51
52
+/**
53
+ * clock_has_source:
54
+ * @clk: the clock
55
+ *
56
+ * Returns true if the clock has a source clock connected to it.
57
+ * This is useful for devices which have input clocks which must
58
+ * be connected by the board/SoC code which creates them. The
59
+ * device code can use this to check in its realize method that
60
+ * the clock has been connected.
61
+ */
62
+static inline bool clock_has_source(const Clock *clk)
63
+{
64
+ return clk->source != NULL;
65
+}
66
+
67
/**
68
* clock_set:
69
* @clk: the clock to initialize.
70
--
71
2.20.1
72
73
diff view generated by jsdifflib
Deleted patch
1
Add a simple test of the CMSDK watchdog, since we're about to do some
2
refactoring of how it is clocked.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Luc Michel <luc@lmichel.fr>
6
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20210128114145.20536-5-peter.maydell@linaro.org
9
Message-id: 20210121190622.22000-5-peter.maydell@linaro.org
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
---
12
tests/qtest/cmsdk-apb-watchdog-test.c | 79 +++++++++++++++++++++++++++
13
MAINTAINERS | 1 +
14
tests/qtest/meson.build | 1 +
15
3 files changed, 81 insertions(+)
16
create mode 100644 tests/qtest/cmsdk-apb-watchdog-test.c
17
18
diff --git a/tests/qtest/cmsdk-apb-watchdog-test.c b/tests/qtest/cmsdk-apb-watchdog-test.c
19
new file mode 100644
20
index XXXXXXX..XXXXXXX
21
--- /dev/null
22
+++ b/tests/qtest/cmsdk-apb-watchdog-test.c
23
@@ -XXX,XX +XXX,XX @@
24
+/*
25
+ * QTest testcase for the CMSDK APB watchdog device
26
+ *
27
+ * Copyright (c) 2021 Linaro Limited
28
+ *
29
+ * This program is free software; you can redistribute it and/or modify it
30
+ * under the terms of the GNU General Public License as published by the
31
+ * Free Software Foundation; either version 2 of the License, or
32
+ * (at your option) any later version.
33
+ *
34
+ * This program is distributed in the hope that it will be useful, but WITHOUT
35
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
36
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
37
+ * for more details.
38
+ */
39
+
40
+#include "qemu/osdep.h"
41
+#include "libqtest-single.h"
42
+
43
+/*
44
+ * lm3s811evb watchdog; at board startup this runs at 200MHz / 16 == 12.5MHz,
45
+ * which is 80ns per tick.
46
+ */
47
+#define WDOG_BASE 0x40000000
48
+
49
+#define WDOGLOAD 0
50
+#define WDOGVALUE 4
51
+#define WDOGCONTROL 8
52
+#define WDOGINTCLR 0xc
53
+#define WDOGRIS 0x10
54
+#define WDOGMIS 0x14
55
+#define WDOGLOCK 0xc00
56
+
57
+static void test_watchdog(void)
58
+{
59
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
60
+
61
+ writel(WDOG_BASE + WDOGCONTROL, 1);
62
+ writel(WDOG_BASE + WDOGLOAD, 1000);
63
+
64
+ /* Step to just past the 500th tick */
65
+ clock_step(500 * 80 + 1);
66
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
67
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 500);
68
+
69
+ /* Just past the 1000th tick: timer should have fired */
70
+ clock_step(500 * 80);
71
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 1);
72
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 0);
73
+
74
+ /* VALUE reloads at following tick */
75
+ clock_step(80);
76
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 1000);
77
+
78
+ /* Writing any value to WDOGINTCLR clears the interrupt and reloads */
79
+ clock_step(500 * 80);
80
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 500);
81
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 1);
82
+ writel(WDOG_BASE + WDOGINTCLR, 0);
83
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 1000);
84
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
85
+}
86
+
87
+int main(int argc, char **argv)
88
+{
89
+ int r;
90
+
91
+ g_test_init(&argc, &argv, NULL);
92
+
93
+ qtest_start("-machine lm3s811evb");
94
+
95
+ qtest_add_func("/cmsdk-apb-watchdog/watchdog", test_watchdog);
96
+
97
+ r = g_test_run();
98
+
99
+ qtest_end();
100
+
101
+ return r;
102
+}
103
diff --git a/MAINTAINERS b/MAINTAINERS
104
index XXXXXXX..XXXXXXX 100644
105
--- a/MAINTAINERS
106
+++ b/MAINTAINERS
107
@@ -XXX,XX +XXX,XX @@ F: hw/char/cmsdk-apb-uart.c
108
F: include/hw/char/cmsdk-apb-uart.h
109
F: hw/watchdog/cmsdk-apb-watchdog.c
110
F: include/hw/watchdog/cmsdk-apb-watchdog.h
111
+F: tests/qtest/cmsdk-apb-watchdog-test.c
112
F: hw/misc/tz-ppc.c
113
F: include/hw/misc/tz-ppc.h
114
F: hw/misc/tz-mpc.c
115
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
116
index XXXXXXX..XXXXXXX 100644
117
--- a/tests/qtest/meson.build
118
+++ b/tests/qtest/meson.build
119
@@ -XXX,XX +XXX,XX @@ qtests_npcm7xx = \
120
'npcm7xx_watchdog_timer-test']
121
qtests_arm = \
122
(config_all_devices.has_key('CONFIG_CMSDK_APB_TIMER') ? ['cmsdk-apb-timer-test'] : []) + \
123
+ (config_all_devices.has_key('CONFIG_CMSDK_APB_WATCHDOG') ? ['cmsdk-apb-watchdog-test'] : []) + \
124
(config_all_devices.has_key('CONFIG_PFLASH_CFI02') ? ['pflash-cfi02-test'] : []) + \
125
(config_all_devices.has_key('CONFIG_NPCM7XX') ? qtests_npcm7xx : []) + \
126
['arm-cpu-features',
127
--
128
2.20.1
129
130
diff view generated by jsdifflib
Deleted patch
1
The state struct for the CMSDK APB timer device doesn't follow our
2
usual naming convention of camelcase -- "CMSDK" and "APB" are both
3
acronyms, but "TIMER" is not so should not be all-uppercase.
4
Globally rename the struct to "CMSDKAPBTimer" (bringing it into line
5
with CMSDKAPBWatchdog and CMSDKAPBDualTimer; CMSDKAPBUART remains
6
as-is because "UART" is an acronym).
7
1
8
Commit created with:
9
perl -p -i -e 's/CMSDKAPBTIMER/CMSDKAPBTimer/g' hw/timer/cmsdk-apb-timer.c include/hw/arm/armsse.h include/hw/timer/cmsdk-apb-timer.h
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Luc Michel <luc@lmichel.fr>
14
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Message-id: 20210128114145.20536-7-peter.maydell@linaro.org
16
Message-id: 20210121190622.22000-7-peter.maydell@linaro.org
17
---
18
include/hw/arm/armsse.h | 6 +++---
19
include/hw/timer/cmsdk-apb-timer.h | 4 ++--
20
hw/timer/cmsdk-apb-timer.c | 28 ++++++++++++++--------------
21
3 files changed, 19 insertions(+), 19 deletions(-)
22
23
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/arm/armsse.h
26
+++ b/include/hw/arm/armsse.h
27
@@ -XXX,XX +XXX,XX @@ struct ARMSSE {
28
TZPPC apb_ppc0;
29
TZPPC apb_ppc1;
30
TZMPC mpc[IOTS_NUM_MPC];
31
- CMSDKAPBTIMER timer0;
32
- CMSDKAPBTIMER timer1;
33
- CMSDKAPBTIMER s32ktimer;
34
+ CMSDKAPBTimer timer0;
35
+ CMSDKAPBTimer timer1;
36
+ CMSDKAPBTimer s32ktimer;
37
qemu_or_irq ppc_irq_orgate;
38
SplitIRQ sec_resp_splitter;
39
SplitIRQ ppc_irq_splitter[NUM_PPCS];
40
diff --git a/include/hw/timer/cmsdk-apb-timer.h b/include/hw/timer/cmsdk-apb-timer.h
41
index XXXXXXX..XXXXXXX 100644
42
--- a/include/hw/timer/cmsdk-apb-timer.h
43
+++ b/include/hw/timer/cmsdk-apb-timer.h
44
@@ -XXX,XX +XXX,XX @@
45
#include "qom/object.h"
46
47
#define TYPE_CMSDK_APB_TIMER "cmsdk-apb-timer"
48
-OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBTIMER, CMSDK_APB_TIMER)
49
+OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBTimer, CMSDK_APB_TIMER)
50
51
-struct CMSDKAPBTIMER {
52
+struct CMSDKAPBTimer {
53
/*< private >*/
54
SysBusDevice parent_obj;
55
56
diff --git a/hw/timer/cmsdk-apb-timer.c b/hw/timer/cmsdk-apb-timer.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/hw/timer/cmsdk-apb-timer.c
59
+++ b/hw/timer/cmsdk-apb-timer.c
60
@@ -XXX,XX +XXX,XX @@ static const int timer_id[] = {
61
0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
62
};
63
64
-static void cmsdk_apb_timer_update(CMSDKAPBTIMER *s)
65
+static void cmsdk_apb_timer_update(CMSDKAPBTimer *s)
66
{
67
qemu_set_irq(s->timerint, !!(s->intstatus & R_INTSTATUS_IRQ_MASK));
68
}
69
70
static uint64_t cmsdk_apb_timer_read(void *opaque, hwaddr offset, unsigned size)
71
{
72
- CMSDKAPBTIMER *s = CMSDK_APB_TIMER(opaque);
73
+ CMSDKAPBTimer *s = CMSDK_APB_TIMER(opaque);
74
uint64_t r;
75
76
switch (offset) {
77
@@ -XXX,XX +XXX,XX @@ static uint64_t cmsdk_apb_timer_read(void *opaque, hwaddr offset, unsigned size)
78
static void cmsdk_apb_timer_write(void *opaque, hwaddr offset, uint64_t value,
79
unsigned size)
80
{
81
- CMSDKAPBTIMER *s = CMSDK_APB_TIMER(opaque);
82
+ CMSDKAPBTimer *s = CMSDK_APB_TIMER(opaque);
83
84
trace_cmsdk_apb_timer_write(offset, value, size);
85
86
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps cmsdk_apb_timer_ops = {
87
88
static void cmsdk_apb_timer_tick(void *opaque)
89
{
90
- CMSDKAPBTIMER *s = CMSDK_APB_TIMER(opaque);
91
+ CMSDKAPBTimer *s = CMSDK_APB_TIMER(opaque);
92
93
if (s->ctrl & R_CTRL_IRQEN_MASK) {
94
s->intstatus |= R_INTSTATUS_IRQ_MASK;
95
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_tick(void *opaque)
96
97
static void cmsdk_apb_timer_reset(DeviceState *dev)
98
{
99
- CMSDKAPBTIMER *s = CMSDK_APB_TIMER(dev);
100
+ CMSDKAPBTimer *s = CMSDK_APB_TIMER(dev);
101
102
trace_cmsdk_apb_timer_reset();
103
s->ctrl = 0;
104
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_reset(DeviceState *dev)
105
static void cmsdk_apb_timer_init(Object *obj)
106
{
107
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
108
- CMSDKAPBTIMER *s = CMSDK_APB_TIMER(obj);
109
+ CMSDKAPBTimer *s = CMSDK_APB_TIMER(obj);
110
111
memory_region_init_io(&s->iomem, obj, &cmsdk_apb_timer_ops,
112
s, "cmsdk-apb-timer", 0x1000);
113
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_init(Object *obj)
114
115
static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
116
{
117
- CMSDKAPBTIMER *s = CMSDK_APB_TIMER(dev);
118
+ CMSDKAPBTimer *s = CMSDK_APB_TIMER(dev);
119
120
if (s->pclk_frq == 0) {
121
error_setg(errp, "CMSDK APB timer: pclk-frq property must be set");
122
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription cmsdk_apb_timer_vmstate = {
123
.version_id = 1,
124
.minimum_version_id = 1,
125
.fields = (VMStateField[]) {
126
- VMSTATE_PTIMER(timer, CMSDKAPBTIMER),
127
- VMSTATE_UINT32(ctrl, CMSDKAPBTIMER),
128
- VMSTATE_UINT32(value, CMSDKAPBTIMER),
129
- VMSTATE_UINT32(reload, CMSDKAPBTIMER),
130
- VMSTATE_UINT32(intstatus, CMSDKAPBTIMER),
131
+ VMSTATE_PTIMER(timer, CMSDKAPBTimer),
132
+ VMSTATE_UINT32(ctrl, CMSDKAPBTimer),
133
+ VMSTATE_UINT32(value, CMSDKAPBTimer),
134
+ VMSTATE_UINT32(reload, CMSDKAPBTimer),
135
+ VMSTATE_UINT32(intstatus, CMSDKAPBTimer),
136
VMSTATE_END_OF_LIST()
137
}
138
};
139
140
static Property cmsdk_apb_timer_properties[] = {
141
- DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBTIMER, pclk_frq, 0),
142
+ DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBTimer, pclk_frq, 0),
143
DEFINE_PROP_END_OF_LIST(),
144
};
145
146
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_class_init(ObjectClass *klass, void *data)
147
static const TypeInfo cmsdk_apb_timer_info = {
148
.name = TYPE_CMSDK_APB_TIMER,
149
.parent = TYPE_SYS_BUS_DEVICE,
150
- .instance_size = sizeof(CMSDKAPBTIMER),
151
+ .instance_size = sizeof(CMSDKAPBTimer),
152
.instance_init = cmsdk_apb_timer_init,
153
.class_init = cmsdk_apb_timer_class_init,
154
};
155
--
156
2.20.1
157
158
diff view generated by jsdifflib
Deleted patch
1
As the first step in converting the CMSDK_APB_TIMER device to the
2
Clock framework, add a Clock input. For the moment we do nothing
3
with this clock; we will change the behaviour from using the pclk-frq
4
property to using the Clock once all the users of this device have
5
been converted to wire up the Clock.
6
1
7
Since the device doesn't already have a doc comment for its "QEMU
8
interface", we add one including the new Clock.
9
10
This is a migration compatibility break for machines mps2-an505,
11
mps2-an521, musca-a, musca-b1.
12
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Reviewed-by: Luc Michel <luc@lmichel.fr>
16
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
17
Message-id: 20210128114145.20536-8-peter.maydell@linaro.org
18
Message-id: 20210121190622.22000-8-peter.maydell@linaro.org
19
---
20
include/hw/timer/cmsdk-apb-timer.h | 9 +++++++++
21
hw/timer/cmsdk-apb-timer.c | 7 +++++--
22
2 files changed, 14 insertions(+), 2 deletions(-)
23
24
diff --git a/include/hw/timer/cmsdk-apb-timer.h b/include/hw/timer/cmsdk-apb-timer.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/include/hw/timer/cmsdk-apb-timer.h
27
+++ b/include/hw/timer/cmsdk-apb-timer.h
28
@@ -XXX,XX +XXX,XX @@
29
#include "hw/qdev-properties.h"
30
#include "hw/sysbus.h"
31
#include "hw/ptimer.h"
32
+#include "hw/clock.h"
33
#include "qom/object.h"
34
35
#define TYPE_CMSDK_APB_TIMER "cmsdk-apb-timer"
36
OBJECT_DECLARE_SIMPLE_TYPE(CMSDKAPBTimer, CMSDK_APB_TIMER)
37
38
+/*
39
+ * QEMU interface:
40
+ * + QOM property "pclk-frq": frequency at which the timer is clocked
41
+ * + Clock input "pclk": clock for the timer
42
+ * + sysbus MMIO region 0: the register bank
43
+ * + sysbus IRQ 0: timer interrupt TIMERINT
44
+ */
45
struct CMSDKAPBTimer {
46
/*< private >*/
47
SysBusDevice parent_obj;
48
@@ -XXX,XX +XXX,XX @@ struct CMSDKAPBTimer {
49
qemu_irq timerint;
50
uint32_t pclk_frq;
51
struct ptimer_state *timer;
52
+ Clock *pclk;
53
54
uint32_t ctrl;
55
uint32_t value;
56
diff --git a/hw/timer/cmsdk-apb-timer.c b/hw/timer/cmsdk-apb-timer.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/hw/timer/cmsdk-apb-timer.c
59
+++ b/hw/timer/cmsdk-apb-timer.c
60
@@ -XXX,XX +XXX,XX @@
61
#include "hw/sysbus.h"
62
#include "hw/irq.h"
63
#include "hw/registerfields.h"
64
+#include "hw/qdev-clock.h"
65
#include "hw/timer/cmsdk-apb-timer.h"
66
#include "migration/vmstate.h"
67
68
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_init(Object *obj)
69
s, "cmsdk-apb-timer", 0x1000);
70
sysbus_init_mmio(sbd, &s->iomem);
71
sysbus_init_irq(sbd, &s->timerint);
72
+ s->pclk = qdev_init_clock_in(DEVICE(s), "pclk", NULL, NULL);
73
}
74
75
static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
76
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
77
78
static const VMStateDescription cmsdk_apb_timer_vmstate = {
79
.name = "cmsdk-apb-timer",
80
- .version_id = 1,
81
- .minimum_version_id = 1,
82
+ .version_id = 2,
83
+ .minimum_version_id = 2,
84
.fields = (VMStateField[]) {
85
VMSTATE_PTIMER(timer, CMSDKAPBTimer),
86
+ VMSTATE_CLOCK(pclk, CMSDKAPBTimer),
87
VMSTATE_UINT32(ctrl, CMSDKAPBTimer),
88
VMSTATE_UINT32(value, CMSDKAPBTimer),
89
VMSTATE_UINT32(reload, CMSDKAPBTimer),
90
--
91
2.20.1
92
93
diff view generated by jsdifflib
Deleted patch
1
As the first step in converting the CMSDK_APB_DUALTIMER device to the
2
Clock framework, add a Clock input. For the moment we do nothing
3
with this clock; we will change the behaviour from using the pclk-frq
4
property to using the Clock once all the users of this device have
5
been converted to wire up the Clock.
6
1
7
We take the opportunity to correct the name of the clock input to
8
match the hardware -- the dual timer names the clock which drives the
9
timers TIMCLK. (It does also have a 'pclk' input, which is used only
10
for the register and APB bus logic; on the SSE-200 these clocks are
11
both connected together.)
12
13
This is a migration compatibility break for machines mps2-an385,
14
mps2-an386, mps2-an500, mps2-an511, mps2-an505, mps2-an521, musca-a,
15
musca-b1.
16
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
Reviewed-by: Luc Michel <luc@lmichel.fr>
20
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
21
Message-id: 20210128114145.20536-9-peter.maydell@linaro.org
22
Message-id: 20210121190622.22000-9-peter.maydell@linaro.org
23
---
24
include/hw/timer/cmsdk-apb-dualtimer.h | 3 +++
25
hw/timer/cmsdk-apb-dualtimer.c | 7 +++++--
26
2 files changed, 8 insertions(+), 2 deletions(-)
27
28
diff --git a/include/hw/timer/cmsdk-apb-dualtimer.h b/include/hw/timer/cmsdk-apb-dualtimer.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/include/hw/timer/cmsdk-apb-dualtimer.h
31
+++ b/include/hw/timer/cmsdk-apb-dualtimer.h
32
@@ -XXX,XX +XXX,XX @@
33
*
34
* QEMU interface:
35
* + QOM property "pclk-frq": frequency at which the timer is clocked
36
+ * + Clock input "TIMCLK": clock (for both timers)
37
* + sysbus MMIO region 0: the register bank
38
* + sysbus IRQ 0: combined timer interrupt TIMINTC
39
* + sysbus IRO 1: timer block 1 interrupt TIMINT1
40
@@ -XXX,XX +XXX,XX @@
41
42
#include "hw/sysbus.h"
43
#include "hw/ptimer.h"
44
+#include "hw/clock.h"
45
#include "qom/object.h"
46
47
#define TYPE_CMSDK_APB_DUALTIMER "cmsdk-apb-dualtimer"
48
@@ -XXX,XX +XXX,XX @@ struct CMSDKAPBDualTimer {
49
MemoryRegion iomem;
50
qemu_irq timerintc;
51
uint32_t pclk_frq;
52
+ Clock *timclk;
53
54
CMSDKAPBDualTimerModule timermod[CMSDK_APB_DUALTIMER_NUM_MODULES];
55
uint32_t timeritcr;
56
diff --git a/hw/timer/cmsdk-apb-dualtimer.c b/hw/timer/cmsdk-apb-dualtimer.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/hw/timer/cmsdk-apb-dualtimer.c
59
+++ b/hw/timer/cmsdk-apb-dualtimer.c
60
@@ -XXX,XX +XXX,XX @@
61
#include "hw/irq.h"
62
#include "hw/qdev-properties.h"
63
#include "hw/registerfields.h"
64
+#include "hw/qdev-clock.h"
65
#include "hw/timer/cmsdk-apb-dualtimer.h"
66
#include "migration/vmstate.h"
67
68
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_dualtimer_init(Object *obj)
69
for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
70
sysbus_init_irq(sbd, &s->timermod[i].timerint);
71
}
72
+ s->timclk = qdev_init_clock_in(DEVICE(s), "TIMCLK", NULL, NULL);
73
}
74
75
static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
76
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription cmsdk_dualtimermod_vmstate = {
77
78
static const VMStateDescription cmsdk_apb_dualtimer_vmstate = {
79
.name = "cmsdk-apb-dualtimer",
80
- .version_id = 1,
81
- .minimum_version_id = 1,
82
+ .version_id = 2,
83
+ .minimum_version_id = 2,
84
.fields = (VMStateField[]) {
85
+ VMSTATE_CLOCK(timclk, CMSDKAPBDualTimer),
86
VMSTATE_STRUCT_ARRAY(timermod, CMSDKAPBDualTimer,
87
CMSDK_APB_DUALTIMER_NUM_MODULES,
88
1, cmsdk_dualtimermod_vmstate,
89
--
90
2.20.1
91
92
diff view generated by jsdifflib
Deleted patch
1
As the first step in converting the CMSDK_APB_TIMER device to the
2
Clock framework, add a Clock input. For the moment we do nothing
3
with this clock; we will change the behaviour from using the
4
wdogclk-frq property to using the Clock once all the users of this
5
device have been converted to wire up the Clock.
6
1
7
This is a migration compatibility break for machines mps2-an385,
8
mps2-an386, mps2-an500, mps2-an511, mps2-an505, mps2-an521, musca-a,
9
musca-b1, lm3s811evb, lm3s6965evb.
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Luc Michel <luc@lmichel.fr>
14
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Message-id: 20210128114145.20536-10-peter.maydell@linaro.org
16
Message-id: 20210121190622.22000-10-peter.maydell@linaro.org
17
---
18
include/hw/watchdog/cmsdk-apb-watchdog.h | 3 +++
19
hw/watchdog/cmsdk-apb-watchdog.c | 7 +++++--
20
2 files changed, 8 insertions(+), 2 deletions(-)
21
22
diff --git a/include/hw/watchdog/cmsdk-apb-watchdog.h b/include/hw/watchdog/cmsdk-apb-watchdog.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/include/hw/watchdog/cmsdk-apb-watchdog.h
25
+++ b/include/hw/watchdog/cmsdk-apb-watchdog.h
26
@@ -XXX,XX +XXX,XX @@
27
*
28
* QEMU interface:
29
* + QOM property "wdogclk-frq": frequency at which the watchdog is clocked
30
+ * + Clock input "WDOGCLK": clock for the watchdog's timer
31
* + sysbus MMIO region 0: the register bank
32
* + sysbus IRQ 0: watchdog interrupt
33
*
34
@@ -XXX,XX +XXX,XX @@
35
36
#include "hw/sysbus.h"
37
#include "hw/ptimer.h"
38
+#include "hw/clock.h"
39
#include "qom/object.h"
40
41
#define TYPE_CMSDK_APB_WATCHDOG "cmsdk-apb-watchdog"
42
@@ -XXX,XX +XXX,XX @@ struct CMSDKAPBWatchdog {
43
uint32_t wdogclk_frq;
44
bool is_luminary;
45
struct ptimer_state *timer;
46
+ Clock *wdogclk;
47
48
uint32_t control;
49
uint32_t intstatus;
50
diff --git a/hw/watchdog/cmsdk-apb-watchdog.c b/hw/watchdog/cmsdk-apb-watchdog.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/hw/watchdog/cmsdk-apb-watchdog.c
53
+++ b/hw/watchdog/cmsdk-apb-watchdog.c
54
@@ -XXX,XX +XXX,XX @@
55
#include "hw/irq.h"
56
#include "hw/qdev-properties.h"
57
#include "hw/registerfields.h"
58
+#include "hw/qdev-clock.h"
59
#include "hw/watchdog/cmsdk-apb-watchdog.h"
60
#include "migration/vmstate.h"
61
62
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_init(Object *obj)
63
s, "cmsdk-apb-watchdog", 0x1000);
64
sysbus_init_mmio(sbd, &s->iomem);
65
sysbus_init_irq(sbd, &s->wdogint);
66
+ s->wdogclk = qdev_init_clock_in(DEVICE(s), "WDOGCLK", NULL, NULL);
67
68
s->is_luminary = false;
69
s->id = cmsdk_apb_watchdog_id;
70
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_realize(DeviceState *dev, Error **errp)
71
72
static const VMStateDescription cmsdk_apb_watchdog_vmstate = {
73
.name = "cmsdk-apb-watchdog",
74
- .version_id = 1,
75
- .minimum_version_id = 1,
76
+ .version_id = 2,
77
+ .minimum_version_id = 2,
78
.fields = (VMStateField[]) {
79
+ VMSTATE_CLOCK(wdogclk, CMSDKAPBWatchdog),
80
VMSTATE_PTIMER(timer, CMSDKAPBWatchdog),
81
VMSTATE_UINT32(control, CMSDKAPBWatchdog),
82
VMSTATE_UINT32(intstatus, CMSDKAPBWatchdog),
83
--
84
2.20.1
85
86
diff view generated by jsdifflib
Deleted patch
1
While we transition the ARMSSE code from integer properties
2
specifying clock frequencies to Clock objects, we want to have the
3
device provide both at once. We want the final name of the main
4
input Clock to be "MAINCLK", following the hardware name.
5
Unfortunately creating an input Clock with a name X creates an
6
under-the-hood QOM property X; for "MAINCLK" this clashes with the
7
existing UINT32 property of that name.
8
1
9
Rename the UINT32 property to MAINCLK_FRQ so it can coexist with the
10
MAINCLK Clock; once the transition is complete MAINCLK_FRQ will be
11
deleted.
12
13
Commit created with:
14
perl -p -i -e 's/MAINCLK/MAINCLK_FRQ/g' hw/arm/{armsse,mps2-tz,musca}.c include/hw/arm/armsse.h
15
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Reviewed-by: Luc Michel <luc@lmichel.fr>
19
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Message-id: 20210128114145.20536-11-peter.maydell@linaro.org
21
Message-id: 20210121190622.22000-11-peter.maydell@linaro.org
22
---
23
include/hw/arm/armsse.h | 2 +-
24
hw/arm/armsse.c | 6 +++---
25
hw/arm/mps2-tz.c | 2 +-
26
hw/arm/musca.c | 2 +-
27
4 files changed, 6 insertions(+), 6 deletions(-)
28
29
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
30
index XXXXXXX..XXXXXXX 100644
31
--- a/include/hw/arm/armsse.h
32
+++ b/include/hw/arm/armsse.h
33
@@ -XXX,XX +XXX,XX @@
34
* QEMU interface:
35
* + QOM property "memory" is a MemoryRegion containing the devices provided
36
* by the board model.
37
- * + QOM property "MAINCLK" is the frequency of the main system clock
38
+ * + QOM property "MAINCLK_FRQ" is the frequency of the main system clock
39
* + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts.
40
* (In hardware, the SSE-200 permits the number of expansion interrupts
41
* for the two CPUs to be configured separately, but we restrict it to
42
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/hw/arm/armsse.c
45
+++ b/hw/arm/armsse.c
46
@@ -XXX,XX +XXX,XX @@ static Property iotkit_properties[] = {
47
DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
48
MemoryRegion *),
49
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
50
- DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
51
+ DEFINE_PROP_UINT32("MAINCLK_FRQ", ARMSSE, mainclk_frq, 0),
52
DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
53
DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
54
DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], true),
55
@@ -XXX,XX +XXX,XX @@ static Property armsse_properties[] = {
56
DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
57
MemoryRegion *),
58
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
59
- DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
60
+ DEFINE_PROP_UINT32("MAINCLK_FRQ", ARMSSE, mainclk_frq, 0),
61
DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
62
DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
63
DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], false),
64
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
65
}
66
67
if (!s->mainclk_frq) {
68
- error_setg(errp, "MAINCLK property was not set");
69
+ error_setg(errp, "MAINCLK_FRQ property was not set");
70
return;
71
}
72
73
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/arm/mps2-tz.c
76
+++ b/hw/arm/mps2-tz.c
77
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
78
object_property_set_link(OBJECT(&mms->iotkit), "memory",
79
OBJECT(system_memory), &error_abort);
80
qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", MPS2TZ_NUMIRQ);
81
- qdev_prop_set_uint32(iotkitdev, "MAINCLK", SYSCLK_FRQ);
82
+ qdev_prop_set_uint32(iotkitdev, "MAINCLK_FRQ", SYSCLK_FRQ);
83
sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
84
85
/*
86
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/hw/arm/musca.c
89
+++ b/hw/arm/musca.c
90
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
91
qdev_prop_set_uint32(ssedev, "EXP_NUMIRQ", mmc->num_irqs);
92
qdev_prop_set_uint32(ssedev, "init-svtor", mmc->init_svtor);
93
qdev_prop_set_uint32(ssedev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width);
94
- qdev_prop_set_uint32(ssedev, "MAINCLK", SYSCLK_FRQ);
95
+ qdev_prop_set_uint32(ssedev, "MAINCLK_FRQ", SYSCLK_FRQ);
96
/*
97
* Musca-A takes the default SSE-200 FPU/DSP settings (ie no for
98
* CPU0 and yes for CPU1); Musca-B1 explicitly enables them for CPU0.
99
--
100
2.20.1
101
102
diff view generated by jsdifflib
Deleted patch
1
Create a fixed-frequency Clock object to be the SYSCLK, and wire it
2
up to the devices that require it.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Luc Michel <luc@lmichel.fr>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20210128114145.20536-14-peter.maydell@linaro.org
9
Message-id: 20210121190622.22000-14-peter.maydell@linaro.org
10
---
11
hw/arm/mps2.c | 9 +++++++++
12
1 file changed, 9 insertions(+)
13
14
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/mps2.c
17
+++ b/hw/arm/mps2.c
18
@@ -XXX,XX +XXX,XX @@
19
#include "hw/net/lan9118.h"
20
#include "net/net.h"
21
#include "hw/watchdog/cmsdk-apb-watchdog.h"
22
+#include "hw/qdev-clock.h"
23
#include "qom/object.h"
24
25
typedef enum MPS2FPGAType {
26
@@ -XXX,XX +XXX,XX @@ struct MPS2MachineState {
27
CMSDKAPBDualTimer dualtimer;
28
CMSDKAPBWatchdog watchdog;
29
CMSDKAPBTimer timer[2];
30
+ Clock *sysclk;
31
};
32
33
#define TYPE_MPS2_MACHINE "mps2"
34
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
35
exit(EXIT_FAILURE);
36
}
37
38
+ /* This clock doesn't need migration because it is fixed-frequency */
39
+ mms->sysclk = clock_new(OBJECT(machine), "SYSCLK");
40
+ clock_set_hz(mms->sysclk, SYSCLK_FRQ);
41
+
42
/* The FPGA images have an odd combination of different RAMs,
43
* because in hardware they are different implementations and
44
* connected to different buses, giving varying performance/size
45
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
46
TYPE_CMSDK_APB_TIMER);
47
sbd = SYS_BUS_DEVICE(&mms->timer[i]);
48
qdev_prop_set_uint32(DEVICE(&mms->timer[i]), "pclk-frq", SYSCLK_FRQ);
49
+ qdev_connect_clock_in(DEVICE(&mms->timer[i]), "pclk", mms->sysclk);
50
sysbus_realize_and_unref(sbd, &error_fatal);
51
sysbus_mmio_map(sbd, 0, base);
52
sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(armv7m, irqno));
53
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
54
object_initialize_child(OBJECT(mms), "dualtimer", &mms->dualtimer,
55
TYPE_CMSDK_APB_DUALTIMER);
56
qdev_prop_set_uint32(DEVICE(&mms->dualtimer), "pclk-frq", SYSCLK_FRQ);
57
+ qdev_connect_clock_in(DEVICE(&mms->dualtimer), "TIMCLK", mms->sysclk);
58
sysbus_realize(SYS_BUS_DEVICE(&mms->dualtimer), &error_fatal);
59
sysbus_connect_irq(SYS_BUS_DEVICE(&mms->dualtimer), 0,
60
qdev_get_gpio_in(armv7m, 10));
61
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
62
object_initialize_child(OBJECT(mms), "watchdog", &mms->watchdog,
63
TYPE_CMSDK_APB_WATCHDOG);
64
qdev_prop_set_uint32(DEVICE(&mms->watchdog), "wdogclk-frq", SYSCLK_FRQ);
65
+ qdev_connect_clock_in(DEVICE(&mms->watchdog), "WDOGCLK", mms->sysclk);
66
sysbus_realize(SYS_BUS_DEVICE(&mms->watchdog), &error_fatal);
67
sysbus_connect_irq(SYS_BUS_DEVICE(&mms->watchdog), 0,
68
qdev_get_gpio_in_named(armv7m, "NMI", 0));
69
--
70
2.20.1
71
72
diff view generated by jsdifflib
Deleted patch
1
Create and connect the two clocks needed by the ARMSSE.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Luc Michel <luc@lmichel.fr>
6
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20210128114145.20536-15-peter.maydell@linaro.org
8
Message-id: 20210121190622.22000-15-peter.maydell@linaro.org
9
---
10
hw/arm/mps2-tz.c | 13 +++++++++++++
11
1 file changed, 13 insertions(+)
12
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/mps2-tz.c
16
+++ b/hw/arm/mps2-tz.c
17
@@ -XXX,XX +XXX,XX @@
18
#include "hw/net/lan9118.h"
19
#include "net/net.h"
20
#include "hw/core/split-irq.h"
21
+#include "hw/qdev-clock.h"
22
#include "qom/object.h"
23
24
#define MPS2TZ_NUMIRQ 92
25
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
26
qemu_or_irq uart_irq_orgate;
27
DeviceState *lan9118;
28
SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ];
29
+ Clock *sysclk;
30
+ Clock *s32kclk;
31
};
32
33
#define TYPE_MPS2TZ_MACHINE "mps2tz"
34
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
35
36
/* Main SYSCLK frequency in Hz */
37
#define SYSCLK_FRQ 20000000
38
+/* Slow 32Khz S32KCLK frequency in Hz */
39
+#define S32KCLK_FRQ (32 * 1000)
40
41
/* Create an alias of an entire original MemoryRegion @orig
42
* located at @base in the memory map.
43
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
44
exit(EXIT_FAILURE);
45
}
46
47
+ /* These clocks don't need migration because they are fixed-frequency */
48
+ mms->sysclk = clock_new(OBJECT(machine), "SYSCLK");
49
+ clock_set_hz(mms->sysclk, SYSCLK_FRQ);
50
+ mms->s32kclk = clock_new(OBJECT(machine), "S32KCLK");
51
+ clock_set_hz(mms->s32kclk, S32KCLK_FRQ);
52
+
53
object_initialize_child(OBJECT(machine), TYPE_IOTKIT, &mms->iotkit,
54
mmc->armsse_type);
55
iotkitdev = DEVICE(&mms->iotkit);
56
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
57
OBJECT(system_memory), &error_abort);
58
qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", MPS2TZ_NUMIRQ);
59
qdev_prop_set_uint32(iotkitdev, "MAINCLK_FRQ", SYSCLK_FRQ);
60
+ qdev_connect_clock_in(iotkitdev, "MAINCLK", mms->sysclk);
61
+ qdev_connect_clock_in(iotkitdev, "S32KCLK", mms->s32kclk);
62
sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
63
64
/*
65
--
66
2.20.1
67
68
diff view generated by jsdifflib
Deleted patch
1
Create and connect the two clocks needed by the ARMSSE.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Luc Michel <luc@lmichel.fr>
6
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20210128114145.20536-16-peter.maydell@linaro.org
8
Message-id: 20210121190622.22000-16-peter.maydell@linaro.org
9
---
10
hw/arm/musca.c | 12 ++++++++++++
11
1 file changed, 12 insertions(+)
12
13
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/musca.c
16
+++ b/hw/arm/musca.c
17
@@ -XXX,XX +XXX,XX @@
18
#include "hw/misc/tz-ppc.h"
19
#include "hw/misc/unimp.h"
20
#include "hw/rtc/pl031.h"
21
+#include "hw/qdev-clock.h"
22
#include "qom/object.h"
23
24
#define MUSCA_NUMIRQ_MAX 96
25
@@ -XXX,XX +XXX,XX @@ struct MuscaMachineState {
26
UnimplementedDeviceState sdio;
27
UnimplementedDeviceState gpio;
28
UnimplementedDeviceState cryptoisland;
29
+ Clock *sysclk;
30
+ Clock *s32kclk;
31
};
32
33
#define TYPE_MUSCA_MACHINE "musca"
34
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(MuscaMachineState, MuscaMachineClass, MUSCA_MACHINE)
35
* don't model that in our SSE-200 model yet.
36
*/
37
#define SYSCLK_FRQ 40000000
38
+/* Slow 32Khz S32KCLK frequency in Hz */
39
+#define S32KCLK_FRQ (32 * 1000)
40
41
static qemu_irq get_sse_irq_in(MuscaMachineState *mms, int irqno)
42
{
43
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
44
exit(1);
45
}
46
47
+ mms->sysclk = clock_new(OBJECT(machine), "SYSCLK");
48
+ clock_set_hz(mms->sysclk, SYSCLK_FRQ);
49
+ mms->s32kclk = clock_new(OBJECT(machine), "S32KCLK");
50
+ clock_set_hz(mms->s32kclk, S32KCLK_FRQ);
51
+
52
object_initialize_child(OBJECT(machine), "sse-200", &mms->sse,
53
TYPE_SSE200);
54
ssedev = DEVICE(&mms->sse);
55
@@ -XXX,XX +XXX,XX @@ static void musca_init(MachineState *machine)
56
qdev_prop_set_uint32(ssedev, "init-svtor", mmc->init_svtor);
57
qdev_prop_set_uint32(ssedev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width);
58
qdev_prop_set_uint32(ssedev, "MAINCLK_FRQ", SYSCLK_FRQ);
59
+ qdev_connect_clock_in(ssedev, "MAINCLK", mms->sysclk);
60
+ qdev_connect_clock_in(ssedev, "S32KCLK", mms->s32kclk);
61
/*
62
* Musca-A takes the default SSE-200 FPU/DSP settings (ie no for
63
* CPU0 and yes for CPU1); Musca-B1 explicitly enables them for CPU0.
64
--
65
2.20.1
66
67
diff view generated by jsdifflib
Deleted patch
1
Convert the SSYS code in the Stellaris boards (which encapsulates the
2
system registers) to a proper QOM device. This will provide us with
3
somewhere to put the output Clock whose frequency depends on the
4
setting of the PLL configuration registers.
5
1
6
This is a migration compatibility break for lm3s811evb, lm3s6965evb.
7
8
We use 3-phase reset here because the Clock will need to propagate
9
its value in the hold phase.
10
11
For the moment we reset the device during the board creation so that
12
the system_clock_scale global gets set; this will be removed in a
13
subsequent commit.
14
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Luc Michel <luc@lmichel.fr>
17
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
Message-id: 20210128114145.20536-17-peter.maydell@linaro.org
20
Message-id: 20210121190622.22000-17-peter.maydell@linaro.org
21
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
22
---
23
hw/arm/stellaris.c | 132 ++++++++++++++++++++++++++++++++++++---------
24
1 file changed, 107 insertions(+), 25 deletions(-)
25
26
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/arm/stellaris.c
29
+++ b/hw/arm/stellaris.c
30
@@ -XXX,XX +XXX,XX @@ static void stellaris_gptm_realize(DeviceState *dev, Error **errp)
31
32
/* System controller. */
33
34
-typedef struct {
35
+#define TYPE_STELLARIS_SYS "stellaris-sys"
36
+OBJECT_DECLARE_SIMPLE_TYPE(ssys_state, STELLARIS_SYS)
37
+
38
+struct ssys_state {
39
+ SysBusDevice parent_obj;
40
+
41
MemoryRegion iomem;
42
uint32_t pborctl;
43
uint32_t ldopctl;
44
@@ -XXX,XX +XXX,XX @@ typedef struct {
45
uint32_t dcgc[3];
46
uint32_t clkvclr;
47
uint32_t ldoarst;
48
+ qemu_irq irq;
49
+ /* Properties (all read-only registers) */
50
uint32_t user0;
51
uint32_t user1;
52
- qemu_irq irq;
53
- stellaris_board_info *board;
54
-} ssys_state;
55
+ uint32_t did0;
56
+ uint32_t did1;
57
+ uint32_t dc0;
58
+ uint32_t dc1;
59
+ uint32_t dc2;
60
+ uint32_t dc3;
61
+ uint32_t dc4;
62
+};
63
64
static void ssys_update(ssys_state *s)
65
{
66
@@ -XXX,XX +XXX,XX @@ static uint32_t pllcfg_fury[16] = {
67
68
static int ssys_board_class(const ssys_state *s)
69
{
70
- uint32_t did0 = s->board->did0;
71
+ uint32_t did0 = s->did0;
72
switch (did0 & DID0_VER_MASK) {
73
case DID0_VER_0:
74
return DID0_CLASS_SANDSTORM;
75
@@ -XXX,XX +XXX,XX @@ static uint64_t ssys_read(void *opaque, hwaddr offset,
76
77
switch (offset) {
78
case 0x000: /* DID0 */
79
- return s->board->did0;
80
+ return s->did0;
81
case 0x004: /* DID1 */
82
- return s->board->did1;
83
+ return s->did1;
84
case 0x008: /* DC0 */
85
- return s->board->dc0;
86
+ return s->dc0;
87
case 0x010: /* DC1 */
88
- return s->board->dc1;
89
+ return s->dc1;
90
case 0x014: /* DC2 */
91
- return s->board->dc2;
92
+ return s->dc2;
93
case 0x018: /* DC3 */
94
- return s->board->dc3;
95
+ return s->dc3;
96
case 0x01c: /* DC4 */
97
- return s->board->dc4;
98
+ return s->dc4;
99
case 0x030: /* PBORCTL */
100
return s->pborctl;
101
case 0x034: /* LDOPCTL */
102
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps ssys_ops = {
103
.endianness = DEVICE_NATIVE_ENDIAN,
104
};
105
106
-static void ssys_reset(void *opaque)
107
+static void stellaris_sys_reset_enter(Object *obj, ResetType type)
108
{
109
- ssys_state *s = (ssys_state *)opaque;
110
+ ssys_state *s = STELLARIS_SYS(obj);
111
112
s->pborctl = 0x7ffd;
113
s->rcc = 0x078e3ac0;
114
@@ -XXX,XX +XXX,XX @@ static void ssys_reset(void *opaque)
115
s->rcgc[0] = 1;
116
s->scgc[0] = 1;
117
s->dcgc[0] = 1;
118
+}
119
+
120
+static void stellaris_sys_reset_hold(Object *obj)
121
+{
122
+ ssys_state *s = STELLARIS_SYS(obj);
123
+
124
ssys_calculate_system_clock(s);
125
}
126
127
+static void stellaris_sys_reset_exit(Object *obj)
128
+{
129
+}
130
+
131
static int stellaris_sys_post_load(void *opaque, int version_id)
132
{
133
ssys_state *s = opaque;
134
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_stellaris_sys = {
135
}
136
};
137
138
+static Property stellaris_sys_properties[] = {
139
+ DEFINE_PROP_UINT32("user0", ssys_state, user0, 0),
140
+ DEFINE_PROP_UINT32("user1", ssys_state, user1, 0),
141
+ DEFINE_PROP_UINT32("did0", ssys_state, did0, 0),
142
+ DEFINE_PROP_UINT32("did1", ssys_state, did1, 0),
143
+ DEFINE_PROP_UINT32("dc0", ssys_state, dc0, 0),
144
+ DEFINE_PROP_UINT32("dc1", ssys_state, dc1, 0),
145
+ DEFINE_PROP_UINT32("dc2", ssys_state, dc2, 0),
146
+ DEFINE_PROP_UINT32("dc3", ssys_state, dc3, 0),
147
+ DEFINE_PROP_UINT32("dc4", ssys_state, dc4, 0),
148
+ DEFINE_PROP_END_OF_LIST()
149
+};
150
+
151
+static void stellaris_sys_instance_init(Object *obj)
152
+{
153
+ ssys_state *s = STELLARIS_SYS(obj);
154
+ SysBusDevice *sbd = SYS_BUS_DEVICE(s);
155
+
156
+ memory_region_init_io(&s->iomem, obj, &ssys_ops, s, "ssys", 0x00001000);
157
+ sysbus_init_mmio(sbd, &s->iomem);
158
+ sysbus_init_irq(sbd, &s->irq);
159
+}
160
+
161
static int stellaris_sys_init(uint32_t base, qemu_irq irq,
162
stellaris_board_info * board,
163
uint8_t *macaddr)
164
{
165
- ssys_state *s;
166
+ DeviceState *dev = qdev_new(TYPE_STELLARIS_SYS);
167
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
168
169
- s = g_new0(ssys_state, 1);
170
- s->irq = irq;
171
- s->board = board;
172
/* Most devices come preprogrammed with a MAC address in the user data. */
173
- s->user0 = macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16);
174
- s->user1 = macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16);
175
+ qdev_prop_set_uint32(dev, "user0",
176
+ macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16));
177
+ qdev_prop_set_uint32(dev, "user1",
178
+ macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16));
179
+ qdev_prop_set_uint32(dev, "did0", board->did0);
180
+ qdev_prop_set_uint32(dev, "did1", board->did1);
181
+ qdev_prop_set_uint32(dev, "dc0", board->dc0);
182
+ qdev_prop_set_uint32(dev, "dc1", board->dc1);
183
+ qdev_prop_set_uint32(dev, "dc2", board->dc2);
184
+ qdev_prop_set_uint32(dev, "dc3", board->dc3);
185
+ qdev_prop_set_uint32(dev, "dc4", board->dc4);
186
+
187
+ sysbus_realize_and_unref(sbd, &error_fatal);
188
+ sysbus_mmio_map(sbd, 0, base);
189
+ sysbus_connect_irq(sbd, 0, irq);
190
+
191
+ /*
192
+ * Normally we should not be resetting devices like this during
193
+ * board creation. For the moment we need to do so, because
194
+ * system_clock_scale will only get set when the STELLARIS_SYS
195
+ * device is reset, and we need its initial value to pass to
196
+ * the watchdog device. This hack can be removed once the
197
+ * watchdog has been converted to use a Clock input instead.
198
+ */
199
+ device_cold_reset(dev);
200
201
- memory_region_init_io(&s->iomem, NULL, &ssys_ops, s, "ssys", 0x00001000);
202
- memory_region_add_subregion(get_system_memory(), base, &s->iomem);
203
- ssys_reset(s);
204
- vmstate_register(NULL, VMSTATE_INSTANCE_ID_ANY, &vmstate_stellaris_sys, s);
205
return 0;
206
}
207
208
-
209
/* I2C controller. */
210
211
#define TYPE_STELLARIS_I2C "stellaris-i2c"
212
@@ -XXX,XX +XXX,XX @@ static const TypeInfo stellaris_adc_info = {
213
.class_init = stellaris_adc_class_init,
214
};
215
216
+static void stellaris_sys_class_init(ObjectClass *klass, void *data)
217
+{
218
+ DeviceClass *dc = DEVICE_CLASS(klass);
219
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
220
+
221
+ dc->vmsd = &vmstate_stellaris_sys;
222
+ rc->phases.enter = stellaris_sys_reset_enter;
223
+ rc->phases.hold = stellaris_sys_reset_hold;
224
+ rc->phases.exit = stellaris_sys_reset_exit;
225
+ device_class_set_props(dc, stellaris_sys_properties);
226
+}
227
+
228
+static const TypeInfo stellaris_sys_info = {
229
+ .name = TYPE_STELLARIS_SYS,
230
+ .parent = TYPE_SYS_BUS_DEVICE,
231
+ .instance_size = sizeof(ssys_state),
232
+ .instance_init = stellaris_sys_instance_init,
233
+ .class_init = stellaris_sys_class_init,
234
+};
235
+
236
static void stellaris_register_types(void)
237
{
238
type_register_static(&stellaris_i2c_info);
239
type_register_static(&stellaris_gptm_info);
240
type_register_static(&stellaris_adc_info);
241
+ type_register_static(&stellaris_sys_info);
242
}
243
244
type_init(stellaris_register_types)
245
--
246
2.20.1
247
248
diff view generated by jsdifflib
Deleted patch
1
Create and connect the Clock input for the watchdog device on the
2
Stellaris boards. Because the Stellaris boards model the ability to
3
change the clock rate by programming PLL registers, we have to create
4
an output Clock on the ssys_state device and wire it up to the
5
watchdog.
6
1
7
Note that the old comment on ssys_calculate_system_clock() got the
8
units wrong -- system_clock_scale is in nanoseconds, not
9
milliseconds. Improve the commentary to clarify how we are
10
calculating the period.
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Luc Michel <luc@lmichel.fr>
14
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Message-id: 20210128114145.20536-18-peter.maydell@linaro.org
17
Message-id: 20210121190622.22000-18-peter.maydell@linaro.org
18
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
19
---
20
hw/arm/stellaris.c | 43 +++++++++++++++++++++++++++++++------------
21
1 file changed, 31 insertions(+), 12 deletions(-)
22
23
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/arm/stellaris.c
26
+++ b/hw/arm/stellaris.c
27
@@ -XXX,XX +XXX,XX @@
28
#include "hw/watchdog/cmsdk-apb-watchdog.h"
29
#include "migration/vmstate.h"
30
#include "hw/misc/unimp.h"
31
+#include "hw/qdev-clock.h"
32
#include "cpu.h"
33
#include "qom/object.h"
34
35
@@ -XXX,XX +XXX,XX @@ struct ssys_state {
36
uint32_t clkvclr;
37
uint32_t ldoarst;
38
qemu_irq irq;
39
+ Clock *sysclk;
40
/* Properties (all read-only registers) */
41
uint32_t user0;
42
uint32_t user1;
43
@@ -XXX,XX +XXX,XX @@ static bool ssys_use_rcc2(ssys_state *s)
44
}
45
46
/*
47
- * Caculate the sys. clock period in ms.
48
+ * Calculate the system clock period. We only want to propagate
49
+ * this change to the rest of the system if we're not being called
50
+ * from migration post-load.
51
*/
52
-static void ssys_calculate_system_clock(ssys_state *s)
53
+static void ssys_calculate_system_clock(ssys_state *s, bool propagate_clock)
54
{
55
+ /*
56
+ * SYSDIV field specifies divisor: 0 == /1, 1 == /2, etc. Input
57
+ * clock is 200MHz, which is a period of 5 ns. Dividing the clock
58
+ * frequency by X is the same as multiplying the period by X.
59
+ */
60
if (ssys_use_rcc2(s)) {
61
system_clock_scale = 5 * (((s->rcc2 >> 23) & 0x3f) + 1);
62
} else {
63
system_clock_scale = 5 * (((s->rcc >> 23) & 0xf) + 1);
64
}
65
+ clock_set_ns(s->sysclk, system_clock_scale);
66
+ if (propagate_clock) {
67
+ clock_propagate(s->sysclk);
68
+ }
69
}
70
71
static void ssys_write(void *opaque, hwaddr offset,
72
@@ -XXX,XX +XXX,XX @@ static void ssys_write(void *opaque, hwaddr offset,
73
s->int_status |= (1 << 6);
74
}
75
s->rcc = value;
76
- ssys_calculate_system_clock(s);
77
+ ssys_calculate_system_clock(s, true);
78
break;
79
case 0x070: /* RCC2 */
80
if (ssys_board_class(s) == DID0_CLASS_SANDSTORM) {
81
@@ -XXX,XX +XXX,XX @@ static void ssys_write(void *opaque, hwaddr offset,
82
s->int_status |= (1 << 6);
83
}
84
s->rcc2 = value;
85
- ssys_calculate_system_clock(s);
86
+ ssys_calculate_system_clock(s, true);
87
break;
88
case 0x100: /* RCGC0 */
89
s->rcgc[0] = value;
90
@@ -XXX,XX +XXX,XX @@ static void stellaris_sys_reset_hold(Object *obj)
91
{
92
ssys_state *s = STELLARIS_SYS(obj);
93
94
- ssys_calculate_system_clock(s);
95
+ /* OK to propagate clocks from the hold phase */
96
+ ssys_calculate_system_clock(s, true);
97
}
98
99
static void stellaris_sys_reset_exit(Object *obj)
100
@@ -XXX,XX +XXX,XX @@ static int stellaris_sys_post_load(void *opaque, int version_id)
101
{
102
ssys_state *s = opaque;
103
104
- ssys_calculate_system_clock(s);
105
+ ssys_calculate_system_clock(s, false);
106
107
return 0;
108
}
109
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_stellaris_sys = {
110
VMSTATE_UINT32_ARRAY(dcgc, ssys_state, 3),
111
VMSTATE_UINT32(clkvclr, ssys_state),
112
VMSTATE_UINT32(ldoarst, ssys_state),
113
+ /* No field for sysclk -- handled in post-load instead */
114
VMSTATE_END_OF_LIST()
115
}
116
};
117
@@ -XXX,XX +XXX,XX @@ static void stellaris_sys_instance_init(Object *obj)
118
memory_region_init_io(&s->iomem, obj, &ssys_ops, s, "ssys", 0x00001000);
119
sysbus_init_mmio(sbd, &s->iomem);
120
sysbus_init_irq(sbd, &s->irq);
121
+ s->sysclk = qdev_init_clock_out(DEVICE(s), "SYSCLK");
122
}
123
124
-static int stellaris_sys_init(uint32_t base, qemu_irq irq,
125
- stellaris_board_info * board,
126
- uint8_t *macaddr)
127
+static DeviceState *stellaris_sys_init(uint32_t base, qemu_irq irq,
128
+ stellaris_board_info *board,
129
+ uint8_t *macaddr)
130
{
131
DeviceState *dev = qdev_new(TYPE_STELLARIS_SYS);
132
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
133
@@ -XXX,XX +XXX,XX @@ static int stellaris_sys_init(uint32_t base, qemu_irq irq,
134
*/
135
device_cold_reset(dev);
136
137
- return 0;
138
+ return dev;
139
}
140
141
/* I2C controller. */
142
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
143
int flash_size;
144
I2CBus *i2c;
145
DeviceState *dev;
146
+ DeviceState *ssys_dev;
147
int i;
148
int j;
149
150
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
151
}
152
}
153
154
- stellaris_sys_init(0x400fe000, qdev_get_gpio_in(nvic, 28),
155
- board, nd_table[0].macaddr.a);
156
+ ssys_dev = stellaris_sys_init(0x400fe000, qdev_get_gpio_in(nvic, 28),
157
+ board, nd_table[0].macaddr.a);
158
159
160
if (board->dc1 & (1 << 3)) { /* watchdog present */
161
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
162
/* system_clock_scale is valid now */
163
uint32_t mainclk = NANOSECONDS_PER_SECOND / system_clock_scale;
164
qdev_prop_set_uint32(dev, "wdogclk-frq", mainclk);
165
+ qdev_connect_clock_in(dev, "WDOGCLK",
166
+ qdev_get_clock_out(ssys_dev, "SYSCLK"));
167
168
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
169
sysbus_mmio_map(SYS_BUS_DEVICE(dev),
170
--
171
2.20.1
172
173
diff view generated by jsdifflib
Deleted patch
1
Switch the CMSDK APB timer device over to using its Clock input; the
2
pclk-frq property is now ignored.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Luc Michel <luc@lmichel.fr>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20210128114145.20536-19-peter.maydell@linaro.org
9
Message-id: 20210121190622.22000-19-peter.maydell@linaro.org
10
---
11
hw/timer/cmsdk-apb-timer.c | 18 ++++++++++++++----
12
1 file changed, 14 insertions(+), 4 deletions(-)
13
14
diff --git a/hw/timer/cmsdk-apb-timer.c b/hw/timer/cmsdk-apb-timer.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/timer/cmsdk-apb-timer.c
17
+++ b/hw/timer/cmsdk-apb-timer.c
18
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_reset(DeviceState *dev)
19
ptimer_transaction_commit(s->timer);
20
}
21
22
+static void cmsdk_apb_timer_clk_update(void *opaque)
23
+{
24
+ CMSDKAPBTimer *s = CMSDK_APB_TIMER(opaque);
25
+
26
+ ptimer_transaction_begin(s->timer);
27
+ ptimer_set_period_from_clock(s->timer, s->pclk, 1);
28
+ ptimer_transaction_commit(s->timer);
29
+}
30
+
31
static void cmsdk_apb_timer_init(Object *obj)
32
{
33
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
34
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_init(Object *obj)
35
s, "cmsdk-apb-timer", 0x1000);
36
sysbus_init_mmio(sbd, &s->iomem);
37
sysbus_init_irq(sbd, &s->timerint);
38
- s->pclk = qdev_init_clock_in(DEVICE(s), "pclk", NULL, NULL);
39
+ s->pclk = qdev_init_clock_in(DEVICE(s), "pclk",
40
+ cmsdk_apb_timer_clk_update, s);
41
}
42
43
static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
44
{
45
CMSDKAPBTimer *s = CMSDK_APB_TIMER(dev);
46
47
- if (s->pclk_frq == 0) {
48
- error_setg(errp, "CMSDK APB timer: pclk-frq property must be set");
49
+ if (!clock_has_source(s->pclk)) {
50
+ error_setg(errp, "CMSDK APB timer: pclk clock must be connected");
51
return;
52
}
53
54
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
55
PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
56
57
ptimer_transaction_begin(s->timer);
58
- ptimer_set_freq(s->timer, s->pclk_frq);
59
+ ptimer_set_period_from_clock(s->timer, s->pclk, 1);
60
ptimer_transaction_commit(s->timer);
61
}
62
63
--
64
2.20.1
65
66
diff view generated by jsdifflib
Deleted patch
1
Switch the CMSDK APB watchdog device over to using its Clock input;
2
the wdogclk_frq property is now ignored.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Luc Michel <luc@lmichel.fr>
7
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20210128114145.20536-21-peter.maydell@linaro.org
9
Message-id: 20210121190622.22000-21-peter.maydell@linaro.org
10
---
11
hw/watchdog/cmsdk-apb-watchdog.c | 18 ++++++++++++++----
12
1 file changed, 14 insertions(+), 4 deletions(-)
13
14
diff --git a/hw/watchdog/cmsdk-apb-watchdog.c b/hw/watchdog/cmsdk-apb-watchdog.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/watchdog/cmsdk-apb-watchdog.c
17
+++ b/hw/watchdog/cmsdk-apb-watchdog.c
18
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_reset(DeviceState *dev)
19
ptimer_transaction_commit(s->timer);
20
}
21
22
+static void cmsdk_apb_watchdog_clk_update(void *opaque)
23
+{
24
+ CMSDKAPBWatchdog *s = CMSDK_APB_WATCHDOG(opaque);
25
+
26
+ ptimer_transaction_begin(s->timer);
27
+ ptimer_set_period_from_clock(s->timer, s->wdogclk, 1);
28
+ ptimer_transaction_commit(s->timer);
29
+}
30
+
31
static void cmsdk_apb_watchdog_init(Object *obj)
32
{
33
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
34
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_init(Object *obj)
35
s, "cmsdk-apb-watchdog", 0x1000);
36
sysbus_init_mmio(sbd, &s->iomem);
37
sysbus_init_irq(sbd, &s->wdogint);
38
- s->wdogclk = qdev_init_clock_in(DEVICE(s), "WDOGCLK", NULL, NULL);
39
+ s->wdogclk = qdev_init_clock_in(DEVICE(s), "WDOGCLK",
40
+ cmsdk_apb_watchdog_clk_update, s);
41
42
s->is_luminary = false;
43
s->id = cmsdk_apb_watchdog_id;
44
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_realize(DeviceState *dev, Error **errp)
45
{
46
CMSDKAPBWatchdog *s = CMSDK_APB_WATCHDOG(dev);
47
48
- if (s->wdogclk_frq == 0) {
49
+ if (!clock_has_source(s->wdogclk)) {
50
error_setg(errp,
51
- "CMSDK APB watchdog: wdogclk-frq property must be set");
52
+ "CMSDK APB watchdog: WDOGCLK clock must be connected");
53
return;
54
}
55
56
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_realize(DeviceState *dev, Error **errp)
57
PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
58
59
ptimer_transaction_begin(s->timer);
60
- ptimer_set_freq(s->timer, s->wdogclk_frq);
61
+ ptimer_set_period_from_clock(s->timer, s->wdogclk, 1);
62
ptimer_transaction_commit(s->timer);
63
}
64
65
--
66
2.20.1
67
68
diff view generated by jsdifflib
Deleted patch
1
Now that the CMSDK APB watchdog uses its Clock input, it will
2
correctly respond when the system clock frequency is changed using
3
the RCC register on in the Stellaris board system registers. Test
4
that when the RCC register is written it causes the watchdog timer to
5
change speed.
6
1
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Luc Michel <luc@lmichel.fr>
10
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 20210128114145.20536-22-peter.maydell@linaro.org
12
Message-id: 20210121190622.22000-22-peter.maydell@linaro.org
13
---
14
tests/qtest/cmsdk-apb-watchdog-test.c | 52 +++++++++++++++++++++++++++
15
1 file changed, 52 insertions(+)
16
17
diff --git a/tests/qtest/cmsdk-apb-watchdog-test.c b/tests/qtest/cmsdk-apb-watchdog-test.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qtest/cmsdk-apb-watchdog-test.c
20
+++ b/tests/qtest/cmsdk-apb-watchdog-test.c
21
@@ -XXX,XX +XXX,XX @@
22
*/
23
24
#include "qemu/osdep.h"
25
+#include "qemu/bitops.h"
26
#include "libqtest-single.h"
27
28
/*
29
@@ -XXX,XX +XXX,XX @@
30
#define WDOGMIS 0x14
31
#define WDOGLOCK 0xc00
32
33
+#define SSYS_BASE 0x400fe000
34
+#define RCC 0x60
35
+#define SYSDIV_SHIFT 23
36
+#define SYSDIV_LENGTH 4
37
+
38
static void test_watchdog(void)
39
{
40
g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
41
@@ -XXX,XX +XXX,XX @@ static void test_watchdog(void)
42
g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
43
}
44
45
+static void test_clock_change(void)
46
+{
47
+ uint32_t rcc;
48
+
49
+ /*
50
+ * Test that writing to the stellaris board's RCC register to
51
+ * change the system clock frequency causes the watchdog
52
+ * to change the speed it counts at.
53
+ */
54
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
55
+
56
+ writel(WDOG_BASE + WDOGCONTROL, 1);
57
+ writel(WDOG_BASE + WDOGLOAD, 1000);
58
+
59
+ /* Step to just past the 500th tick */
60
+ clock_step(80 * 500 + 1);
61
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
62
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 500);
63
+
64
+ /* Rewrite RCC.SYSDIV from 16 to 8, so the clock is now 40ns per tick */
65
+ rcc = readl(SSYS_BASE + RCC);
66
+ g_assert_cmpuint(extract32(rcc, SYSDIV_SHIFT, SYSDIV_LENGTH), ==, 0xf);
67
+ rcc = deposit32(rcc, SYSDIV_SHIFT, SYSDIV_LENGTH, 7);
68
+ writel(SSYS_BASE + RCC, rcc);
69
+
70
+ /* Just past the 1000th tick: timer should have fired */
71
+ clock_step(40 * 500);
72
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 1);
73
+
74
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 0);
75
+
76
+ /* VALUE reloads at following tick */
77
+ clock_step(41);
78
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 1000);
79
+
80
+ /* Writing any value to WDOGINTCLR clears the interrupt and reloads */
81
+ clock_step(40 * 500);
82
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 500);
83
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 1);
84
+ writel(WDOG_BASE + WDOGINTCLR, 0);
85
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGVALUE), ==, 1000);
86
+ g_assert_cmpuint(readl(WDOG_BASE + WDOGRIS), ==, 0);
87
+}
88
+
89
int main(int argc, char **argv)
90
{
91
int r;
92
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
93
qtest_start("-machine lm3s811evb");
94
95
qtest_add_func("/cmsdk-apb-watchdog/watchdog", test_watchdog);
96
+ qtest_add_func("/cmsdk-apb-watchdog/watchdog_clock_change",
97
+ test_clock_change);
98
99
r = g_test_run();
100
101
--
102
2.20.1
103
104
diff view generated by jsdifflib