1
Nothing too exciting in this lot :-)
1
Arm queue; not huge but I figured I might as well send it out since
2
I've been doing code review today and there's no queue of unprocessed
3
pullreqs...
2
4
3
The following changes since commit ba0fa56bc06e563de68d2a2bf3ddb0cfea1be4f9:
5
thanks
6
-- PMM
4
7
5
Merge remote-tracking branch 'remotes/vivier/tags/q800-for-6.2-pull-request' into staging (2021-09-29 21:20:49 +0100)
8
The following changes since commit b3f846c59d8405bb87c551187721fc92ff2f1b92:
9
10
Merge remote-tracking branch 'remotes/huth-gitlab/tags/pull-request-2021-01-11v2' into staging (2021-01-11 15:15:35 +0000)
6
11
7
are available in the Git repository at:
12
are available in the Git repository at:
8
13
9
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210930
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210112
10
15
11
for you to fetch changes up to 1f4b2ec701b9d73d3fa7bb90c8b4376bc7d3c42b:
16
for you to fetch changes up to 19d131395ccaf503db21dadd8257e6dc9fc1d7de:
12
17
13
hw/arm: sabrelite: Connect SPI flash CS line to GPIO3_19 (2021-09-30 13:44:13 +0100)
18
ui/cocoa: Fix openFile: deprecation on Big Sur (2021-01-12 11:38:37 +0000)
14
19
15
----------------------------------------------------------------
20
----------------------------------------------------------------
16
target-arm queue:
21
target-arm queue:
17
* allwinner-h3: Switch to SMC as PSCI conduit
22
* arm: Support emulation of ARMv8.4-TTST extension
18
* arm: tcg: Adhere to SMCCC 1.3 section 5.2
23
* arm: Update cpu.h ID register field definitions
19
* xlnx-zcu102, xlnx-versal-virt: Support BBRAM and eFUSE devices
24
* arm: Fix breakage of XScale instruction emulation
20
* gdbstub related code cleanups
25
* hw/net/lan9118: Fix RX Status FIFO PEEK value
21
* Don't put FPEXC and FPSID in org.gnu.gdb.arm.vfp XML
26
* npcm7xx: Add ADC and PWM emulation
22
* Use _init vs _new convention in bus creation function names
27
* ui/cocoa: Make "open docs" help menu entry work again when binary
23
* sabrelite: Connect SPI flash CS line to GPIO3_19
28
is run from the build tree
29
* ui/cocoa: Fix openFile: deprecation on Big Sur
30
* docs: Add qemu-storage-daemon(1) manpage to meson.build
31
* docs: Build and install all the docs in a single manual
24
32
25
----------------------------------------------------------------
33
----------------------------------------------------------------
26
Alexander Graf (2):
34
Hao Wu (6):
27
allwinner-h3: Switch to SMC as PSCI conduit
35
hw/misc: Add clock converter in NPCM7XX CLK module
28
arm: tcg: Adhere to SMCCC 1.3 section 5.2
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
29
41
30
Peter Maydell (10):
42
Leif Lindholm (6):
31
configs: Don't include 32-bit-only GDB XML in aarch64 linux configs
43
target/arm: fix typo in cpu.h ID_AA64PFR1 field name
32
target/arm: Fix coding style issues in gdbstub code in helper.c
44
target/arm: make ARMCPU.clidr 64-bit
33
target/arm: Move gdbstub related code out of helper.c
45
target/arm: make ARMCPU.ctr 64-bit
34
target/arm: Don't put FPEXC and FPSID in org.gnu.gdb.arm.vfp XML
46
target/arm: add descriptions of CLIDR_EL1, CCSIDR_EL1, CTR_EL0 to cpu.h
35
scsi: Replace scsi_bus_new() with scsi_bus_init(), scsi_bus_init_named()
47
target/arm: add aarch64 ID register fields to cpu.h
36
ipack: Rename ipack_bus_new_inplace() to ipack_bus_init()
48
target/arm: add aarch32 ID register fields to cpu.h
37
pci: Rename pci_root_bus_new_inplace() to pci_root_bus_init()
38
qbus: Rename qbus_create_inplace() to qbus_init()
39
qbus: Rename qbus_create() to qbus_new()
40
ide: Rename ide_bus_new() to ide_bus_init()
41
49
42
Tong Ho (9):
50
Peter Maydell (5):
43
hw/nvram: Introduce Xilinx eFuse QOM
51
docs: Add qemu-storage-daemon(1) manpage to meson.build
44
hw/nvram: Introduce Xilinx Versal eFuse device
52
docs: Build and install all the docs in a single manual
45
hw/nvram: Introduce Xilinx ZynqMP eFuse device
53
target/arm: Don't decode insns in the XScale/iWMMXt space as cp insns
46
hw/nvram: Introduce Xilinx battery-backed ram
54
hw/net/lan9118: Fix RX Status FIFO PEEK value
47
hw/arm: xlnx-versal-virt: Add Xilinx BBRAM device
55
hw/net/lan9118: Add symbolic constants for register offsets
48
hw/arm: xlnx-versal-virt: Add Xilinx eFUSE device
49
hw/arm: xlnx-zcu102: Add Xilinx BBRAM device
50
hw/arm: xlnx-zcu102: Add Xilinx eFUSE device
51
docs/system/arm: xlnx-versal-virt: BBRAM and eFUSE Usage
52
56
53
Xuzhou Cheng (1):
57
Roman Bolshakov (2):
54
hw/arm: sabrelite: Connect SPI flash CS line to GPIO3_19
58
ui/cocoa: Update path to docs in build tree
59
ui/cocoa: Fix openFile: deprecation on Big Sur
55
60
56
docs/system/arm/xlnx-versal-virt.rst | 49 ++
61
Rémi Denis-Courmont (2):
57
configs/targets/aarch64-linux-user.mak | 2 +-
62
target/arm: ARMv8.4-TTST extension
58
configs/targets/aarch64-softmmu.mak | 2 +-
63
target/arm: enable Small Translation tables in max CPU
59
configs/targets/aarch64_be-linux-user.mak | 2 +-
60
configs/targets/arm-linux-user.mak | 2 +-
61
configs/targets/arm-softmmu.mak | 2 +-
62
configs/targets/armeb-linux-user.mak | 2 +-
63
include/hw/arm/xlnx-versal.h | 15 +
64
include/hw/arm/xlnx-zynqmp.h | 5 +
65
include/hw/ide/internal.h | 4 +-
66
include/hw/ipack/ipack.h | 8 +-
67
include/hw/nvram/xlnx-bbram.h | 54 ++
68
include/hw/nvram/xlnx-efuse.h | 132 +++++
69
include/hw/nvram/xlnx-versal-efuse.h | 68 +++
70
include/hw/nvram/xlnx-zynqmp-efuse.h | 44 ++
71
include/hw/pci/pci.h | 10 +-
72
include/hw/qdev-core.h | 6 +-
73
include/hw/scsi/scsi.h | 30 +-
74
target/arm/internals.h | 7 +
75
hw/arm/allwinner-h3.c | 2 +-
76
hw/arm/sabrelite.c | 2 +-
77
hw/arm/xlnx-versal-virt.c | 88 +++
78
hw/arm/xlnx-versal.c | 57 ++
79
hw/arm/xlnx-zcu102.c | 30 ++
80
hw/arm/xlnx-zynqmp.c | 49 ++
81
hw/audio/intel-hda.c | 2 +-
82
hw/block/fdc.c | 2 +-
83
hw/block/swim.c | 3 +-
84
hw/char/virtio-serial-bus.c | 4 +-
85
hw/core/bus.c | 13 +-
86
hw/core/sysbus.c | 10 +-
87
hw/gpio/bcm2835_gpio.c | 3 +-
88
hw/hyperv/vmbus.c | 2 +-
89
hw/i2c/core.c | 2 +-
90
hw/ide/ahci.c | 2 +-
91
hw/ide/cmd646.c | 2 +-
92
hw/ide/isa.c | 2 +-
93
hw/ide/macio.c | 2 +-
94
hw/ide/microdrive.c | 2 +-
95
hw/ide/mmio.c | 2 +-
96
hw/ide/piix.c | 2 +-
97
hw/ide/qdev.c | 4 +-
98
hw/ide/sii3112.c | 2 +-
99
hw/ide/via.c | 2 +-
100
hw/ipack/ipack.c | 10 +-
101
hw/ipack/tpci200.c | 4 +-
102
hw/isa/isa-bus.c | 2 +-
103
hw/misc/auxbus.c | 2 +-
104
hw/misc/mac_via.c | 4 +-
105
hw/misc/macio/cuda.c | 4 +-
106
hw/misc/macio/macio.c | 4 +-
107
hw/misc/macio/pmu.c | 4 +-
108
hw/nubus/nubus-bridge.c | 2 +-
109
hw/nvme/ctrl.c | 4 +-
110
hw/nvme/subsys.c | 3 +-
111
hw/nvram/xlnx-bbram.c | 545 +++++++++++++++++++
112
hw/nvram/xlnx-efuse-crc.c | 119 +++++
113
hw/nvram/xlnx-efuse.c | 280 ++++++++++
114
hw/nvram/xlnx-versal-efuse-cache.c | 114 ++++
115
hw/nvram/xlnx-versal-efuse-ctrl.c | 783 +++++++++++++++++++++++++++
116
hw/nvram/xlnx-zynqmp-efuse.c | 855 ++++++++++++++++++++++++++++++
117
hw/pci-host/raven.c | 4 +-
118
hw/pci-host/versatile.c | 6 +-
119
hw/pci/pci.c | 30 +-
120
hw/pci/pci_bridge.c | 4 +-
121
hw/ppc/spapr_vio.c | 2 +-
122
hw/s390x/ap-bridge.c | 2 +-
123
hw/s390x/css-bridge.c | 2 +-
124
hw/s390x/event-facility.c | 4 +-
125
hw/s390x/s390-pci-bus.c | 2 +-
126
hw/s390x/virtio-ccw.c | 3 +-
127
hw/scsi/esp-pci.c | 2 +-
128
hw/scsi/esp.c | 2 +-
129
hw/scsi/lsi53c895a.c | 2 +-
130
hw/scsi/megasas.c | 3 +-
131
hw/scsi/mptsas.c | 2 +-
132
hw/scsi/scsi-bus.c | 6 +-
133
hw/scsi/spapr_vscsi.c | 3 +-
134
hw/scsi/virtio-scsi.c | 4 +-
135
hw/scsi/vmw_pvscsi.c | 3 +-
136
hw/sd/allwinner-sdhost.c | 4 +-
137
hw/sd/bcm2835_sdhost.c | 4 +-
138
hw/sd/pl181.c | 3 +-
139
hw/sd/pxa2xx_mmci.c | 4 +-
140
hw/sd/sdhci.c | 3 +-
141
hw/sd/ssi-sd.c | 3 +-
142
hw/ssi/ssi.c | 2 +-
143
hw/usb/bus.c | 2 +-
144
hw/usb/dev-smartcard-reader.c | 3 +-
145
hw/usb/dev-storage-bot.c | 3 +-
146
hw/usb/dev-storage-classic.c | 4 +-
147
hw/usb/dev-uas.c | 3 +-
148
hw/virtio/virtio-mmio.c | 3 +-
149
hw/virtio/virtio-pci.c | 3 +-
150
hw/xen/xen-bus.c | 2 +-
151
hw/xen/xen-legacy-backend.c | 2 +-
152
target/arm/gdbstub.c | 154 ++++++
153
target/arm/gdbstub64.c | 140 +++++
154
target/arm/helper.c | 262 ---------
155
target/arm/psci.c | 35 +-
156
gdb-xml/arm-neon.xml | 2 -
157
gdb-xml/arm-vfp-sysregs.xml | 17 +
158
gdb-xml/arm-vfp.xml | 2 -
159
gdb-xml/arm-vfp3.xml | 2 -
160
hw/Kconfig | 2 +
161
hw/arm/Kconfig | 2 +
162
hw/nvram/Kconfig | 19 +
163
hw/nvram/meson.build | 8 +
164
108 files changed, 3806 insertions(+), 447 deletions(-)
165
create mode 100644 include/hw/nvram/xlnx-bbram.h
166
create mode 100644 include/hw/nvram/xlnx-efuse.h
167
create mode 100644 include/hw/nvram/xlnx-versal-efuse.h
168
create mode 100644 include/hw/nvram/xlnx-zynqmp-efuse.h
169
create mode 100644 hw/nvram/xlnx-bbram.c
170
create mode 100644 hw/nvram/xlnx-efuse-crc.c
171
create mode 100644 hw/nvram/xlnx-efuse.c
172
create mode 100644 hw/nvram/xlnx-versal-efuse-cache.c
173
create mode 100644 hw/nvram/xlnx-versal-efuse-ctrl.c
174
create mode 100644 hw/nvram/xlnx-zynqmp-efuse.c
175
create mode 100644 gdb-xml/arm-vfp-sysregs.xml
176
64
65
docs/conf.py | 46 ++-
66
docs/devel/conf.py | 15 -
67
docs/index.html.in | 17 -
68
docs/interop/conf.py | 28 --
69
docs/meson.build | 65 ++--
70
docs/specs/conf.py | 16 -
71
docs/system/arm/nuvoton.rst | 4 +-
72
docs/system/conf.py | 28 --
73
docs/tools/conf.py | 37 --
74
docs/user/conf.py | 15 -
75
meson.build | 1 +
76
hw/adc/trace.h | 1 +
77
include/hw/adc/npcm7xx_adc.h | 69 ++++
78
include/hw/arm/npcm7xx.h | 4 +
79
include/hw/misc/npcm7xx_clk.h | 146 ++++++-
80
include/hw/misc/npcm7xx_pwm.h | 105 +++++
81
include/hw/timer/npcm7xx_timer.h | 1 +
82
target/arm/cpu.h | 85 ++++-
83
hw/adc/npcm7xx_adc.c | 301 +++++++++++++++
84
hw/arm/npcm7xx.c | 55 ++-
85
hw/arm/npcm7xx_boards.c | 2 +-
86
hw/mem/npcm7xx_mc.c | 2 +-
87
hw/misc/npcm7xx_clk.c | 807 ++++++++++++++++++++++++++++++++++++++-
88
hw/misc/npcm7xx_gcr.c | 2 +-
89
hw/misc/npcm7xx_pwm.c | 550 ++++++++++++++++++++++++++
90
hw/misc/npcm7xx_rng.c | 2 +-
91
hw/net/lan9118.c | 26 +-
92
hw/nvram/npcm7xx_otp.c | 2 +-
93
hw/ssi/npcm7xx_fiu.c | 2 +-
94
hw/timer/npcm7xx_timer.c | 39 +-
95
target/arm/cpu64.c | 1 +
96
target/arm/helper.c | 15 +-
97
target/arm/translate.c | 7 +
98
tests/qtest/npcm7xx_adc-test.c | 377 ++++++++++++++++++
99
tests/qtest/npcm7xx_pwm-test.c | 490 ++++++++++++++++++++++++
100
hw/adc/meson.build | 1 +
101
hw/adc/trace-events | 5 +
102
hw/misc/meson.build | 1 +
103
hw/misc/trace-events | 6 +
104
tests/qtest/meson.build | 4 +-
105
ui/cocoa.m | 7 +-
106
41 files changed, 3124 insertions(+), 263 deletions(-)
107
delete mode 100644 docs/devel/conf.py
108
delete mode 100644 docs/index.html.in
109
delete mode 100644 docs/interop/conf.py
110
delete mode 100644 docs/specs/conf.py
111
delete mode 100644 docs/system/conf.py
112
delete mode 100644 docs/tools/conf.py
113
delete mode 100644 docs/user/conf.py
114
create mode 100644 hw/adc/trace.h
115
create mode 100644 include/hw/adc/npcm7xx_adc.h
116
create mode 100644 include/hw/misc/npcm7xx_pwm.h
117
create mode 100644 hw/adc/npcm7xx_adc.c
118
create mode 100644 hw/misc/npcm7xx_pwm.c
119
create mode 100644 tests/qtest/npcm7xx_adc-test.c
120
create mode 100644 tests/qtest/npcm7xx_pwm-test.c
121
create mode 100644 hw/adc/trace-events
122
diff view generated by jsdifflib
1
Currently helper.c includes some code which is part of the arm
1
From: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
2
target's gdbstub support. This code has a better home: in gdbstub.c
3
and gdbstub64.c. Move it there.
4
2
5
Because aarch64_fpu_gdb_get_reg() and aarch64_fpu_gdb_set_reg() move
3
This adds for the Small Translation tables extension in AArch64 state.
6
into gdbstub64.c, this means that they're now compiled only for
7
TARGET_AARCH64 rather than always. That is the only case when they
8
would ever be used, but it does mean that the ifdef in
9
arm_cpu_register_gdb_regs_for_features() needs to be adjusted to
10
match.
11
4
5
Signed-off-by: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20210921162901.17508-4-peter.maydell@linaro.org
16
---
8
---
17
target/arm/internals.h | 7 ++
9
target/arm/cpu.h | 5 +++++
18
target/arm/gdbstub.c | 130 ++++++++++++++++++++
10
target/arm/helper.c | 15 +++++++++++++--
19
target/arm/gdbstub64.c | 140 +++++++++++++++++++++
11
2 files changed, 18 insertions(+), 2 deletions(-)
20
target/arm/helper.c | 271 -----------------------------------------
21
4 files changed, 277 insertions(+), 271 deletions(-)
22
12
23
diff --git a/target/arm/internals.h b/target/arm/internals.h
13
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
24
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/internals.h
15
--- a/target/arm/cpu.h
26
+++ b/target/arm/internals.h
16
+++ b/target/arm/cpu.h
27
@@ -XXX,XX +XXX,XX @@ static inline uint64_t pmu_counter_mask(CPUARMState *env)
17
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_uao(const ARMISARegisters *id)
28
return (1 << 31) | ((1 << pmu_num_counters(env)) - 1);
18
return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0;
29
}
19
}
30
20
31
+#ifdef TARGET_AARCH64
21
+static inline bool isar_feature_aa64_st(const ARMISARegisters *id)
32
+int arm_gdb_get_svereg(CPUARMState *env, GByteArray *buf, int reg);
33
+int arm_gdb_set_svereg(CPUARMState *env, uint8_t *buf, int reg);
34
+int aarch64_fpu_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg);
35
+int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg);
36
+#endif
37
+
38
#endif
39
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/gdbstub.c
42
+++ b/target/arm/gdbstub.c
43
@@ -XXX,XX +XXX,XX @@
44
*/
45
#include "qemu/osdep.h"
46
#include "cpu.h"
47
+#include "internals.h"
48
#include "exec/gdbstub.h"
49
50
typedef struct RegisterSysregXmlParam {
51
@@ -XXX,XX +XXX,XX @@ int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
52
return 0;
53
}
54
55
+static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
56
+{
22
+{
57
+ ARMCPU *cpu = env_archcpu(env);
23
+ return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, ST) != 0;
58
+ int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16;
59
+
60
+ /* VFP data registers are always little-endian. */
61
+ if (reg < nregs) {
62
+ return gdb_get_reg64(buf, *aa32_vfp_dreg(env, reg));
63
+ }
64
+ if (arm_feature(env, ARM_FEATURE_NEON)) {
65
+ /* Aliases for Q regs. */
66
+ nregs += 16;
67
+ if (reg < nregs) {
68
+ uint64_t *q = aa32_vfp_qreg(env, reg - 32);
69
+ return gdb_get_reg128(buf, q[0], q[1]);
70
+ }
71
+ }
72
+ switch (reg - nregs) {
73
+ case 0:
74
+ return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]);
75
+ case 1:
76
+ return gdb_get_reg32(buf, vfp_get_fpscr(env));
77
+ case 2:
78
+ return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]);
79
+ }
80
+ return 0;
81
+}
24
+}
82
+
25
+
83
+static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
26
static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
84
+{
27
{
85
+ ARMCPU *cpu = env_archcpu(env);
28
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;
86
+ int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16;
87
+
88
+ if (reg < nregs) {
89
+ *aa32_vfp_dreg(env, reg) = ldq_le_p(buf);
90
+ return 8;
91
+ }
92
+ if (arm_feature(env, ARM_FEATURE_NEON)) {
93
+ nregs += 16;
94
+ if (reg < nregs) {
95
+ uint64_t *q = aa32_vfp_qreg(env, reg - 32);
96
+ q[0] = ldq_le_p(buf);
97
+ q[1] = ldq_le_p(buf + 8);
98
+ return 16;
99
+ }
100
+ }
101
+ switch (reg - nregs) {
102
+ case 0:
103
+ env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf);
104
+ return 4;
105
+ case 1:
106
+ vfp_set_fpscr(env, ldl_p(buf));
107
+ return 4;
108
+ case 2:
109
+ env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30);
110
+ return 4;
111
+ }
112
+ return 0;
113
+}
114
+
115
+/**
116
+ * arm_get/set_gdb_*: get/set a gdb register
117
+ * @env: the CPU state
118
+ * @buf: a buffer to copy to/from
119
+ * @reg: register number (offset from start of group)
120
+ *
121
+ * We return the number of bytes copied
122
+ */
123
+
124
+static int arm_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg)
125
+{
126
+ ARMCPU *cpu = env_archcpu(env);
127
+ const ARMCPRegInfo *ri;
128
+ uint32_t key;
129
+
130
+ key = cpu->dyn_sysreg_xml.data.cpregs.keys[reg];
131
+ ri = get_arm_cp_reginfo(cpu->cp_regs, key);
132
+ if (ri) {
133
+ if (cpreg_field_is_64bit(ri)) {
134
+ return gdb_get_reg64(buf, (uint64_t)read_raw_cp_reg(env, ri));
135
+ } else {
136
+ return gdb_get_reg32(buf, (uint32_t)read_raw_cp_reg(env, ri));
137
+ }
138
+ }
139
+ return 0;
140
+}
141
+
142
+static int arm_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg)
143
+{
144
+ return 0;
145
+}
146
+
147
static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
148
ARMCPRegInfo *ri, uint32_t ri_key,
149
int bitsize, int regnum)
150
@@ -XXX,XX +XXX,XX @@ const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
151
}
152
return NULL;
153
}
154
+
155
+void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
156
+{
157
+ CPUState *cs = CPU(cpu);
158
+ CPUARMState *env = &cpu->env;
159
+
160
+ if (arm_feature(env, ARM_FEATURE_AARCH64)) {
161
+ /*
162
+ * The lower part of each SVE register aliases to the FPU
163
+ * registers so we don't need to include both.
164
+ */
165
+#ifdef TARGET_AARCH64
166
+ if (isar_feature_aa64_sve(&cpu->isar)) {
167
+ gdb_register_coprocessor(cs, arm_gdb_get_svereg, arm_gdb_set_svereg,
168
+ arm_gen_dynamic_svereg_xml(cs, cs->gdb_num_regs),
169
+ "sve-registers.xml", 0);
170
+ } else {
171
+ gdb_register_coprocessor(cs, aarch64_fpu_gdb_get_reg,
172
+ aarch64_fpu_gdb_set_reg,
173
+ 34, "aarch64-fpu.xml", 0);
174
+ }
175
+#endif
176
+ } else if (arm_feature(env, ARM_FEATURE_NEON)) {
177
+ gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
178
+ 51, "arm-neon.xml", 0);
179
+ } else if (cpu_isar_feature(aa32_simd_r32, cpu)) {
180
+ gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
181
+ 35, "arm-vfp3.xml", 0);
182
+ } else if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
183
+ gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
184
+ 19, "arm-vfp.xml", 0);
185
+ }
186
+ gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg,
187
+ arm_gen_dynamic_sysreg_xml(cs, cs->gdb_num_regs),
188
+ "system-registers.xml", 0);
189
+
190
+}
191
diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
192
index XXXXXXX..XXXXXXX 100644
193
--- a/target/arm/gdbstub64.c
194
+++ b/target/arm/gdbstub64.c
195
@@ -XXX,XX +XXX,XX @@
196
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
197
*/
198
#include "qemu/osdep.h"
199
+#include "qemu/log.h"
200
#include "cpu.h"
201
+#include "internals.h"
202
#include "exec/gdbstub.h"
203
204
int aarch64_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
205
@@ -XXX,XX +XXX,XX @@ int aarch64_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
206
/* Unknown register. */
207
return 0;
208
}
209
+
210
+int aarch64_fpu_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
211
+{
212
+ switch (reg) {
213
+ case 0 ... 31:
214
+ {
215
+ /* 128 bit FP register - quads are in LE order */
216
+ uint64_t *q = aa64_vfp_qreg(env, reg);
217
+ return gdb_get_reg128(buf, q[1], q[0]);
218
+ }
219
+ case 32:
220
+ /* FPSR */
221
+ return gdb_get_reg32(buf, vfp_get_fpsr(env));
222
+ case 33:
223
+ /* FPCR */
224
+ return gdb_get_reg32(buf, vfp_get_fpcr(env));
225
+ default:
226
+ return 0;
227
+ }
228
+}
229
+
230
+int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
231
+{
232
+ switch (reg) {
233
+ case 0 ... 31:
234
+ /* 128 bit FP register */
235
+ {
236
+ uint64_t *q = aa64_vfp_qreg(env, reg);
237
+ q[0] = ldq_le_p(buf);
238
+ q[1] = ldq_le_p(buf + 8);
239
+ return 16;
240
+ }
241
+ case 32:
242
+ /* FPSR */
243
+ vfp_set_fpsr(env, ldl_p(buf));
244
+ return 4;
245
+ case 33:
246
+ /* FPCR */
247
+ vfp_set_fpcr(env, ldl_p(buf));
248
+ return 4;
249
+ default:
250
+ return 0;
251
+ }
252
+}
253
+
254
+int arm_gdb_get_svereg(CPUARMState *env, GByteArray *buf, int reg)
255
+{
256
+ ARMCPU *cpu = env_archcpu(env);
257
+
258
+ switch (reg) {
259
+ /* The first 32 registers are the zregs */
260
+ case 0 ... 31:
261
+ {
262
+ int vq, len = 0;
263
+ for (vq = 0; vq < cpu->sve_max_vq; vq++) {
264
+ len += gdb_get_reg128(buf,
265
+ env->vfp.zregs[reg].d[vq * 2 + 1],
266
+ env->vfp.zregs[reg].d[vq * 2]);
267
+ }
268
+ return len;
269
+ }
270
+ case 32:
271
+ return gdb_get_reg32(buf, vfp_get_fpsr(env));
272
+ case 33:
273
+ return gdb_get_reg32(buf, vfp_get_fpcr(env));
274
+ /* then 16 predicates and the ffr */
275
+ case 34 ... 50:
276
+ {
277
+ int preg = reg - 34;
278
+ int vq, len = 0;
279
+ for (vq = 0; vq < cpu->sve_max_vq; vq = vq + 4) {
280
+ len += gdb_get_reg64(buf, env->vfp.pregs[preg].p[vq / 4]);
281
+ }
282
+ return len;
283
+ }
284
+ case 51:
285
+ {
286
+ /*
287
+ * We report in Vector Granules (VG) which is 64bit in a Z reg
288
+ * while the ZCR works in Vector Quads (VQ) which is 128bit chunks.
289
+ */
290
+ int vq = sve_zcr_len_for_el(env, arm_current_el(env)) + 1;
291
+ return gdb_get_reg64(buf, vq * 2);
292
+ }
293
+ default:
294
+ /* gdbstub asked for something out our range */
295
+ qemu_log_mask(LOG_UNIMP, "%s: out of range register %d", __func__, reg);
296
+ break;
297
+ }
298
+
299
+ return 0;
300
+}
301
+
302
+int arm_gdb_set_svereg(CPUARMState *env, uint8_t *buf, int reg)
303
+{
304
+ ARMCPU *cpu = env_archcpu(env);
305
+
306
+ /* The first 32 registers are the zregs */
307
+ switch (reg) {
308
+ /* The first 32 registers are the zregs */
309
+ case 0 ... 31:
310
+ {
311
+ int vq, len = 0;
312
+ uint64_t *p = (uint64_t *) buf;
313
+ for (vq = 0; vq < cpu->sve_max_vq; vq++) {
314
+ env->vfp.zregs[reg].d[vq * 2 + 1] = *p++;
315
+ env->vfp.zregs[reg].d[vq * 2] = *p++;
316
+ len += 16;
317
+ }
318
+ return len;
319
+ }
320
+ case 32:
321
+ vfp_set_fpsr(env, *(uint32_t *)buf);
322
+ return 4;
323
+ case 33:
324
+ vfp_set_fpcr(env, *(uint32_t *)buf);
325
+ return 4;
326
+ case 34 ... 50:
327
+ {
328
+ int preg = reg - 34;
329
+ int vq, len = 0;
330
+ uint64_t *p = (uint64_t *) buf;
331
+ for (vq = 0; vq < cpu->sve_max_vq; vq = vq + 4) {
332
+ env->vfp.pregs[preg].p[vq / 4] = *p++;
333
+ len += 8;
334
+ }
335
+ return len;
336
+ }
337
+ case 51:
338
+ /* cannot set vg via gdbstub */
339
+ return 0;
340
+ default:
341
+ /* gdbstub asked for something out our range */
342
+ break;
343
+ }
344
+
345
+ return 0;
346
+}
347
diff --git a/target/arm/helper.c b/target/arm/helper.c
29
diff --git a/target/arm/helper.c b/target/arm/helper.c
348
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
349
--- a/target/arm/helper.c
31
--- a/target/arm/helper.c
350
+++ b/target/arm/helper.c
32
+++ b/target/arm/helper.c
351
@@ -XXX,XX +XXX,XX @@
33
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
352
#include "trace.h"
34
{
353
#include "cpu.h"
35
uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
354
#include "internals.h"
36
bool epd, hpd, using16k, using64k;
355
-#include "exec/gdbstub.h"
37
- int select, tsz, tbi;
356
#include "exec/helper-proto.h"
38
+ int select, tsz, tbi, max_tsz;
357
#include "qemu/host-utils.h"
39
358
#include "qemu/main-loop.h"
40
if (!regime_has_2_ranges(mmu_idx)) {
41
select = 0;
42
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
43
hpd = extract64(tcr, 42, 1);
44
}
45
}
46
- tsz = MIN(tsz, 39); /* TODO: ARMv8.4-TTST */
47
+
48
+ if (cpu_isar_feature(aa64_st, env_archcpu(env))) {
49
+ max_tsz = 48 - using64k;
50
+ } else {
51
+ max_tsz = 39;
52
+ }
53
+
54
+ tsz = MIN(tsz, max_tsz);
55
tsz = MAX(tsz, 16); /* TODO: ARMv8.2-LVA */
56
57
/* Present TBI as a composite with TBID. */
359
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
58
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
360
static void switch_mode(CPUARMState *env, int mode);
59
if (!aarch64 || stride == 9) {
361
static int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx);
60
/* AArch32 or 4KB pages */
362
61
startlevel = 2 - sl0;
363
-static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
62
+
364
-{
63
+ if (cpu_isar_feature(aa64_st, cpu)) {
365
- ARMCPU *cpu = env_archcpu(env);
64
+ startlevel &= 3;
366
- int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16;
65
+ }
367
-
66
} else {
368
- /* VFP data registers are always little-endian. */
67
/* 16KB or 64KB pages */
369
- if (reg < nregs) {
68
startlevel = 3 - sl0;
370
- return gdb_get_reg64(buf, *aa32_vfp_dreg(env, reg));
371
- }
372
- if (arm_feature(env, ARM_FEATURE_NEON)) {
373
- /* Aliases for Q regs. */
374
- nregs += 16;
375
- if (reg < nregs) {
376
- uint64_t *q = aa32_vfp_qreg(env, reg - 32);
377
- return gdb_get_reg128(buf, q[0], q[1]);
378
- }
379
- }
380
- switch (reg - nregs) {
381
- case 0:
382
- return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]);
383
- case 1:
384
- return gdb_get_reg32(buf, vfp_get_fpscr(env));
385
- case 2:
386
- return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]);
387
- }
388
- return 0;
389
-}
390
-
391
-static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
392
-{
393
- ARMCPU *cpu = env_archcpu(env);
394
- int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16;
395
-
396
- if (reg < nregs) {
397
- *aa32_vfp_dreg(env, reg) = ldq_le_p(buf);
398
- return 8;
399
- }
400
- if (arm_feature(env, ARM_FEATURE_NEON)) {
401
- nregs += 16;
402
- if (reg < nregs) {
403
- uint64_t *q = aa32_vfp_qreg(env, reg - 32);
404
- q[0] = ldq_le_p(buf);
405
- q[1] = ldq_le_p(buf + 8);
406
- return 16;
407
- }
408
- }
409
- switch (reg - nregs) {
410
- case 0:
411
- env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf);
412
- return 4;
413
- case 1:
414
- vfp_set_fpscr(env, ldl_p(buf));
415
- return 4;
416
- case 2:
417
- env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30);
418
- return 4;
419
- }
420
- return 0;
421
-}
422
-
423
-static int aarch64_fpu_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
424
-{
425
- switch (reg) {
426
- case 0 ... 31:
427
- {
428
- /* 128 bit FP register - quads are in LE order */
429
- uint64_t *q = aa64_vfp_qreg(env, reg);
430
- return gdb_get_reg128(buf, q[1], q[0]);
431
- }
432
- case 32:
433
- /* FPSR */
434
- return gdb_get_reg32(buf, vfp_get_fpsr(env));
435
- case 33:
436
- /* FPCR */
437
- return gdb_get_reg32(buf, vfp_get_fpcr(env));
438
- default:
439
- return 0;
440
- }
441
-}
442
-
443
-static int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
444
-{
445
- switch (reg) {
446
- case 0 ... 31:
447
- /* 128 bit FP register */
448
- {
449
- uint64_t *q = aa64_vfp_qreg(env, reg);
450
- q[0] = ldq_le_p(buf);
451
- q[1] = ldq_le_p(buf + 8);
452
- return 16;
453
- }
454
- case 32:
455
- /* FPSR */
456
- vfp_set_fpsr(env, ldl_p(buf));
457
- return 4;
458
- case 33:
459
- /* FPCR */
460
- vfp_set_fpcr(env, ldl_p(buf));
461
- return 4;
462
- default:
463
- return 0;
464
- }
465
-}
466
-
467
static uint64_t raw_read(CPUARMState *env, const ARMCPRegInfo *ri)
468
{
469
assert(ri->fieldoffset);
470
@@ -XXX,XX +XXX,XX @@ static void write_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri,
471
}
472
}
473
474
-/**
475
- * arm_get/set_gdb_*: get/set a gdb register
476
- * @env: the CPU state
477
- * @buf: a buffer to copy to/from
478
- * @reg: register number (offset from start of group)
479
- *
480
- * We return the number of bytes copied
481
- */
482
-
483
-static int arm_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg)
484
-{
485
- ARMCPU *cpu = env_archcpu(env);
486
- const ARMCPRegInfo *ri;
487
- uint32_t key;
488
-
489
- key = cpu->dyn_sysreg_xml.data.cpregs.keys[reg];
490
- ri = get_arm_cp_reginfo(cpu->cp_regs, key);
491
- if (ri) {
492
- if (cpreg_field_is_64bit(ri)) {
493
- return gdb_get_reg64(buf, (uint64_t)read_raw_cp_reg(env, ri));
494
- } else {
495
- return gdb_get_reg32(buf, (uint32_t)read_raw_cp_reg(env, ri));
496
- }
497
- }
498
- return 0;
499
-}
500
-
501
-static int arm_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg)
502
-{
503
- return 0;
504
-}
505
-
506
-#ifdef TARGET_AARCH64
507
-static int arm_gdb_get_svereg(CPUARMState *env, GByteArray *buf, int reg)
508
-{
509
- ARMCPU *cpu = env_archcpu(env);
510
-
511
- switch (reg) {
512
- /* The first 32 registers are the zregs */
513
- case 0 ... 31:
514
- {
515
- int vq, len = 0;
516
- for (vq = 0; vq < cpu->sve_max_vq; vq++) {
517
- len += gdb_get_reg128(buf,
518
- env->vfp.zregs[reg].d[vq * 2 + 1],
519
- env->vfp.zregs[reg].d[vq * 2]);
520
- }
521
- return len;
522
- }
523
- case 32:
524
- return gdb_get_reg32(buf, vfp_get_fpsr(env));
525
- case 33:
526
- return gdb_get_reg32(buf, vfp_get_fpcr(env));
527
- /* then 16 predicates and the ffr */
528
- case 34 ... 50:
529
- {
530
- int preg = reg - 34;
531
- int vq, len = 0;
532
- for (vq = 0; vq < cpu->sve_max_vq; vq = vq + 4) {
533
- len += gdb_get_reg64(buf, env->vfp.pregs[preg].p[vq / 4]);
534
- }
535
- return len;
536
- }
537
- case 51:
538
- {
539
- /*
540
- * We report in Vector Granules (VG) which is 64bit in a Z reg
541
- * while the ZCR works in Vector Quads (VQ) which is 128bit chunks.
542
- */
543
- int vq = sve_zcr_len_for_el(env, arm_current_el(env)) + 1;
544
- return gdb_get_reg64(buf, vq * 2);
545
- }
546
- default:
547
- /* gdbstub asked for something out our range */
548
- qemu_log_mask(LOG_UNIMP, "%s: out of range register %d", __func__, reg);
549
- break;
550
- }
551
-
552
- return 0;
553
-}
554
-
555
-static int arm_gdb_set_svereg(CPUARMState *env, uint8_t *buf, int reg)
556
-{
557
- ARMCPU *cpu = env_archcpu(env);
558
-
559
- /* The first 32 registers are the zregs */
560
- switch (reg) {
561
- /* The first 32 registers are the zregs */
562
- case 0 ... 31:
563
- {
564
- int vq, len = 0;
565
- uint64_t *p = (uint64_t *) buf;
566
- for (vq = 0; vq < cpu->sve_max_vq; vq++) {
567
- env->vfp.zregs[reg].d[vq * 2 + 1] = *p++;
568
- env->vfp.zregs[reg].d[vq * 2] = *p++;
569
- len += 16;
570
- }
571
- return len;
572
- }
573
- case 32:
574
- vfp_set_fpsr(env, *(uint32_t *)buf);
575
- return 4;
576
- case 33:
577
- vfp_set_fpcr(env, *(uint32_t *)buf);
578
- return 4;
579
- case 34 ... 50:
580
- {
581
- int preg = reg - 34;
582
- int vq, len = 0;
583
- uint64_t *p = (uint64_t *) buf;
584
- for (vq = 0; vq < cpu->sve_max_vq; vq = vq + 4) {
585
- env->vfp.pregs[preg].p[vq / 4] = *p++;
586
- len += 8;
587
- }
588
- return len;
589
- }
590
- case 51:
591
- /* cannot set vg via gdbstub */
592
- return 0;
593
- default:
594
- /* gdbstub asked for something out our range */
595
- break;
596
- }
597
-
598
- return 0;
599
-}
600
-#endif /* TARGET_AARCH64 */
601
-
602
static bool raw_accessors_invalid(const ARMCPRegInfo *ri)
603
{
604
/* Return true if the regdef would cause an assertion if you called
605
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
606
#endif
607
}
608
609
-void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
610
-{
611
- CPUState *cs = CPU(cpu);
612
- CPUARMState *env = &cpu->env;
613
-
614
- if (arm_feature(env, ARM_FEATURE_AARCH64)) {
615
- /*
616
- * The lower part of each SVE register aliases to the FPU
617
- * registers so we don't need to include both.
618
- */
619
-#ifdef TARGET_AARCH64
620
- if (isar_feature_aa64_sve(&cpu->isar)) {
621
- gdb_register_coprocessor(cs, arm_gdb_get_svereg, arm_gdb_set_svereg,
622
- arm_gen_dynamic_svereg_xml(cs, cs->gdb_num_regs),
623
- "sve-registers.xml", 0);
624
- } else
625
-#endif
626
- {
627
- gdb_register_coprocessor(cs, aarch64_fpu_gdb_get_reg,
628
- aarch64_fpu_gdb_set_reg,
629
- 34, "aarch64-fpu.xml", 0);
630
- }
631
- } else if (arm_feature(env, ARM_FEATURE_NEON)) {
632
- gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
633
- 51, "arm-neon.xml", 0);
634
- } else if (cpu_isar_feature(aa32_simd_r32, cpu)) {
635
- gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
636
- 35, "arm-vfp3.xml", 0);
637
- } else if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
638
- gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
639
- 19, "arm-vfp.xml", 0);
640
- }
641
- gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg,
642
- arm_gen_dynamic_sysreg_xml(cs, cs->gdb_num_regs),
643
- "system-registers.xml", 0);
644
-
645
-}
646
-
647
/* Sort alphabetically by type name, except for "any". */
648
static gint arm_cpu_list_compare(gconstpointer a, gconstpointer b)
649
{
650
--
69
--
651
2.20.1
70
2.20.1
652
71
653
72
diff view generated by jsdifflib
1
The function ide_bus_new() does an in-place initialization. Rename
1
From: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
2
it to ide_bus_init() to follow our _init vs _new convention.
3
2
3
Signed-off-by: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
7
Reviewed-by: Corey Minyard <cminyard@mvista.com>
8
Reviewed-by: John Snow <jsnow@redhat.com>
9
Acked-by: John Snow <jsnow@redhat.com> (Feel free to merge.)
10
Message-id: 20210923121153.23754-7-peter.maydell@linaro.org
11
---
6
---
12
include/hw/ide/internal.h | 4 ++--
7
target/arm/cpu64.c | 1 +
13
hw/ide/ahci.c | 2 +-
8
1 file changed, 1 insertion(+)
14
hw/ide/cmd646.c | 2 +-
15
hw/ide/isa.c | 2 +-
16
hw/ide/macio.c | 2 +-
17
hw/ide/microdrive.c | 2 +-
18
hw/ide/mmio.c | 2 +-
19
hw/ide/piix.c | 2 +-
20
hw/ide/qdev.c | 2 +-
21
hw/ide/sii3112.c | 2 +-
22
hw/ide/via.c | 2 +-
23
11 files changed, 12 insertions(+), 12 deletions(-)
24
9
25
diff --git a/include/hw/ide/internal.h b/include/hw/ide/internal.h
10
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
26
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
27
--- a/include/hw/ide/internal.h
12
--- a/target/arm/cpu64.c
28
+++ b/include/hw/ide/internal.h
13
+++ b/target/arm/cpu64.c
29
@@ -XXX,XX +XXX,XX @@ void ide_atapi_cmd(IDEState *s);
14
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
30
void ide_atapi_cmd_reply_end(IDEState *s);
15
t = cpu->isar.id_aa64mmfr2;
31
16
t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1);
32
/* hw/ide/qdev.c */
17
t = FIELD_DP64(t, ID_AA64MMFR2, CNP, 1); /* TTCNP */
33
-void ide_bus_new(IDEBus *idebus, size_t idebus_size, DeviceState *dev,
18
+ t = FIELD_DP64(t, ID_AA64MMFR2, ST, 1); /* TTST */
34
- int bus_id, int max_units);
19
cpu->isar.id_aa64mmfr2 = t;
35
+void ide_bus_init(IDEBus *idebus, size_t idebus_size, DeviceState *dev,
20
36
+ int bus_id, int max_units);
21
/* Replicate the same data to the 32-bit id registers. */
37
IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive);
38
39
int ide_handle_rw_error(IDEState *s, int error, int op);
40
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/ide/ahci.c
43
+++ b/hw/ide/ahci.c
44
@@ -XXX,XX +XXX,XX @@ void ahci_realize(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports)
45
for (i = 0; i < s->ports; i++) {
46
AHCIDevice *ad = &s->dev[i];
47
48
- ide_bus_new(&ad->port, sizeof(ad->port), qdev, i, 1);
49
+ ide_bus_init(&ad->port, sizeof(ad->port), qdev, i, 1);
50
ide_init2(&ad->port, irqs[i]);
51
52
ad->hba = s;
53
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/hw/ide/cmd646.c
56
+++ b/hw/ide/cmd646.c
57
@@ -XXX,XX +XXX,XX @@ static void pci_cmd646_ide_realize(PCIDevice *dev, Error **errp)
58
59
qdev_init_gpio_in(ds, cmd646_set_irq, 2);
60
for (i = 0; i < 2; i++) {
61
- ide_bus_new(&d->bus[i], sizeof(d->bus[i]), ds, i, 2);
62
+ ide_bus_init(&d->bus[i], sizeof(d->bus[i]), ds, i, 2);
63
ide_init2(&d->bus[i], qdev_get_gpio_in(ds, i));
64
65
bmdma_init(&d->bus[i], &d->bmdma[i], d);
66
diff --git a/hw/ide/isa.c b/hw/ide/isa.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/hw/ide/isa.c
69
+++ b/hw/ide/isa.c
70
@@ -XXX,XX +XXX,XX @@ static void isa_ide_realizefn(DeviceState *dev, Error **errp)
71
ISADevice *isadev = ISA_DEVICE(dev);
72
ISAIDEState *s = ISA_IDE(dev);
73
74
- ide_bus_new(&s->bus, sizeof(s->bus), dev, 0, 2);
75
+ ide_bus_init(&s->bus, sizeof(s->bus), dev, 0, 2);
76
ide_init_ioport(&s->bus, isadev, s->iobase, s->iobase2);
77
isa_init_irq(isadev, &s->irq, s->isairq);
78
ide_init2(&s->bus, s->irq);
79
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/hw/ide/macio.c
82
+++ b/hw/ide/macio.c
83
@@ -XXX,XX +XXX,XX @@ static void macio_ide_initfn(Object *obj)
84
SysBusDevice *d = SYS_BUS_DEVICE(obj);
85
MACIOIDEState *s = MACIO_IDE(obj);
86
87
- ide_bus_new(&s->bus, sizeof(s->bus), DEVICE(obj), 0, 2);
88
+ ide_bus_init(&s->bus, sizeof(s->bus), DEVICE(obj), 0, 2);
89
memory_region_init_io(&s->mem, obj, &pmac_ide_ops, s, "pmac-ide", 0x1000);
90
sysbus_init_mmio(d, &s->mem);
91
sysbus_init_irq(d, &s->real_ide_irq);
92
diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c
93
index XXXXXXX..XXXXXXX 100644
94
--- a/hw/ide/microdrive.c
95
+++ b/hw/ide/microdrive.c
96
@@ -XXX,XX +XXX,XX @@ static void microdrive_init(Object *obj)
97
{
98
MicroDriveState *md = MICRODRIVE(obj);
99
100
- ide_bus_new(&md->bus, sizeof(md->bus), DEVICE(obj), 0, 1);
101
+ ide_bus_init(&md->bus, sizeof(md->bus), DEVICE(obj), 0, 1);
102
}
103
104
static void microdrive_class_init(ObjectClass *oc, void *data)
105
diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/hw/ide/mmio.c
108
+++ b/hw/ide/mmio.c
109
@@ -XXX,XX +XXX,XX @@ static void mmio_ide_initfn(Object *obj)
110
SysBusDevice *d = SYS_BUS_DEVICE(obj);
111
MMIOState *s = MMIO_IDE(obj);
112
113
- ide_bus_new(&s->bus, sizeof(s->bus), DEVICE(obj), 0, 2);
114
+ ide_bus_init(&s->bus, sizeof(s->bus), DEVICE(obj), 0, 2);
115
sysbus_init_irq(d, &s->irq);
116
}
117
118
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
119
index XXXXXXX..XXXXXXX 100644
120
--- a/hw/ide/piix.c
121
+++ b/hw/ide/piix.c
122
@@ -XXX,XX +XXX,XX @@ static int pci_piix_init_ports(PCIIDEState *d)
123
int i, ret;
124
125
for (i = 0; i < 2; i++) {
126
- ide_bus_new(&d->bus[i], sizeof(d->bus[i]), DEVICE(d), i, 2);
127
+ ide_bus_init(&d->bus[i], sizeof(d->bus[i]), DEVICE(d), i, 2);
128
ret = ide_init_ioport(&d->bus[i], NULL, port_info[i].iobase,
129
port_info[i].iobase2);
130
if (ret) {
131
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
132
index XXXXXXX..XXXXXXX 100644
133
--- a/hw/ide/qdev.c
134
+++ b/hw/ide/qdev.c
135
@@ -XXX,XX +XXX,XX @@ static const TypeInfo ide_bus_info = {
136
.class_init = ide_bus_class_init,
137
};
138
139
-void ide_bus_new(IDEBus *idebus, size_t idebus_size, DeviceState *dev,
140
+void ide_bus_init(IDEBus *idebus, size_t idebus_size, DeviceState *dev,
141
int bus_id, int max_units)
142
{
143
qbus_init(idebus, idebus_size, TYPE_IDE_BUS, dev, NULL);
144
diff --git a/hw/ide/sii3112.c b/hw/ide/sii3112.c
145
index XXXXXXX..XXXXXXX 100644
146
--- a/hw/ide/sii3112.c
147
+++ b/hw/ide/sii3112.c
148
@@ -XXX,XX +XXX,XX @@ static void sii3112_pci_realize(PCIDevice *dev, Error **errp)
149
150
qdev_init_gpio_in(ds, sii3112_set_irq, 2);
151
for (i = 0; i < 2; i++) {
152
- ide_bus_new(&s->bus[i], sizeof(s->bus[i]), ds, i, 1);
153
+ ide_bus_init(&s->bus[i], sizeof(s->bus[i]), ds, i, 1);
154
ide_init2(&s->bus[i], qdev_get_gpio_in(ds, i));
155
156
bmdma_init(&s->bus[i], &s->bmdma[i], s);
157
diff --git a/hw/ide/via.c b/hw/ide/via.c
158
index XXXXXXX..XXXXXXX 100644
159
--- a/hw/ide/via.c
160
+++ b/hw/ide/via.c
161
@@ -XXX,XX +XXX,XX @@ static void via_ide_realize(PCIDevice *dev, Error **errp)
162
163
qdev_init_gpio_in(ds, via_ide_set_irq, 2);
164
for (i = 0; i < 2; i++) {
165
- ide_bus_new(&d->bus[i], sizeof(d->bus[i]), ds, i, 2);
166
+ ide_bus_init(&d->bus[i], sizeof(d->bus[i]), ds, i, 2);
167
ide_init2(&d->bus[i], qdev_get_gpio_in(ds, i));
168
169
bmdma_init(&d->bus[i], &d->bmdma[i], d);
170
--
22
--
171
2.20.1
23
2.20.1
172
24
173
25
diff view generated by jsdifflib
1
Rename the pci_root_bus_new_inplace() function to
1
From: Leif Lindholm <leif@nuviainc.com>
2
pci_root_bus_init(); this brings the bus type in to line with a
3
"_init for in-place init, _new for allocate-and-return" convention.
4
To do this we need to rename the implementation-internal function
5
that was using the pci_root_bus_init() name to
6
pci_root_bus_internal_init().
7
2
3
SBSS -> SSBS
4
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
9
Message-id: 20210108185154.8108-2-leif@nuviainc.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
11
Message-id: 20210923121153.23754-4-peter.maydell@linaro.org
12
---
11
---
13
include/hw/pci/pci.h | 10 +++++-----
12
target/arm/cpu.h | 2 +-
14
hw/pci-host/raven.c | 4 ++--
13
1 file changed, 1 insertion(+), 1 deletion(-)
15
hw/pci-host/versatile.c | 6 +++---
16
hw/pci/pci.c | 26 +++++++++++++-------------
17
4 files changed, 23 insertions(+), 23 deletions(-)
18
14
19
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/pci/pci.h
17
--- a/target/arm/cpu.h
22
+++ b/include/hw/pci/pci.h
18
+++ b/target/arm/cpu.h
23
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(PCIBus, PCIBusClass, PCI_BUS)
19
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64PFR0, RAS, 28, 4)
24
20
FIELD(ID_AA64PFR0, SVE, 32, 4)
25
bool pci_bus_is_express(PCIBus *bus);
21
26
22
FIELD(ID_AA64PFR1, BT, 0, 4)
27
-void pci_root_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent,
23
-FIELD(ID_AA64PFR1, SBSS, 4, 4)
28
- const char *name,
24
+FIELD(ID_AA64PFR1, SSBS, 4, 4)
29
- MemoryRegion *address_space_mem,
25
FIELD(ID_AA64PFR1, MTE, 8, 4)
30
- MemoryRegion *address_space_io,
26
FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4)
31
- uint8_t devfn_min, const char *typename);
32
+void pci_root_bus_init(PCIBus *bus, size_t bus_size, DeviceState *parent,
33
+ const char *name,
34
+ MemoryRegion *address_space_mem,
35
+ MemoryRegion *address_space_io,
36
+ uint8_t devfn_min, const char *typename);
37
PCIBus *pci_root_bus_new(DeviceState *parent, const char *name,
38
MemoryRegion *address_space_mem,
39
MemoryRegion *address_space_io,
40
diff --git a/hw/pci-host/raven.c b/hw/pci-host/raven.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/pci-host/raven.c
43
+++ b/hw/pci-host/raven.c
44
@@ -XXX,XX +XXX,XX @@ static void raven_pcihost_initfn(Object *obj)
45
memory_region_add_subregion_overlap(address_space_mem, PCI_IO_BASE_ADDR,
46
&s->pci_io_non_contiguous, 1);
47
memory_region_add_subregion(address_space_mem, 0xc0000000, &s->pci_memory);
48
- pci_root_bus_new_inplace(&s->pci_bus, sizeof(s->pci_bus), DEVICE(obj), NULL,
49
- &s->pci_memory, &s->pci_io, 0, TYPE_PCI_BUS);
50
+ pci_root_bus_init(&s->pci_bus, sizeof(s->pci_bus), DEVICE(obj), NULL,
51
+ &s->pci_memory, &s->pci_io, 0, TYPE_PCI_BUS);
52
53
/* Bus master address space */
54
memory_region_init(&s->bm, obj, "bm-raven", 4 * GiB);
55
diff --git a/hw/pci-host/versatile.c b/hw/pci-host/versatile.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/hw/pci-host/versatile.c
58
+++ b/hw/pci-host/versatile.c
59
@@ -XXX,XX +XXX,XX @@ static void pci_vpb_realize(DeviceState *dev, Error **errp)
60
memory_region_init(&s->pci_io_space, OBJECT(s), "pci_io", 4 * GiB);
61
memory_region_init(&s->pci_mem_space, OBJECT(s), "pci_mem", 4 * GiB);
62
63
- pci_root_bus_new_inplace(&s->pci_bus, sizeof(s->pci_bus), dev, "pci",
64
- &s->pci_mem_space, &s->pci_io_space,
65
- PCI_DEVFN(11, 0), TYPE_PCI_BUS);
66
+ pci_root_bus_init(&s->pci_bus, sizeof(s->pci_bus), dev, "pci",
67
+ &s->pci_mem_space, &s->pci_io_space,
68
+ PCI_DEVFN(11, 0), TYPE_PCI_BUS);
69
h->bus = &s->pci_bus;
70
71
object_initialize(&s->pci_dev, sizeof(s->pci_dev), TYPE_VERSATILE_PCI_HOST);
72
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
73
index XXXXXXX..XXXXXXX 100644
74
--- a/hw/pci/pci.c
75
+++ b/hw/pci/pci.c
76
@@ -XXX,XX +XXX,XX @@ bool pci_bus_bypass_iommu(PCIBus *bus)
77
return host_bridge->bypass_iommu;
78
}
79
80
-static void pci_root_bus_init(PCIBus *bus, DeviceState *parent,
81
- MemoryRegion *address_space_mem,
82
- MemoryRegion *address_space_io,
83
- uint8_t devfn_min)
84
+static void pci_root_bus_internal_init(PCIBus *bus, DeviceState *parent,
85
+ MemoryRegion *address_space_mem,
86
+ MemoryRegion *address_space_io,
87
+ uint8_t devfn_min)
88
{
89
assert(PCI_FUNC(devfn_min) == 0);
90
bus->devfn_min = devfn_min;
91
@@ -XXX,XX +XXX,XX @@ bool pci_bus_is_express(PCIBus *bus)
92
return object_dynamic_cast(OBJECT(bus), TYPE_PCIE_BUS);
93
}
94
95
-void pci_root_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent,
96
- const char *name,
97
- MemoryRegion *address_space_mem,
98
- MemoryRegion *address_space_io,
99
- uint8_t devfn_min, const char *typename)
100
+void pci_root_bus_init(PCIBus *bus, size_t bus_size, DeviceState *parent,
101
+ const char *name,
102
+ MemoryRegion *address_space_mem,
103
+ MemoryRegion *address_space_io,
104
+ uint8_t devfn_min, const char *typename)
105
{
106
qbus_create_inplace(bus, bus_size, typename, parent, name);
107
- pci_root_bus_init(bus, parent, address_space_mem, address_space_io,
108
- devfn_min);
109
+ pci_root_bus_internal_init(bus, parent, address_space_mem,
110
+ address_space_io, devfn_min);
111
}
112
113
PCIBus *pci_root_bus_new(DeviceState *parent, const char *name,
114
@@ -XXX,XX +XXX,XX @@ PCIBus *pci_root_bus_new(DeviceState *parent, const char *name,
115
PCIBus *bus;
116
117
bus = PCI_BUS(qbus_create(typename, parent, name));
118
- pci_root_bus_init(bus, parent, address_space_mem, address_space_io,
119
- devfn_min);
120
+ pci_root_bus_internal_init(bus, parent, address_space_mem,
121
+ address_space_io, devfn_min);
122
return bus;
123
}
124
27
125
--
28
--
126
2.20.1
29
2.20.1
127
30
128
31
diff view generated by jsdifflib
1
From: Tong Ho <tong.ho@xilinx.com>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
Add BBRAM and eFUSE usage to the Xilinx Versal Virt board
3
The AArch64 view of CLIDR_EL1 extends the ICB field to include also bit
4
document.
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.
5
6
6
Signed-off-by: Tong Ho <tong.ho@xilinx.com>
7
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
7
Message-id: 20210917052400.1249094-10-tong.ho@xilinx.com
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
11
Message-id: 20210108185154.8108-3-leif@nuviainc.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
13
---
11
docs/system/arm/xlnx-versal-virt.rst | 49 ++++++++++++++++++++++++++++
14
target/arm/cpu.h | 2 +-
12
1 file changed, 49 insertions(+)
15
1 file changed, 1 insertion(+), 1 deletion(-)
13
16
14
diff --git a/docs/system/arm/xlnx-versal-virt.rst b/docs/system/arm/xlnx-versal-virt.rst
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/docs/system/arm/xlnx-versal-virt.rst
19
--- a/target/arm/cpu.h
17
+++ b/docs/system/arm/xlnx-versal-virt.rst
20
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@ Implemented devices:
21
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
19
- OCM (256KB of On Chip Memory)
22
uint32_t id_afr0;
20
- XRAM (4MB of on chip Accelerator RAM)
23
uint64_t id_aa64afr0;
21
- DDR memory
24
uint64_t id_aa64afr1;
22
+- BBRAM (36 bytes of Battery-backed RAM)
25
- uint32_t clidr;
23
+- eFUSE (3072 bytes of one-time field-programmable bit array)
26
+ uint64_t clidr;
24
27
uint64_t mp_affinity; /* MP ID without feature bits */
25
QEMU does not yet model any other devices, including the PL and the AI Engine.
28
/* The elements of this array are the CCSIDR values for each cache,
26
29
* in the order L1DCache, L1ICache, L2DCache, L2ICache, etc.
27
@@ -XXX,XX +XXX,XX @@ Run the following at the U-Boot prompt:
28
fdt set /chosen/dom0 reg <0x00000000 0x40000000 0x0 0x03100000>
29
booti 30000000 - 20000000
30
31
+BBRAM File Backend
32
+""""""""""""""""""
33
+BBRAM can have an optional file backend, which must be a seekable
34
+binary file with a size of 36 bytes or larger. A file with all
35
+binary 0s is a 'blank'.
36
+
37
+To add a file-backend for the BBRAM:
38
+
39
+.. code-block:: bash
40
+
41
+ -drive if=pflash,index=0,file=versal-bbram.bin,format=raw
42
+
43
+To use a different index value, N, from default of 0, add:
44
+
45
+.. code-block:: bash
46
+
47
+ -global xlnx,bbram-ctrl.drive-index=N
48
+
49
+eFUSE File Backend
50
+""""""""""""""""""
51
+eFUSE can have an optional file backend, which must be a seekable
52
+binary file with a size of 3072 bytes or larger. A file with all
53
+binary 0s is a 'blank'.
54
+
55
+To add a file-backend for the eFUSE:
56
+
57
+.. code-block:: bash
58
+
59
+ -drive if=pflash,index=1,file=versal-efuse.bin,format=raw
60
+
61
+To use a different index value, N, from default of 1, add:
62
+
63
+.. code-block:: bash
64
+
65
+ -global xlnx,efuse.drive-index=N
66
+
67
+.. warning::
68
+ In actual physical Versal, BBRAM and eFUSE contain sensitive data.
69
+ The QEMU device models do **not** encrypt nor obfuscate any data
70
+ when holding them in models' memory or when writing them to their
71
+ file backends.
72
+
73
+ Thus, a file backend should be used with caution, and 'format=luks'
74
+ is highly recommended (albeit with usage complexity).
75
+
76
+ Better yet, do not use actual product data when running guest image
77
+ on this Xilinx Versal Virt board.
78
--
30
--
79
2.20.1
31
2.20.1
80
32
81
33
diff view generated by jsdifflib
1
From: Alexander Graf <agraf@csgraf.de>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
The Allwinner H3 SoC uses Cortex-A7 cores which support virtualization.
3
When FEAT_MTE is implemented, the AArch64 view of CTR_EL0 adds the
4
However, today we are configuring QEMU to use HVC as PSCI conduit.
4
TminLine field in bits [37:32].
5
Extend the ctr field to be able to hold this context.
5
6
6
That means HVC calls get trapped into QEMU instead of the guest's own
7
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
7
emulated CPU and thus break the guest's ability to execute virtualization.
8
Reviewed-by: Hao Wu <wuhaotsh@google.com>
8
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Fix this by moving to SMC as conduit, freeing up HYP completely to the VM.
10
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
10
11
Message-id: 20210108185154.8108-4-leif@nuviainc.com
11
Signed-off-by: Alexander Graf <agraf@csgraf.de>
12
Message-id: 20210920203931.66527-1-agraf@csgraf.de
13
Fixes: 740dafc0ba0 ("hw/arm: add Allwinner H3 System-on-Chip")
14
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
15
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
13
---
20
hw/arm/allwinner-h3.c | 2 +-
14
target/arm/cpu.h | 2 +-
21
1 file changed, 1 insertion(+), 1 deletion(-)
15
1 file changed, 1 insertion(+), 1 deletion(-)
22
16
23
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
24
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/arm/allwinner-h3.c
19
--- a/target/arm/cpu.h
26
+++ b/hw/arm/allwinner-h3.c
20
+++ b/target/arm/cpu.h
27
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
21
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
28
22
uint64_t midr;
29
/* Provide Power State Coordination Interface */
23
uint32_t revidr;
30
qdev_prop_set_int32(DEVICE(&s->cpus[i]), "psci-conduit",
24
uint32_t reset_fpsid;
31
- QEMU_PSCI_CONDUIT_HVC);
25
- uint32_t ctr;
32
+ QEMU_PSCI_CONDUIT_SMC);
26
+ uint64_t ctr;
33
27
uint32_t reset_sctlr;
34
/* Disable secondary CPUs */
28
uint64_t pmceid0;
35
qdev_prop_set_bit(DEVICE(&s->cpus[i]), "start-powered-off",
29
uint64_t pmceid1;
36
--
30
--
37
2.20.1
31
2.20.1
38
32
39
33
diff view generated by jsdifflib
1
From: Tong Ho <tong.ho@xilinx.com>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
Connect the support for ZynqMP eFUSE one-time field-programmable
3
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
4
bit array.
4
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
5
5
Message-id: 20210108185154.8108-5-leif@nuviainc.com
6
The command argument:
7
-drive if=pflash,index=3,...
8
Can be used to optionally connect the bit array to a
9
backend storage, such that field-programmed values
10
in one invocation can be made available to next
11
invocation.
12
13
The backend storage must be a seekable binary file, and
14
its size must be 768 bytes or larger. A file with all
15
binary 0's is a 'blank'.
16
17
Signed-off-by: Tong Ho <tong.ho@xilinx.com>
18
Message-id: 20210917052400.1249094-9-tong.ho@xilinx.com
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
7
---
22
include/hw/arm/xlnx-zynqmp.h | 3 +++
8
target/arm/cpu.h | 31 +++++++++++++++++++++++++++++++
23
hw/arm/xlnx-zcu102.c | 15 +++++++++++++++
9
1 file changed, 31 insertions(+)
24
hw/arm/xlnx-zynqmp.c | 29 +++++++++++++++++++++++++++++
25
hw/Kconfig | 1 +
26
4 files changed, 48 insertions(+)
27
10
28
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
11
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
29
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
30
--- a/include/hw/arm/xlnx-zynqmp.h
13
--- a/target/arm/cpu.h
31
+++ b/include/hw/arm/xlnx-zynqmp.h
14
+++ b/target/arm/cpu.h
32
@@ -XXX,XX +XXX,XX @@
15
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_FPCCR, ASPEN, 31, 1)
33
#include "net/can_emu.h"
16
/*
34
#include "hw/dma/xlnx_csu_dma.h"
17
* System register ID fields.
35
#include "hw/nvram/xlnx-bbram.h"
18
*/
36
+#include "hw/nvram/xlnx-zynqmp-efuse.h"
19
+FIELD(CLIDR_EL1, CTYPE1, 0, 3)
37
20
+FIELD(CLIDR_EL1, CTYPE2, 3, 3)
38
#define TYPE_XLNX_ZYNQMP "xlnx-zynqmp"
21
+FIELD(CLIDR_EL1, CTYPE3, 6, 3)
39
OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
22
+FIELD(CLIDR_EL1, CTYPE4, 9, 3)
40
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
23
+FIELD(CLIDR_EL1, CTYPE5, 12, 3)
41
MemoryRegion *ddr_ram;
24
+FIELD(CLIDR_EL1, CTYPE6, 15, 3)
42
MemoryRegion ddr_ram_low, ddr_ram_high;
25
+FIELD(CLIDR_EL1, CTYPE7, 18, 3)
43
XlnxBBRam bbram;
26
+FIELD(CLIDR_EL1, LOUIS, 21, 3)
44
+ XlnxEFuse efuse;
27
+FIELD(CLIDR_EL1, LOC, 24, 3)
45
+ XlnxZynqMPEFuse efuse_ctrl;
28
+FIELD(CLIDR_EL1, LOUU, 27, 3)
46
29
+FIELD(CLIDR_EL1, ICB, 30, 3)
47
MemoryRegion mr_unimp[XLNX_ZYNQMP_NUM_UNIMP_AREAS];
48
49
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/arm/xlnx-zcu102.c
52
+++ b/hw/arm/xlnx-zcu102.c
53
@@ -XXX,XX +XXX,XX @@ static void bbram_attach_drive(XlnxBBRam *dev)
54
}
55
}
56
57
+static void efuse_attach_drive(XlnxEFuse *dev)
58
+{
59
+ DriveInfo *dinfo;
60
+ BlockBackend *blk;
61
+
30
+
62
+ dinfo = drive_get_by_index(IF_PFLASH, 3);
31
+/* When FEAT_CCIDX is implemented */
63
+ blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
32
+FIELD(CCSIDR_EL1, CCIDX_LINESIZE, 0, 3)
64
+ if (blk) {
33
+FIELD(CCSIDR_EL1, CCIDX_ASSOCIATIVITY, 3, 21)
65
+ qdev_prop_set_drive(DEVICE(dev), "drive", blk);
34
+FIELD(CCSIDR_EL1, CCIDX_NUMSETS, 32, 24)
66
+ }
67
+}
68
+
35
+
69
static void xlnx_zcu102_init(MachineState *machine)
36
+/* When FEAT_CCIDX is not implemented */
70
{
37
+FIELD(CCSIDR_EL1, LINESIZE, 0, 3)
71
XlnxZCU102 *s = ZCU102_MACHINE(machine);
38
+FIELD(CCSIDR_EL1, ASSOCIATIVITY, 3, 10)
72
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_init(MachineState *machine)
39
+FIELD(CCSIDR_EL1, NUMSETS, 13, 15)
73
/* Attach bbram backend, if given */
74
bbram_attach_drive(&s->soc.bbram);
75
76
+ /* Attach efuse backend, if given */
77
+ efuse_attach_drive(&s->soc.efuse);
78
+
40
+
79
/* Create and plug in the SD cards */
41
+FIELD(CTR_EL0, IMINLINE, 0, 4)
80
for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
42
+FIELD(CTR_EL0, L1IP, 14, 2)
81
BusState *bus;
43
+FIELD(CTR_EL0, DMINLINE, 16, 4)
82
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
44
+FIELD(CTR_EL0, ERG, 20, 4)
83
index XXXXXXX..XXXXXXX 100644
45
+FIELD(CTR_EL0, CWG, 24, 4)
84
--- a/hw/arm/xlnx-zynqmp.c
46
+FIELD(CTR_EL0, IDC, 28, 1)
85
+++ b/hw/arm/xlnx-zynqmp.c
47
+FIELD(CTR_EL0, DIC, 29, 1)
86
@@ -XXX,XX +XXX,XX @@
48
+FIELD(CTR_EL0, TMINLINE, 32, 6)
87
#define BBRAM_ADDR 0xffcd0000
88
#define BBRAM_IRQ 11
89
90
+#define EFUSE_ADDR 0xffcc0000
91
+#define EFUSE_IRQ 87
92
+
49
+
93
#define SDHCI_CAPABILITIES 0x280737ec6481 /* Datasheet: UG1085 (v1.7) */
50
FIELD(MIDR_EL1, REVISION, 0, 4)
94
51
FIELD(MIDR_EL1, PARTNUM, 4, 12)
95
static const uint64_t gem_addr[XLNX_ZYNQMP_NUM_GEMS] = {
52
FIELD(MIDR_EL1, ARCHITECTURE, 16, 4)
96
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_create_bbram(XlnxZynqMPState *s, qemu_irq *gic)
97
sysbus_connect_irq(sbd, 0, gic[BBRAM_IRQ]);
98
}
99
100
+static void xlnx_zynqmp_create_efuse(XlnxZynqMPState *s, qemu_irq *gic)
101
+{
102
+ Object *bits = OBJECT(&s->efuse);
103
+ Object *ctrl = OBJECT(&s->efuse_ctrl);
104
+ SysBusDevice *sbd;
105
+
106
+ object_initialize_child(OBJECT(s), "efuse-ctrl", &s->efuse_ctrl,
107
+ TYPE_XLNX_ZYNQMP_EFUSE);
108
+
109
+ object_initialize_child_with_props(ctrl, "xlnx-efuse@0", bits,
110
+ sizeof(s->efuse),
111
+ TYPE_XLNX_EFUSE, &error_abort,
112
+ "efuse-nr", "3",
113
+ "efuse-size", "2048",
114
+ NULL);
115
+
116
+ qdev_realize(DEVICE(bits), NULL, &error_abort);
117
+ object_property_set_link(ctrl, "efuse", bits, &error_abort);
118
+
119
+ sbd = SYS_BUS_DEVICE(ctrl);
120
+ sysbus_realize(sbd, &error_abort);
121
+ sysbus_mmio_map(sbd, 0, EFUSE_ADDR);
122
+ sysbus_connect_irq(sbd, 0, gic[EFUSE_IRQ]);
123
+}
124
+
125
static void xlnx_zynqmp_create_unimp_mmio(XlnxZynqMPState *s)
126
{
127
static const struct UnimpInfo {
128
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
129
sysbus_connect_irq(SYS_BUS_DEVICE(&s->rtc), 0, gic_spi[RTC_IRQ]);
130
131
xlnx_zynqmp_create_bbram(s, gic_spi);
132
+ xlnx_zynqmp_create_efuse(s, gic_spi);
133
xlnx_zynqmp_create_unimp_mmio(s);
134
135
for (i = 0; i < XLNX_ZYNQMP_NUM_GDMA_CH; i++) {
136
diff --git a/hw/Kconfig b/hw/Kconfig
137
index XXXXXXX..XXXXXXX 100644
138
--- a/hw/Kconfig
139
+++ b/hw/Kconfig
140
@@ -XXX,XX +XXX,XX @@ config XLNX_ZYNQMP
141
select CAN_BUS
142
select PTIMER
143
select XLNX_BBRAM
144
+ select XLNX_EFUSE_ZYNQMP
145
--
53
--
146
2.20.1
54
2.20.1
147
55
148
56
diff view generated by jsdifflib
1
From: Tong Ho <tong.ho@xilinx.com>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
Connect the support for Xilinx ZynqMP Battery-Backed RAM (BBRAM)
3
Add entries present in ARM DDI 0487F.c (August 2020).
4
4
5
The command argument:
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
6
-drive if=pflash,index=2,...
7
Can be used to optionally connect the bbram to a backend
8
storage, such that field-programmed values in one
9
invocation can be made available to next invocation.
10
11
The backend storage must be a seekable binary file, and
12
its size must be 36 bytes or larger. A file with all
13
binary 0's is a 'blank'.
14
15
Signed-off-by: Tong Ho <tong.ho@xilinx.com>
16
Message-id: 20210917052400.1249094-8-tong.ho@xilinx.com
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
8
Message-id: 20210108185154.8108-6-leif@nuviainc.com
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
10
---
20
include/hw/arm/xlnx-zynqmp.h | 2 ++
11
target/arm/cpu.h | 15 +++++++++++++++
21
hw/arm/xlnx-zcu102.c | 15 +++++++++++++++
12
1 file changed, 15 insertions(+)
22
hw/arm/xlnx-zynqmp.c | 20 ++++++++++++++++++++
23
hw/Kconfig | 1 +
24
4 files changed, 38 insertions(+)
25
13
26
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
27
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
28
--- a/include/hw/arm/xlnx-zynqmp.h
16
--- a/target/arm/cpu.h
29
+++ b/include/hw/arm/xlnx-zynqmp.h
17
+++ b/target/arm/cpu.h
30
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64ISAR1, GPI, 28, 4)
31
#include "qom/object.h"
19
FIELD(ID_AA64ISAR1, FRINTTS, 32, 4)
32
#include "net/can_emu.h"
20
FIELD(ID_AA64ISAR1, SB, 36, 4)
33
#include "hw/dma/xlnx_csu_dma.h"
21
FIELD(ID_AA64ISAR1, SPECRES, 40, 4)
34
+#include "hw/nvram/xlnx-bbram.h"
22
+FIELD(ID_AA64ISAR1, BF16, 44, 4)
35
23
+FIELD(ID_AA64ISAR1, DGH, 48, 4)
36
#define TYPE_XLNX_ZYNQMP "xlnx-zynqmp"
24
+FIELD(ID_AA64ISAR1, I8MM, 52, 4)
37
OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
25
38
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
26
FIELD(ID_AA64PFR0, EL0, 0, 4)
39
27
FIELD(ID_AA64PFR0, EL1, 4, 4)
40
MemoryRegion *ddr_ram;
28
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64PFR0, ADVSIMD, 20, 4)
41
MemoryRegion ddr_ram_low, ddr_ram_high;
29
FIELD(ID_AA64PFR0, GIC, 24, 4)
42
+ XlnxBBRam bbram;
30
FIELD(ID_AA64PFR0, RAS, 28, 4)
43
31
FIELD(ID_AA64PFR0, SVE, 32, 4)
44
MemoryRegion mr_unimp[XLNX_ZYNQMP_NUM_UNIMP_AREAS];
32
+FIELD(ID_AA64PFR0, SEL2, 36, 4)
45
33
+FIELD(ID_AA64PFR0, MPAM, 40, 4)
46
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
34
+FIELD(ID_AA64PFR0, AMU, 44, 4)
47
index XXXXXXX..XXXXXXX 100644
35
+FIELD(ID_AA64PFR0, DIT, 48, 4)
48
--- a/hw/arm/xlnx-zcu102.c
36
+FIELD(ID_AA64PFR0, CSV2, 56, 4)
49
+++ b/hw/arm/xlnx-zcu102.c
37
+FIELD(ID_AA64PFR0, CSV3, 60, 4)
50
@@ -XXX,XX +XXX,XX @@ static void zcu102_modify_dtb(const struct arm_boot_info *binfo, void *fdt)
38
51
}
39
FIELD(ID_AA64PFR1, BT, 0, 4)
52
}
40
FIELD(ID_AA64PFR1, SSBS, 4, 4)
53
41
FIELD(ID_AA64PFR1, MTE, 8, 4)
54
+static void bbram_attach_drive(XlnxBBRam *dev)
42
FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4)
55
+{
43
+FIELD(ID_AA64PFR1, MPAM_FRAC, 16, 4)
56
+ DriveInfo *dinfo;
44
57
+ BlockBackend *blk;
45
FIELD(ID_AA64MMFR0, PARANGE, 0, 4)
58
+
46
FIELD(ID_AA64MMFR0, ASIDBITS, 4, 4)
59
+ dinfo = drive_get_by_index(IF_PFLASH, 2);
47
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64MMFR0, TGRAN16_2, 32, 4)
60
+ blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
48
FIELD(ID_AA64MMFR0, TGRAN64_2, 36, 4)
61
+ if (blk) {
49
FIELD(ID_AA64MMFR0, TGRAN4_2, 40, 4)
62
+ qdev_prop_set_drive(DEVICE(dev), "drive", blk);
50
FIELD(ID_AA64MMFR0, EXS, 44, 4)
63
+ }
51
+FIELD(ID_AA64MMFR0, FGT, 56, 4)
64
+}
52
+FIELD(ID_AA64MMFR0, ECV, 60, 4)
65
+
53
66
static void xlnx_zcu102_init(MachineState *machine)
54
FIELD(ID_AA64MMFR1, HAFDBS, 0, 4)
67
{
55
FIELD(ID_AA64MMFR1, VMIDBITS, 4, 4)
68
XlnxZCU102 *s = ZCU102_MACHINE(machine);
56
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64MMFR1, LO, 16, 4)
69
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_init(MachineState *machine)
57
FIELD(ID_AA64MMFR1, PAN, 20, 4)
70
58
FIELD(ID_AA64MMFR1, SPECSEI, 24, 4)
71
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
59
FIELD(ID_AA64MMFR1, XNX, 28, 4)
72
60
+FIELD(ID_AA64MMFR1, TWED, 32, 4)
73
+ /* Attach bbram backend, if given */
61
+FIELD(ID_AA64MMFR1, ETS, 36, 4)
74
+ bbram_attach_drive(&s->soc.bbram);
62
75
+
63
FIELD(ID_AA64MMFR2, CNP, 0, 4)
76
/* Create and plug in the SD cards */
64
FIELD(ID_AA64MMFR2, UAO, 4, 4)
77
for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
65
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64DFR0, CTX_CMPS, 28, 4)
78
BusState *bus;
66
FIELD(ID_AA64DFR0, PMSVER, 32, 4)
79
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
67
FIELD(ID_AA64DFR0, DOUBLELOCK, 36, 4)
80
index XXXXXXX..XXXXXXX 100644
68
FIELD(ID_AA64DFR0, TRACEFILT, 40, 4)
81
--- a/hw/arm/xlnx-zynqmp.c
69
+FIELD(ID_AA64DFR0, MTPMU, 48, 4)
82
+++ b/hw/arm/xlnx-zynqmp.c
70
83
@@ -XXX,XX +XXX,XX @@
71
FIELD(ID_DFR0, COPDBG, 0, 4)
84
#define RTC_ADDR 0xffa60000
72
FIELD(ID_DFR0, COPSDBG, 4, 4)
85
#define RTC_IRQ 26
86
87
+#define BBRAM_ADDR 0xffcd0000
88
+#define BBRAM_IRQ 11
89
+
90
#define SDHCI_CAPABILITIES 0x280737ec6481 /* Datasheet: UG1085 (v1.7) */
91
92
static const uint64_t gem_addr[XLNX_ZYNQMP_NUM_GEMS] = {
93
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_create_rpu(MachineState *ms, XlnxZynqMPState *s,
94
qdev_realize(DEVICE(&s->rpu_cluster), NULL, &error_fatal);
95
}
96
97
+static void xlnx_zynqmp_create_bbram(XlnxZynqMPState *s, qemu_irq *gic)
98
+{
99
+ SysBusDevice *sbd;
100
+
101
+ object_initialize_child_with_props(OBJECT(s), "bbram", &s->bbram,
102
+ sizeof(s->bbram), TYPE_XLNX_BBRAM,
103
+ &error_fatal,
104
+ "crc-zpads", "1",
105
+ NULL);
106
+ sbd = SYS_BUS_DEVICE(&s->bbram);
107
+
108
+ sysbus_realize(sbd, &error_fatal);
109
+ sysbus_mmio_map(sbd, 0, BBRAM_ADDR);
110
+ sysbus_connect_irq(sbd, 0, gic[BBRAM_IRQ]);
111
+}
112
+
113
static void xlnx_zynqmp_create_unimp_mmio(XlnxZynqMPState *s)
114
{
115
static const struct UnimpInfo {
116
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
117
sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, RTC_ADDR);
118
sysbus_connect_irq(SYS_BUS_DEVICE(&s->rtc), 0, gic_spi[RTC_IRQ]);
119
120
+ xlnx_zynqmp_create_bbram(s, gic_spi);
121
xlnx_zynqmp_create_unimp_mmio(s);
122
123
for (i = 0; i < XLNX_ZYNQMP_NUM_GDMA_CH; i++) {
124
diff --git a/hw/Kconfig b/hw/Kconfig
125
index XXXXXXX..XXXXXXX 100644
126
--- a/hw/Kconfig
127
+++ b/hw/Kconfig
128
@@ -XXX,XX +XXX,XX @@ config XLNX_ZYNQMP
129
select REGISTER
130
select CAN_BUS
131
select PTIMER
132
+ select XLNX_BBRAM
133
--
73
--
134
2.20.1
74
2.20.1
135
75
136
76
diff view generated by jsdifflib
1
From: Tong Ho <tong.ho@xilinx.com>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
Connect the support for Versal eFUSE one-time field-programmable
3
Add entries present in ARM DDI 0487F.c (August 2020).
4
bit array.
5
4
6
The command argument:
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
7
-drive if=pflash,index=1,...
8
Can be used to optionally connect the bit array to a
9
backend storage, such that field-programmed values
10
in one invocation can be made available to next
11
invocation.
12
13
The backend storage must be a seekable binary file, and
14
its size must be 3072 bytes or larger. A file with all
15
binary 0's is a 'blank'.
16
17
Signed-off-by: Tong Ho <tong.ho@xilinx.com>
18
Message-id: 20210917052400.1249094-7-tong.ho@xilinx.com
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
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
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
10
---
22
include/hw/arm/xlnx-versal.h | 10 +++++++
11
target/arm/cpu.h | 28 ++++++++++++++++++++++++++++
23
hw/arm/xlnx-versal-virt.c | 52 ++++++++++++++++++++++++++++++++++++
12
1 file changed, 28 insertions(+)
24
hw/arm/xlnx-versal.c | 39 +++++++++++++++++++++++++++
25
hw/arm/Kconfig | 1 +
26
4 files changed, 102 insertions(+)
27
13
28
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
29
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
30
--- a/include/hw/arm/xlnx-versal.h
16
--- a/target/arm/cpu.h
31
+++ b/include/hw/arm/xlnx-versal.h
17
+++ b/target/arm/cpu.h
32
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ FIELD(ID_ISAR6, DP, 4, 4)
33
#include "hw/usb/xlnx-usb-subsystem.h"
19
FIELD(ID_ISAR6, FHM, 8, 4)
34
#include "hw/misc/xlnx-versal-xramc.h"
20
FIELD(ID_ISAR6, SB, 12, 4)
35
#include "hw/nvram/xlnx-bbram.h"
21
FIELD(ID_ISAR6, SPECRES, 16, 4)
36
+#include "hw/nvram/xlnx-versal-efuse.h"
22
+FIELD(ID_ISAR6, BF16, 20, 4)
37
23
+FIELD(ID_ISAR6, I8MM, 24, 4)
38
#define TYPE_XLNX_VERSAL "xlnx-versal"
24
39
OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
25
FIELD(ID_MMFR0, VMSA, 0, 4)
40
@@ -XXX,XX +XXX,XX @@ struct Versal {
26
FIELD(ID_MMFR0, PMSA, 4, 4)
41
27
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR0, AUXREG, 20, 4)
42
XlnxZynqMPRTC rtc;
28
FIELD(ID_MMFR0, FCSE, 24, 4)
43
XlnxBBRam bbram;
29
FIELD(ID_MMFR0, INNERSHR, 28, 4)
44
+ XlnxEFuse efuse;
30
45
+ XlnxVersalEFuseCtrl efuse_ctrl;
31
+FIELD(ID_MMFR1, L1HVDVA, 0, 4)
46
+ XlnxVersalEFuseCache efuse_cache;
32
+FIELD(ID_MMFR1, L1UNIVA, 4, 4)
47
} pmc;
33
+FIELD(ID_MMFR1, L1HVDSW, 8, 4)
48
34
+FIELD(ID_MMFR1, L1UNISW, 12, 4)
49
struct {
35
+FIELD(ID_MMFR1, L1HVD, 16, 4)
50
@@ -XXX,XX +XXX,XX @@ struct Versal {
36
+FIELD(ID_MMFR1, L1UNI, 20, 4)
51
#define VERSAL_BBRAM_APB_IRQ_0 121
37
+FIELD(ID_MMFR1, L1TSTCLN, 24, 4)
52
#define VERSAL_RTC_APB_ERR_IRQ 121
38
+FIELD(ID_MMFR1, BPRED, 28, 4)
53
#define VERSAL_SD0_IRQ_0 126
54
+#define VERSAL_EFUSE_IRQ 139
55
#define VERSAL_RTC_ALARM_IRQ 142
56
#define VERSAL_RTC_SECONDS_IRQ 143
57
58
@@ -XXX,XX +XXX,XX @@ struct Versal {
59
#define MM_PMC_SD0_SIZE 0x10000
60
#define MM_PMC_BBRAM_CTRL 0xf11f0000
61
#define MM_PMC_BBRAM_CTRL_SIZE 0x00050
62
+#define MM_PMC_EFUSE_CTRL 0xf1240000
63
+#define MM_PMC_EFUSE_CTRL_SIZE 0x00104
64
+#define MM_PMC_EFUSE_CACHE 0xf1250000
65
+#define MM_PMC_EFUSE_CACHE_SIZE 0x00C00
66
+
39
+
67
#define MM_PMC_CRP 0xf1260000U
40
+FIELD(ID_MMFR2, L1HVDFG, 0, 4)
68
#define MM_PMC_CRP_SIZE 0x10000
41
+FIELD(ID_MMFR2, L1HVDBG, 4, 4)
69
#define MM_PMC_RTC 0xf12a0000
42
+FIELD(ID_MMFR2, L1HVDRNG, 8, 4)
70
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
43
+FIELD(ID_MMFR2, HVDTLB, 12, 4)
71
index XXXXXXX..XXXXXXX 100644
44
+FIELD(ID_MMFR2, UNITLB, 16, 4)
72
--- a/hw/arm/xlnx-versal-virt.c
45
+FIELD(ID_MMFR2, MEMBARR, 20, 4)
73
+++ b/hw/arm/xlnx-versal-virt.c
46
+FIELD(ID_MMFR2, WFISTALL, 24, 4)
74
@@ -XXX,XX +XXX,XX @@ static void fdt_add_bbram_node(VersalVirt *s)
47
+FIELD(ID_MMFR2, HWACCFLG, 28, 4)
75
g_free(name);
76
}
77
78
+static void fdt_add_efuse_ctrl_node(VersalVirt *s)
79
+{
80
+ const char compat[] = TYPE_XLNX_VERSAL_EFUSE_CTRL;
81
+ const char interrupt_names[] = "pmc_efuse";
82
+ char *name = g_strdup_printf("/pmc_efuse@%x", MM_PMC_EFUSE_CTRL);
83
+
48
+
84
+ qemu_fdt_add_subnode(s->fdt, name);
49
FIELD(ID_MMFR3, CMAINTVA, 0, 4)
50
FIELD(ID_MMFR3, CMAINTSW, 4, 4)
51
FIELD(ID_MMFR3, BPMAINT, 8, 4)
52
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR4, LSM, 20, 4)
53
FIELD(ID_MMFR4, CCIDX, 24, 4)
54
FIELD(ID_MMFR4, EVT, 28, 4)
55
56
+FIELD(ID_MMFR5, ETS, 0, 4)
85
+
57
+
86
+ qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
58
FIELD(ID_PFR0, STATE0, 0, 4)
87
+ GIC_FDT_IRQ_TYPE_SPI, VERSAL_EFUSE_IRQ,
59
FIELD(ID_PFR0, STATE1, 4, 4)
88
+ GIC_FDT_IRQ_FLAGS_LEVEL_HI);
60
FIELD(ID_PFR0, STATE2, 8, 4)
89
+ qemu_fdt_setprop(s->fdt, name, "interrupt-names",
61
@@ -XXX,XX +XXX,XX @@ FIELD(ID_PFR1, SEC_FRAC, 20, 4)
90
+ interrupt_names, sizeof(interrupt_names));
62
FIELD(ID_PFR1, VIRT_FRAC, 24, 4)
91
+ qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
63
FIELD(ID_PFR1, GIC, 28, 4)
92
+ 2, MM_PMC_EFUSE_CTRL,
64
93
+ 2, MM_PMC_EFUSE_CTRL_SIZE);
65
+FIELD(ID_PFR2, CSV3, 0, 4)
94
+ qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
66
+FIELD(ID_PFR2, SSBS, 4, 4)
95
+ g_free(name);
67
+FIELD(ID_PFR2, RAS_FRAC, 8, 4)
96
+}
97
+
68
+
98
+static void fdt_add_efuse_cache_node(VersalVirt *s)
69
FIELD(ID_AA64ISAR0, AES, 4, 4)
99
+{
70
FIELD(ID_AA64ISAR0, SHA1, 8, 4)
100
+ const char compat[] = TYPE_XLNX_VERSAL_EFUSE_CACHE;
71
FIELD(ID_AA64ISAR0, SHA2, 12, 4)
101
+ char *name = g_strdup_printf("/xlnx_pmc_efuse_cache@%x",
72
@@ -XXX,XX +XXX,XX @@ FIELD(ID_DFR0, MPROFDBG, 20, 4)
102
+ MM_PMC_EFUSE_CACHE);
73
FIELD(ID_DFR0, PERFMON, 24, 4)
74
FIELD(ID_DFR0, TRACEFILT, 28, 4)
75
76
+FIELD(ID_DFR1, MTPMU, 0, 4)
103
+
77
+
104
+ qemu_fdt_add_subnode(s->fdt, name);
78
FIELD(DBGDIDR, SE_IMP, 12, 1)
105
+
79
FIELD(DBGDIDR, NSUHD_IMP, 14, 1)
106
+ qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
80
FIELD(DBGDIDR, VERSION, 16, 4)
107
+ 2, MM_PMC_EFUSE_CACHE,
108
+ 2, MM_PMC_EFUSE_CACHE_SIZE);
109
+ qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
110
+ g_free(name);
111
+}
112
+
113
static void fdt_nop_memory_nodes(void *fdt, Error **errp)
114
{
115
Error *err = NULL;
116
@@ -XXX,XX +XXX,XX @@ static void bbram_attach_drive(XlnxBBRam *dev)
117
}
118
}
119
120
+static void efuse_attach_drive(XlnxEFuse *dev)
121
+{
122
+ DriveInfo *dinfo;
123
+ BlockBackend *blk;
124
+
125
+ dinfo = drive_get_by_index(IF_PFLASH, 1);
126
+ blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
127
+ if (blk) {
128
+ qdev_prop_set_drive(DEVICE(dev), "drive", blk);
129
+ }
130
+}
131
+
132
static void sd_plugin_card(SDHCIState *sd, DriveInfo *di)
133
{
134
BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL;
135
@@ -XXX,XX +XXX,XX @@ static void versal_virt_init(MachineState *machine)
136
fdt_add_sd_nodes(s);
137
fdt_add_rtc_node(s);
138
fdt_add_bbram_node(s);
139
+ fdt_add_efuse_ctrl_node(s);
140
+ fdt_add_efuse_cache_node(s);
141
fdt_add_cpu_nodes(s, psci_conduit);
142
fdt_add_clk_node(s, "/clk125", 125000000, s->phandle.clk_125Mhz);
143
fdt_add_clk_node(s, "/clk25", 25000000, s->phandle.clk_25Mhz);
144
@@ -XXX,XX +XXX,XX @@ static void versal_virt_init(MachineState *machine)
145
/* Attach bbram backend, if given */
146
bbram_attach_drive(&s->soc.pmc.bbram);
147
148
+ /* Attach efuse backend, if given */
149
+ efuse_attach_drive(&s->soc.pmc.efuse);
150
+
151
/* Plugin SD cards. */
152
for (i = 0; i < ARRAY_SIZE(s->soc.pmc.iou.sd); i++) {
153
sd_plugin_card(&s->soc.pmc.iou.sd[i], drive_get_next(IF_SD));
154
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
155
index XXXXXXX..XXXXXXX 100644
156
--- a/hw/arm/xlnx-versal.c
157
+++ b/hw/arm/xlnx-versal.c
158
@@ -XXX,XX +XXX,XX @@ static void versal_create_bbram(Versal *s, qemu_irq *pic)
159
sysbus_connect_irq(sbd, 0, pic[VERSAL_BBRAM_APB_IRQ_0]);
160
}
161
162
+static void versal_realize_efuse_part(Versal *s, Object *dev, hwaddr base)
163
+{
164
+ SysBusDevice *part = SYS_BUS_DEVICE(dev);
165
+
166
+ object_property_set_link(OBJECT(part), "efuse",
167
+ OBJECT(&s->pmc.efuse), &error_abort);
168
+
169
+ sysbus_realize(part, &error_abort);
170
+ memory_region_add_subregion(&s->mr_ps, base,
171
+ sysbus_mmio_get_region(part, 0));
172
+}
173
+
174
+static void versal_create_efuse(Versal *s, qemu_irq *pic)
175
+{
176
+ Object *bits = OBJECT(&s->pmc.efuse);
177
+ Object *ctrl = OBJECT(&s->pmc.efuse_ctrl);
178
+ Object *cache = OBJECT(&s->pmc.efuse_cache);
179
+
180
+ object_initialize_child(OBJECT(s), "efuse-ctrl", &s->pmc.efuse_ctrl,
181
+ TYPE_XLNX_VERSAL_EFUSE_CTRL);
182
+
183
+ object_initialize_child(OBJECT(s), "efuse-cache", &s->pmc.efuse_cache,
184
+ TYPE_XLNX_VERSAL_EFUSE_CACHE);
185
+
186
+ object_initialize_child_with_props(ctrl, "xlnx-efuse@0", bits,
187
+ sizeof(s->pmc.efuse),
188
+ TYPE_XLNX_EFUSE, &error_abort,
189
+ "efuse-nr", "3",
190
+ "efuse-size", "8192",
191
+ NULL);
192
+
193
+ qdev_realize(DEVICE(bits), NULL, &error_abort);
194
+ versal_realize_efuse_part(s, ctrl, MM_PMC_EFUSE_CTRL);
195
+ versal_realize_efuse_part(s, cache, MM_PMC_EFUSE_CACHE);
196
+
197
+ sysbus_connect_irq(SYS_BUS_DEVICE(ctrl), 0, pic[VERSAL_EFUSE_IRQ]);
198
+}
199
+
200
/* This takes the board allocated linear DDR memory and creates aliases
201
* for each split DDR range/aperture on the Versal address map.
202
*/
203
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
204
versal_create_rtc(s, pic);
205
versal_create_xrams(s, pic);
206
versal_create_bbram(s, pic);
207
+ versal_create_efuse(s, pic);
208
versal_map_ddr(s);
209
versal_unimp(s);
210
211
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
212
index XXXXXXX..XXXXXXX 100644
213
--- a/hw/arm/Kconfig
214
+++ b/hw/arm/Kconfig
215
@@ -XXX,XX +XXX,XX @@ config XLNX_VERSAL
216
select XLNX_ZYNQMP
217
select OR_IRQ
218
select XLNX_BBRAM
219
+ select XLNX_EFUSE_VERSAL
220
221
config NPCM7XX
222
bool
223
--
81
--
224
2.20.1
82
2.20.1
225
83
226
84
diff view generated by jsdifflib
1
From: Alexander Graf <agraf@csgraf.de>
1
From: Roman Bolshakov <r.bolshakov@yadro.com>
2
2
3
The SMCCC 1.3 spec section 5.2 says
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
The Unknown SMC Function Identifier is a sign-extended value of (-1)
7
Signed-off-by: Roman Bolshakov <r.bolshakov@yadro.com>
6
that is returned in the R0, W0 or X0 registers. An implementation must
8
Reported-by: Peter Maydell <peter.maydell@linaro.org>
7
return this error code when it receives:
9
Message-id: 20210108213815.64678-1-r.bolshakov@yadro.com
8
9
* An SMC or HVC call with an unknown Function Identifier
10
* An SMC or HVC call for a removed Function Identifier
11
* An SMC64/HVC64 call from AArch32 state
12
13
To comply with these statements, let's always return -1 when we encounter
14
an unknown HVC or SMC call.
15
16
Signed-off-by: Alexander Graf <agraf@csgraf.de>
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
12
---
20
target/arm/psci.c | 35 ++++++-----------------------------
13
ui/cocoa.m | 2 +-
21
1 file changed, 6 insertions(+), 29 deletions(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
22
15
23
diff --git a/target/arm/psci.c b/target/arm/psci.c
16
diff --git a/ui/cocoa.m b/ui/cocoa.m
24
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/psci.c
18
--- a/ui/cocoa.m
26
+++ b/target/arm/psci.c
19
+++ b/ui/cocoa.m
27
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
28
21
- (void) openDocumentation: (NSString *) filename
29
bool arm_is_psci_call(ARMCPU *cpu, int excp_type)
30
{
22
{
31
- /* Return true if the r0/x0 value indicates a PSCI call and
23
/* Where to look for local files */
32
- * the exception type matches the configured PSCI conduit. This is
24
- NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"../docs/"};
33
- * called before the SMC/HVC instruction is executed, to decide whether
25
+ NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"docs/"};
34
- * we should treat it as a PSCI call or with the architecturally
26
NSString *full_file_path;
35
+ /*
27
36
+ * Return true if the exception type matches the configured PSCI conduit.
28
/* iterate thru the possible paths until the file is found */
37
+ * This is called before the SMC/HVC instruction is executed, to decide
38
+ * whether we should treat it as a PSCI call or with the architecturally
39
* defined behaviour for an SMC or HVC (which might be UNDEF or trap
40
* to EL2 or to EL3).
41
*/
42
- CPUARMState *env = &cpu->env;
43
- uint64_t param = is_a64(env) ? env->xregs[0] : env->regs[0];
44
45
switch (excp_type) {
46
case EXCP_HVC:
47
@@ -XXX,XX +XXX,XX @@ bool arm_is_psci_call(ARMCPU *cpu, int excp_type)
48
return false;
49
}
50
51
- switch (param) {
52
- case QEMU_PSCI_0_2_FN_PSCI_VERSION:
53
- case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
54
- case QEMU_PSCI_0_2_FN_AFFINITY_INFO:
55
- case QEMU_PSCI_0_2_FN64_AFFINITY_INFO:
56
- case QEMU_PSCI_0_2_FN_SYSTEM_RESET:
57
- case QEMU_PSCI_0_2_FN_SYSTEM_OFF:
58
- case QEMU_PSCI_0_1_FN_CPU_ON:
59
- case QEMU_PSCI_0_2_FN_CPU_ON:
60
- case QEMU_PSCI_0_2_FN64_CPU_ON:
61
- case QEMU_PSCI_0_1_FN_CPU_OFF:
62
- case QEMU_PSCI_0_2_FN_CPU_OFF:
63
- case QEMU_PSCI_0_1_FN_CPU_SUSPEND:
64
- case QEMU_PSCI_0_2_FN_CPU_SUSPEND:
65
- case QEMU_PSCI_0_2_FN64_CPU_SUSPEND:
66
- case QEMU_PSCI_0_1_FN_MIGRATE:
67
- case QEMU_PSCI_0_2_FN_MIGRATE:
68
- return true;
69
- default:
70
- return false;
71
- }
72
+ return true;
73
}
74
75
void arm_handle_psci_call(ARMCPU *cpu)
76
@@ -XXX,XX +XXX,XX @@ void arm_handle_psci_call(ARMCPU *cpu)
77
break;
78
case QEMU_PSCI_0_1_FN_MIGRATE:
79
case QEMU_PSCI_0_2_FN_MIGRATE:
80
+ default:
81
ret = QEMU_PSCI_RET_NOT_SUPPORTED;
82
break;
83
- default:
84
- g_assert_not_reached();
85
}
86
87
err:
88
--
29
--
89
2.20.1
30
2.20.1
90
31
91
32
diff view generated by jsdifflib
1
Rename the "allocate and return" qbus creation function to
1
In commit 1982e1602d15 we added a new qemu-storage-daemon(1) manpage.
2
qbus_new(), to bring it into line with our _init vs _new convention.
2
At the moment new manpages have to be listed both in the conf.py for
3
Sphinx and also in docs/meson.build for Meson. We forgot the second
4
of those -- correct the omission.
3
5
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Reviewed-by: Corey Minyard <cminyard@mvista.com>
9
Message-id: 20210108161416.21129-2-peter.maydell@linaro.org
8
Message-id: 20210923121153.23754-6-peter.maydell@linaro.org
9
---
10
---
10
include/hw/qdev-core.h | 2 +-
11
docs/meson.build | 1 +
11
hw/core/bus.c | 2 +-
12
1 file changed, 1 insertion(+)
12
hw/hyperv/vmbus.c | 2 +-
13
hw/i2c/core.c | 2 +-
14
hw/isa/isa-bus.c | 2 +-
15
hw/misc/auxbus.c | 2 +-
16
hw/pci/pci.c | 2 +-
17
hw/ppc/spapr_vio.c | 2 +-
18
hw/s390x/ap-bridge.c | 2 +-
19
hw/s390x/css-bridge.c | 2 +-
20
hw/s390x/s390-pci-bus.c | 2 +-
21
hw/ssi/ssi.c | 2 +-
22
hw/xen/xen-bus.c | 2 +-
23
hw/xen/xen-legacy-backend.c | 2 +-
24
14 files changed, 14 insertions(+), 14 deletions(-)
25
13
26
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
14
diff --git a/docs/meson.build b/docs/meson.build
27
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
28
--- a/include/hw/qdev-core.h
16
--- a/docs/meson.build
29
+++ b/include/hw/qdev-core.h
17
+++ b/docs/meson.build
30
@@ -XXX,XX +XXX,XX @@ typedef int (qdev_walkerfn)(DeviceState *dev, void *opaque);
18
@@ -XXX,XX +XXX,XX @@ if build_docs
31
19
'qemu-img.1': (have_tools ? 'man1' : ''),
32
void qbus_init(void *bus, size_t size, const char *typename,
20
'qemu-nbd.8': (have_tools ? 'man8' : ''),
33
DeviceState *parent, const char *name);
21
'qemu-pr-helper.8': (have_tools ? 'man8' : ''),
34
-BusState *qbus_create(const char *typename, DeviceState *parent, const char *name);
22
+ 'qemu-storage-daemon.1': (have_tools ? 'man1' : ''),
35
+BusState *qbus_new(const char *typename, DeviceState *parent, const char *name);
23
'qemu-trace-stap.1': (config_host.has_key('CONFIG_TRACE_SYSTEMTAP') ? 'man1' : ''),
36
bool qbus_realize(BusState *bus, Error **errp);
24
'virtfs-proxy-helper.1': (have_virtfs_proxy_helper ? 'man1' : ''),
37
void qbus_unrealize(BusState *bus);
25
'virtiofsd.1': (have_virtiofsd ? 'man1' : ''),
38
39
diff --git a/hw/core/bus.c b/hw/core/bus.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/core/bus.c
42
+++ b/hw/core/bus.c
43
@@ -XXX,XX +XXX,XX @@ void qbus_init(void *bus, size_t size, const char *typename,
44
qbus_init_internal(bus, parent, name);
45
}
46
47
-BusState *qbus_create(const char *typename, DeviceState *parent, const char *name)
48
+BusState *qbus_new(const char *typename, DeviceState *parent, const char *name)
49
{
50
BusState *bus;
51
52
diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/hw/hyperv/vmbus.c
55
+++ b/hw/hyperv/vmbus.c
56
@@ -XXX,XX +XXX,XX @@ static void vmbus_bridge_realize(DeviceState *dev, Error **errp)
57
return;
58
}
59
60
- bridge->bus = VMBUS(qbus_create(TYPE_VMBUS, dev, "vmbus"));
61
+ bridge->bus = VMBUS(qbus_new(TYPE_VMBUS, dev, "vmbus"));
62
}
63
64
static char *vmbus_bridge_ofw_unit_address(const SysBusDevice *dev)
65
diff --git a/hw/i2c/core.c b/hw/i2c/core.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/hw/i2c/core.c
68
+++ b/hw/i2c/core.c
69
@@ -XXX,XX +XXX,XX @@ I2CBus *i2c_init_bus(DeviceState *parent, const char *name)
70
{
71
I2CBus *bus;
72
73
- bus = I2C_BUS(qbus_create(TYPE_I2C_BUS, parent, name));
74
+ bus = I2C_BUS(qbus_new(TYPE_I2C_BUS, parent, name));
75
QLIST_INIT(&bus->current_devs);
76
vmstate_register(NULL, VMSTATE_INSTANCE_ID_ANY, &vmstate_i2c_bus, bus);
77
return bus;
78
diff --git a/hw/isa/isa-bus.c b/hw/isa/isa-bus.c
79
index XXXXXXX..XXXXXXX 100644
80
--- a/hw/isa/isa-bus.c
81
+++ b/hw/isa/isa-bus.c
82
@@ -XXX,XX +XXX,XX @@ ISABus *isa_bus_new(DeviceState *dev, MemoryRegion* address_space,
83
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
84
}
85
86
- isabus = ISA_BUS(qbus_create(TYPE_ISA_BUS, dev, NULL));
87
+ isabus = ISA_BUS(qbus_new(TYPE_ISA_BUS, dev, NULL));
88
isabus->address_space = address_space;
89
isabus->address_space_io = address_space_io;
90
return isabus;
91
diff --git a/hw/misc/auxbus.c b/hw/misc/auxbus.c
92
index XXXXXXX..XXXXXXX 100644
93
--- a/hw/misc/auxbus.c
94
+++ b/hw/misc/auxbus.c
95
@@ -XXX,XX +XXX,XX @@ AUXBus *aux_bus_init(DeviceState *parent, const char *name)
96
AUXBus *bus;
97
Object *auxtoi2c;
98
99
- bus = AUX_BUS(qbus_create(TYPE_AUX_BUS, parent, name));
100
+ bus = AUX_BUS(qbus_new(TYPE_AUX_BUS, parent, name));
101
auxtoi2c = object_new_with_props(TYPE_AUXTOI2C, OBJECT(bus), "i2c",
102
&error_abort, NULL);
103
104
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
105
index XXXXXXX..XXXXXXX 100644
106
--- a/hw/pci/pci.c
107
+++ b/hw/pci/pci.c
108
@@ -XXX,XX +XXX,XX @@ PCIBus *pci_root_bus_new(DeviceState *parent, const char *name,
109
{
110
PCIBus *bus;
111
112
- bus = PCI_BUS(qbus_create(typename, parent, name));
113
+ bus = PCI_BUS(qbus_new(typename, parent, name));
114
pci_root_bus_internal_init(bus, parent, address_space_mem,
115
address_space_io, devfn_min);
116
return bus;
117
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/hw/ppc/spapr_vio.c
120
+++ b/hw/ppc/spapr_vio.c
121
@@ -XXX,XX +XXX,XX @@ SpaprVioBus *spapr_vio_bus_init(void)
122
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
123
124
/* Create bus on bridge device */
125
- qbus = qbus_create(TYPE_SPAPR_VIO_BUS, dev, "spapr-vio");
126
+ qbus = qbus_new(TYPE_SPAPR_VIO_BUS, dev, "spapr-vio");
127
bus = SPAPR_VIO_BUS(qbus);
128
bus->next_reg = SPAPR_VIO_REG_BASE;
129
130
diff --git a/hw/s390x/ap-bridge.c b/hw/s390x/ap-bridge.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/hw/s390x/ap-bridge.c
133
+++ b/hw/s390x/ap-bridge.c
134
@@ -XXX,XX +XXX,XX @@ void s390_init_ap(void)
135
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
136
137
/* Create bus on bridge device */
138
- bus = qbus_create(TYPE_AP_BUS, dev, TYPE_AP_BUS);
139
+ bus = qbus_new(TYPE_AP_BUS, dev, TYPE_AP_BUS);
140
141
/* Enable hotplugging */
142
qbus_set_hotplug_handler(bus, OBJECT(dev));
143
diff --git a/hw/s390x/css-bridge.c b/hw/s390x/css-bridge.c
144
index XXXXXXX..XXXXXXX 100644
145
--- a/hw/s390x/css-bridge.c
146
+++ b/hw/s390x/css-bridge.c
147
@@ -XXX,XX +XXX,XX @@ VirtualCssBus *virtual_css_bus_init(void)
148
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
149
150
/* Create bus on bridge device */
151
- bus = qbus_create(TYPE_VIRTUAL_CSS_BUS, dev, "virtual-css");
152
+ bus = qbus_new(TYPE_VIRTUAL_CSS_BUS, dev, "virtual-css");
153
cbus = VIRTUAL_CSS_BUS(bus);
154
155
/* Enable hotplugging */
156
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
157
index XXXXXXX..XXXXXXX 100644
158
--- a/hw/s390x/s390-pci-bus.c
159
+++ b/hw/s390x/s390-pci-bus.c
160
@@ -XXX,XX +XXX,XX @@ static void s390_pcihost_realize(DeviceState *dev, Error **errp)
161
qbus_set_hotplug_handler(bus, OBJECT(dev));
162
phb->bus = b;
163
164
- s->bus = S390_PCI_BUS(qbus_create(TYPE_S390_PCI_BUS, dev, NULL));
165
+ s->bus = S390_PCI_BUS(qbus_new(TYPE_S390_PCI_BUS, dev, NULL));
166
qbus_set_hotplug_handler(BUS(s->bus), OBJECT(dev));
167
168
s->iommu_table = g_hash_table_new_full(g_int64_hash, g_int64_equal,
169
diff --git a/hw/ssi/ssi.c b/hw/ssi/ssi.c
170
index XXXXXXX..XXXXXXX 100644
171
--- a/hw/ssi/ssi.c
172
+++ b/hw/ssi/ssi.c
173
@@ -XXX,XX +XXX,XX @@ DeviceState *ssi_create_peripheral(SSIBus *bus, const char *name)
174
SSIBus *ssi_create_bus(DeviceState *parent, const char *name)
175
{
176
BusState *bus;
177
- bus = qbus_create(TYPE_SSI_BUS, parent, name);
178
+ bus = qbus_new(TYPE_SSI_BUS, parent, name);
179
return SSI_BUS(bus);
180
}
181
182
diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c
183
index XXXXXXX..XXXXXXX 100644
184
--- a/hw/xen/xen-bus.c
185
+++ b/hw/xen/xen-bus.c
186
@@ -XXX,XX +XXX,XX @@ type_init(xen_register_types)
187
void xen_bus_init(void)
188
{
189
DeviceState *dev = qdev_new(TYPE_XEN_BRIDGE);
190
- BusState *bus = qbus_create(TYPE_XEN_BUS, dev, NULL);
191
+ BusState *bus = qbus_new(TYPE_XEN_BUS, dev, NULL);
192
193
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
194
qbus_set_bus_hotplug_handler(bus);
195
diff --git a/hw/xen/xen-legacy-backend.c b/hw/xen/xen-legacy-backend.c
196
index XXXXXXX..XXXXXXX 100644
197
--- a/hw/xen/xen-legacy-backend.c
198
+++ b/hw/xen/xen-legacy-backend.c
199
@@ -XXX,XX +XXX,XX @@ int xen_be_init(void)
200
201
xen_sysdev = qdev_new(TYPE_XENSYSDEV);
202
sysbus_realize_and_unref(SYS_BUS_DEVICE(xen_sysdev), &error_fatal);
203
- xen_sysbus = qbus_create(TYPE_XENSYSBUS, xen_sysdev, "xen-sysbus");
204
+ xen_sysbus = qbus_new(TYPE_XENSYSBUS, xen_sysdev, "xen-sysbus");
205
qbus_set_bus_hotplug_handler(xen_sysbus);
206
207
return 0;
208
--
26
--
209
2.20.1
27
2.20.1
210
28
211
29
diff view generated by jsdifflib
1
Rename qbus_create_inplace() to qbus_init(); this is more in line
1
When we first converted our documentation to Sphinx, we split it into
2
with our usual naming convention for functions that in-place
2
multiple manuals (system, interop, tools, etc), which are all built
3
initialize objects.
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é <philmd@redhat.com>
38
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
7
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
39
Message-id: 20210108161416.21129-3-peter.maydell@linaro.org
8
Message-id: 20210923121153.23754-5-peter.maydell@linaro.org
9
---
40
---
10
include/hw/qdev-core.h | 4 ++--
41
docs/conf.py | 46 ++++++++++++++++++++++++++++++-
11
hw/audio/intel-hda.c | 2 +-
42
docs/devel/conf.py | 15 -----------
12
hw/block/fdc.c | 2 +-
43
docs/index.html.in | 17 ------------
13
hw/block/swim.c | 3 +--
44
docs/interop/conf.py | 28 -------------------
14
hw/char/virtio-serial-bus.c | 4 ++--
45
docs/meson.build | 64 +++++++++++++++++---------------------------
15
hw/core/bus.c | 11 ++++++-----
46
docs/specs/conf.py | 16 -----------
16
hw/core/sysbus.c | 10 ++++++----
47
docs/system/conf.py | 28 -------------------
17
hw/gpio/bcm2835_gpio.c | 3 +--
48
docs/tools/conf.py | 37 -------------------------
18
hw/ide/qdev.c | 2 +-
49
docs/user/conf.py | 15 -----------
19
hw/ipack/ipack.c | 2 +-
50
9 files changed, 70 insertions(+), 196 deletions(-)
20
hw/misc/mac_via.c | 4 ++--
51
delete mode 100644 docs/devel/conf.py
21
hw/misc/macio/cuda.c | 4 ++--
52
delete mode 100644 docs/index.html.in
22
hw/misc/macio/macio.c | 4 ++--
53
delete mode 100644 docs/interop/conf.py
23
hw/misc/macio/pmu.c | 4 ++--
54
delete mode 100644 docs/specs/conf.py
24
hw/nubus/nubus-bridge.c | 2 +-
55
delete mode 100644 docs/system/conf.py
25
hw/nvme/ctrl.c | 4 ++--
56
delete mode 100644 docs/tools/conf.py
26
hw/nvme/subsys.c | 3 +--
57
delete mode 100644 docs/user/conf.py
27
hw/pci/pci.c | 2 +-
58
28
hw/pci/pci_bridge.c | 4 ++--
59
diff --git a/docs/conf.py b/docs/conf.py
29
hw/s390x/event-facility.c | 4 ++--
30
hw/s390x/virtio-ccw.c | 3 +--
31
hw/scsi/scsi-bus.c | 2 +-
32
hw/sd/allwinner-sdhost.c | 4 ++--
33
hw/sd/bcm2835_sdhost.c | 4 ++--
34
hw/sd/pl181.c | 3 +--
35
hw/sd/pxa2xx_mmci.c | 4 ++--
36
hw/sd/sdhci.c | 3 +--
37
hw/sd/ssi-sd.c | 3 +--
38
hw/usb/bus.c | 2 +-
39
hw/usb/dev-smartcard-reader.c | 3 +--
40
hw/virtio/virtio-mmio.c | 3 +--
41
hw/virtio/virtio-pci.c | 3 +--
42
32 files changed, 54 insertions(+), 61 deletions(-)
43
44
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
45
index XXXXXXX..XXXXXXX 100644
60
index XXXXXXX..XXXXXXX 100644
46
--- a/include/hw/qdev-core.h
61
--- a/docs/conf.py
47
+++ b/include/hw/qdev-core.h
62
+++ b/docs/conf.py
48
@@ -XXX,XX +XXX,XX @@ DeviceState *qdev_find_recursive(BusState *bus, const char *id);
63
@@ -XXX,XX +XXX,XX @@ latex_documents = [
49
typedef int (qbus_walkerfn)(BusState *bus, void *opaque);
64
50
typedef int (qdev_walkerfn)(DeviceState *dev, void *opaque);
65
# -- Options for manual page output ---------------------------------------
51
66
# Individual manual/conf.py can override this to create man pages
52
-void qbus_create_inplace(void *bus, size_t size, const char *typename,
67
-man_pages = []
53
- DeviceState *parent, const char *name);
68
+man_pages = [
54
+void qbus_init(void *bus, size_t size, const char *typename,
69
+ ('interop/qemu-ga', 'qemu-ga',
55
+ DeviceState *parent, const char *name);
70
+ 'QEMU Guest Agent',
56
BusState *qbus_create(const char *typename, DeviceState *parent, const char *name);
71
+ ['Michael Roth <mdroth@linux.vnet.ibm.com>'], 8),
57
bool qbus_realize(BusState *bus, Error **errp);
72
+ ('interop/qemu-ga-ref', 'qemu-ga-ref',
58
void qbus_unrealize(BusState *bus);
73
+ 'QEMU Guest Agent Protocol Reference',
59
diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c
74
+ [], 7),
75
+ ('interop/qemu-qmp-ref', 'qemu-qmp-ref',
76
+ 'QEMU QMP Reference Manual',
77
+ [], 7),
78
+ ('interop/qemu-storage-daemon-qmp-ref', 'qemu-storage-daemon-qmp-ref',
79
+ 'QEMU Storage Daemon QMP Reference Manual',
80
+ [], 7),
81
+ ('system/qemu-manpage', 'qemu',
82
+ 'QEMU User Documentation',
83
+ ['Fabrice Bellard'], 1),
84
+ ('system/qemu-block-drivers', 'qemu-block-drivers',
85
+ 'QEMU block drivers reference',
86
+ ['Fabrice Bellard and the QEMU Project developers'], 7),
87
+ ('system/qemu-cpu-models', 'qemu-cpu-models',
88
+ 'QEMU CPU Models',
89
+ ['The QEMU Project developers'], 7),
90
+ ('tools/qemu-img', 'qemu-img',
91
+ 'QEMU disk image utility',
92
+ ['Fabrice Bellard'], 1),
93
+ ('tools/qemu-nbd', 'qemu-nbd',
94
+ 'QEMU Disk Network Block Device Server',
95
+ ['Anthony Liguori <anthony@codemonkey.ws>'], 8),
96
+ ('tools/qemu-pr-helper', 'qemu-pr-helper',
97
+ 'QEMU persistent reservation helper',
98
+ [], 8),
99
+ ('tools/qemu-storage-daemon', 'qemu-storage-daemon',
100
+ 'QEMU storage daemon',
101
+ [], 1),
102
+ ('tools/qemu-trace-stap', 'qemu-trace-stap',
103
+ 'QEMU SystemTap trace tool',
104
+ [], 1),
105
+ ('tools/virtfs-proxy-helper', 'virtfs-proxy-helper',
106
+ 'QEMU 9p virtfs proxy filesystem helper',
107
+ ['M. Mohan Kumar'], 1),
108
+ ('tools/virtiofsd', 'virtiofsd',
109
+ 'QEMU virtio-fs shared file system daemon',
110
+ ['Stefan Hajnoczi <stefanha@redhat.com>',
111
+ 'Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>'], 1),
112
+]
113
114
# -- Options for Texinfo output -------------------------------------------
115
116
diff --git a/docs/devel/conf.py b/docs/devel/conf.py
117
deleted file mode 100644
118
index XXXXXXX..XXXXXXX
119
--- a/docs/devel/conf.py
120
+++ /dev/null
121
@@ -XXX,XX +XXX,XX @@
122
-# -*- coding: utf-8 -*-
123
-#
124
-# QEMU documentation build configuration file for the 'devel' manual.
125
-#
126
-# This includes the top level conf file and then makes any necessary tweaks.
127
-import sys
128
-import os
129
-
130
-qemu_docdir = os.path.abspath("..")
131
-parent_config = os.path.join(qemu_docdir, "conf.py")
132
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
133
-
134
-# This slightly misuses the 'description', but is the best way to get
135
-# the manual title to appear in the sidebar.
136
-html_theme_options['description'] = u'Developer''s Guide'
137
diff --git a/docs/index.html.in b/docs/index.html.in
138
deleted file mode 100644
139
index XXXXXXX..XXXXXXX
140
--- a/docs/index.html.in
141
+++ /dev/null
142
@@ -XXX,XX +XXX,XX @@
143
-<!DOCTYPE html>
144
-<html lang="en">
145
- <head>
146
- <meta charset="UTF-8">
147
- <title>QEMU @VERSION@ Documentation</title>
148
- </head>
149
- <body>
150
- <h1>QEMU @VERSION@ Documentation</h1>
151
- <ul>
152
- <li><a href="system/index.html">System Emulation User's Guide</a></li>
153
- <li><a href="user/index.html">User Mode Emulation User's Guide</a></li>
154
- <li><a href="tools/index.html">Tools Guide</a></li>
155
- <li><a href="interop/index.html">System Emulation Management and Interoperability Guide</a></li>
156
- <li><a href="specs/index.html">System Emulation Guest Hardware Specifications</a></li>
157
- </ul>
158
- </body>
159
-</html>
160
diff --git a/docs/interop/conf.py b/docs/interop/conf.py
161
deleted file mode 100644
162
index XXXXXXX..XXXXXXX
163
--- a/docs/interop/conf.py
164
+++ /dev/null
165
@@ -XXX,XX +XXX,XX @@
166
-# -*- coding: utf-8 -*-
167
-#
168
-# QEMU documentation build configuration file for the 'interop' manual.
169
-#
170
-# This includes the top level conf file and then makes any necessary tweaks.
171
-import sys
172
-import os
173
-
174
-qemu_docdir = os.path.abspath("..")
175
-parent_config = os.path.join(qemu_docdir, "conf.py")
176
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
177
-
178
-# This slightly misuses the 'description', but is the best way to get
179
-# the manual title to appear in the sidebar.
180
-html_theme_options['description'] = u'System Emulation Management and Interoperability Guide'
181
-
182
-# One entry per manual page. List of tuples
183
-# (source start file, name, description, authors, manual section).
184
-man_pages = [
185
- ('qemu-ga', 'qemu-ga', u'QEMU Guest Agent',
186
- ['Michael Roth <mdroth@linux.vnet.ibm.com>'], 8),
187
- ('qemu-ga-ref', 'qemu-ga-ref', 'QEMU Guest Agent Protocol Reference',
188
- [], 7),
189
- ('qemu-qmp-ref', 'qemu-qmp-ref', 'QEMU QMP Reference Manual',
190
- [], 7),
191
- ('qemu-storage-daemon-qmp-ref', 'qemu-storage-daemon-qmp-ref',
192
- 'QEMU Storage Daemon QMP Reference Manual', [], 7),
193
-]
194
diff --git a/docs/meson.build b/docs/meson.build
60
index XXXXXXX..XXXXXXX 100644
195
index XXXXXXX..XXXXXXX 100644
61
--- a/hw/audio/intel-hda.c
196
--- a/docs/meson.build
62
+++ b/hw/audio/intel-hda.c
197
+++ b/docs/meson.build
63
@@ -XXX,XX +XXX,XX @@ void hda_codec_bus_init(DeviceState *dev, HDACodecBus *bus, size_t bus_size,
198
@@ -XXX,XX +XXX,XX @@ if build_docs
64
hda_codec_response_func response,
199
meson.source_root() / 'docs/sphinx/qmp_lexer.py',
65
hda_codec_xfer_func xfer)
200
qapi_gen_depends ]
66
{
201
67
- qbus_create_inplace(bus, bus_size, TYPE_HDA_BUS, dev, NULL);
202
- configure_file(output: 'index.html',
68
+ qbus_init(bus, bus_size, TYPE_HDA_BUS, dev, NULL);
203
- input: files('index.html.in'),
69
bus->response = response;
204
- configuration: {'VERSION': meson.project_version()},
70
bus->xfer = xfer;
205
- install_dir: qemu_docdir)
71
}
206
- manuals = [ 'devel', 'interop', 'tools', 'specs', 'system', 'user' ]
72
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
207
man_pages = {
73
index XXXXXXX..XXXXXXX 100644
208
- 'interop' : {
74
--- a/hw/block/fdc.c
209
'qemu-ga.8': (have_tools ? 'man8' : ''),
75
+++ b/hw/block/fdc.c
210
'qemu-ga-ref.7': 'man7',
76
@@ -XXX,XX +XXX,XX @@ static const TypeInfo floppy_bus_info = {
211
'qemu-qmp-ref.7': 'man7',
77
212
'qemu-storage-daemon-qmp-ref.7': (have_tools ? 'man7' : ''),
78
static void floppy_bus_create(FDCtrl *fdc, FloppyBus *bus, DeviceState *dev)
213
- },
79
{
214
- 'tools': {
80
- qbus_create_inplace(bus, sizeof(FloppyBus), TYPE_FLOPPY_BUS, dev, NULL);
215
'qemu-img.1': (have_tools ? 'man1' : ''),
81
+ qbus_init(bus, sizeof(FloppyBus), TYPE_FLOPPY_BUS, dev, NULL);
216
'qemu-nbd.8': (have_tools ? 'man8' : ''),
82
bus->fdc = fdc;
217
'qemu-pr-helper.8': (have_tools ? 'man8' : ''),
83
}
218
@@ -XXX,XX +XXX,XX @@ if build_docs
84
219
'qemu-trace-stap.1': (config_host.has_key('CONFIG_TRACE_SYSTEMTAP') ? 'man1' : ''),
85
diff --git a/hw/block/swim.c b/hw/block/swim.c
220
'virtfs-proxy-helper.1': (have_virtfs_proxy_helper ? 'man1' : ''),
86
index XXXXXXX..XXXXXXX 100644
221
'virtiofsd.1': (have_virtiofsd ? 'man1' : ''),
87
--- a/hw/block/swim.c
222
- },
88
+++ b/hw/block/swim.c
223
- 'system': {
89
@@ -XXX,XX +XXX,XX @@ static void sysbus_swim_realize(DeviceState *dev, Error **errp)
224
'qemu.1': 'man1',
90
Swim *sys = SWIM(dev);
225
'qemu-block-drivers.7': 'man7',
91
SWIMCtrl *swimctrl = &sys->ctrl;
226
'qemu-cpu-models.7': 'man7'
92
227
- },
93
- qbus_create_inplace(&swimctrl->bus, sizeof(SWIMBus), TYPE_SWIM_BUS, dev,
228
}
94
- NULL);
229
95
+ qbus_init(&swimctrl->bus, sizeof(SWIMBus), TYPE_SWIM_BUS, dev, NULL);
230
sphinxdocs = []
96
swimctrl->bus.ctrl = swimctrl;
231
sphinxmans = []
97
}
232
- foreach manual : manuals
98
233
- private_dir = meson.current_build_dir() / (manual + '.p')
99
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
234
- output_dir = meson.current_build_dir() / manual
100
index XXXXXXX..XXXXXXX 100644
235
- input_dir = meson.current_source_dir() / manual
101
--- a/hw/char/virtio-serial-bus.c
236
102
+++ b/hw/char/virtio-serial-bus.c
237
- this_manual = custom_target(manual + ' manual',
103
@@ -XXX,XX +XXX,XX @@ static void virtio_serial_device_realize(DeviceState *dev, Error **errp)
238
+ private_dir = meson.current_build_dir() / 'manual.p'
104
config_size);
239
+ output_dir = meson.current_build_dir() / 'manual'
105
240
+ input_dir = meson.current_source_dir()
106
/* Spawn a new virtio-serial bus on which the ports will ride as devices */
241
+
107
- qbus_create_inplace(&vser->bus, sizeof(vser->bus), TYPE_VIRTIO_SERIAL_BUS,
242
+ this_manual = custom_target('QEMU manual',
108
- dev, vdev->bus_name);
243
build_by_default: build_docs,
109
+ qbus_init(&vser->bus, sizeof(vser->bus), TYPE_VIRTIO_SERIAL_BUS,
244
- output: [manual + '.stamp'],
110
+ dev, vdev->bus_name);
245
- input: [files('conf.py'), files(manual / 'conf.py')],
111
qbus_set_hotplug_handler(BUS(&vser->bus), OBJECT(vser));
246
- depfile: manual + '.d',
112
vser->bus.vser = vser;
247
+ output: 'docs.stamp',
113
QTAILQ_INIT(&vser->ports);
248
+ input: files('conf.py'),
114
diff --git a/hw/core/bus.c b/hw/core/bus.c
249
+ depfile: 'docs.d',
115
index XXXXXXX..XXXXXXX 100644
250
depend_files: sphinx_extn_depends,
116
--- a/hw/core/bus.c
251
command: [SPHINX_ARGS, '-Ddepfile=@DEPFILE@',
117
+++ b/hw/core/bus.c
252
'-Ddepfile_stamp=@OUTPUT0@',
118
@@ -XXX,XX +XXX,XX @@ static void bus_reset_child_foreach(Object *obj, ResettableChildCallback cb,
253
'-b', 'html', '-d', private_dir,
119
}
254
input_dir, output_dir])
120
}
255
- sphinxdocs += this_manual
121
256
- if build_docs and manual != 'devel'
122
-static void qbus_init(BusState *bus, DeviceState *parent, const char *name)
257
- install_subdir(output_dir, install_dir: qemu_docdir)
123
+static void qbus_init_internal(BusState *bus, DeviceState *parent,
258
- endif
124
+ const char *name)
259
+ sphinxdocs += this_manual
125
{
260
+ install_subdir(output_dir, install_dir: qemu_docdir, strip_directory: true)
126
const char *typename = object_get_typename(OBJECT(bus));
261
127
BusClass *bc;
262
- these_man_pages = []
128
@@ -XXX,XX +XXX,XX @@ static void bus_unparent(Object *obj)
263
- install_dirs = []
129
bus->parent = NULL;
264
- foreach page, section : man_pages.get(manual, {})
130
}
265
- these_man_pages += page
131
266
- install_dirs += section == '' ? false : get_option('mandir') / section
132
-void qbus_create_inplace(void *bus, size_t size, const char *typename,
267
- endforeach
133
- DeviceState *parent, const char *name)
268
- if these_man_pages.length() > 0
134
+void qbus_init(void *bus, size_t size, const char *typename,
269
- sphinxmans += custom_target(manual + ' man pages',
135
+ DeviceState *parent, const char *name)
270
- build_by_default: build_docs,
136
{
271
- output: these_man_pages,
137
object_initialize(bus, size, typename);
272
- input: this_manual,
138
- qbus_init(bus, parent, name);
273
- install: build_docs,
139
+ qbus_init_internal(bus, parent, name);
274
- install_dir: install_dirs,
140
}
275
- command: [SPHINX_ARGS, '-b', 'man', '-d', private_dir,
141
276
- input_dir, meson.current_build_dir()])
142
BusState *qbus_create(const char *typename, DeviceState *parent, const char *name)
277
- endif
143
@@ -XXX,XX +XXX,XX @@ BusState *qbus_create(const char *typename, DeviceState *parent, const char *nam
278
+ these_man_pages = []
144
BusState *bus;
279
+ install_dirs = []
145
280
+ foreach page, section : man_pages
146
bus = BUS(object_new(typename));
281
+ these_man_pages += page
147
- qbus_init(bus, parent, name);
282
+ install_dirs += section == '' ? false : get_option('mandir') / section
148
+ qbus_init_internal(bus, parent, name);
283
endforeach
149
284
+
150
return bus;
285
+ sphinxmans += custom_target('QEMU man pages',
151
}
286
+ build_by_default: build_docs,
152
diff --git a/hw/core/sysbus.c b/hw/core/sysbus.c
287
+ output: these_man_pages,
153
index XXXXXXX..XXXXXXX 100644
288
+ input: this_manual,
154
--- a/hw/core/sysbus.c
289
+ install: build_docs,
155
+++ b/hw/core/sysbus.c
290
+ install_dir: install_dirs,
156
@@ -XXX,XX +XXX,XX @@ static BusState *main_system_bus;
291
+ command: [SPHINX_ARGS, '-b', 'man', '-d', private_dir,
157
292
+ input_dir, meson.current_build_dir()])
158
static void main_system_bus_create(void)
293
+
159
{
294
alias_target('sphinxdocs', sphinxdocs)
160
- /* assign main_system_bus before qbus_create_inplace()
295
alias_target('html', sphinxdocs)
161
- * in order to make "if (bus != sysbus_get_default())" work */
296
alias_target('man', sphinxmans)
162
+ /*
297
diff --git a/docs/specs/conf.py b/docs/specs/conf.py
163
+ * assign main_system_bus before qbus_init()
298
deleted file mode 100644
164
+ * in order to make "if (bus != sysbus_get_default())" work
299
index XXXXXXX..XXXXXXX
165
+ */
300
--- a/docs/specs/conf.py
166
main_system_bus = g_malloc0(system_bus_info.instance_size);
301
+++ /dev/null
167
- qbus_create_inplace(main_system_bus, system_bus_info.instance_size,
302
@@ -XXX,XX +XXX,XX @@
168
- TYPE_SYSTEM_BUS, NULL, "main-system-bus");
303
-# -*- coding: utf-8 -*-
169
+ qbus_init(main_system_bus, system_bus_info.instance_size,
304
-#
170
+ TYPE_SYSTEM_BUS, NULL, "main-system-bus");
305
-# QEMU documentation build configuration file for the 'specs' manual.
171
OBJECT(main_system_bus)->free = g_free;
306
-#
172
}
307
-# This includes the top level conf file and then makes any necessary tweaks.
173
308
-import sys
174
diff --git a/hw/gpio/bcm2835_gpio.c b/hw/gpio/bcm2835_gpio.c
309
-import os
175
index XXXXXXX..XXXXXXX 100644
310
-
176
--- a/hw/gpio/bcm2835_gpio.c
311
-qemu_docdir = os.path.abspath("..")
177
+++ b/hw/gpio/bcm2835_gpio.c
312
-parent_config = os.path.join(qemu_docdir, "conf.py")
178
@@ -XXX,XX +XXX,XX @@ static void bcm2835_gpio_init(Object *obj)
313
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
179
DeviceState *dev = DEVICE(obj);
314
-
180
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
315
-# This slightly misuses the 'description', but is the best way to get
181
316
-# the manual title to appear in the sidebar.
182
- qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
317
-html_theme_options['description'] = \
183
- TYPE_SD_BUS, DEVICE(s), "sd-bus");
318
- u'System Emulation Guest Hardware Specifications'
184
+ qbus_init(&s->sdbus, sizeof(s->sdbus), TYPE_SD_BUS, DEVICE(s), "sd-bus");
319
diff --git a/docs/system/conf.py b/docs/system/conf.py
185
320
deleted file mode 100644
186
memory_region_init_io(&s->iomem, obj,
321
index XXXXXXX..XXXXXXX
187
&bcm2835_gpio_ops, s, "bcm2835_gpio", 0x1000);
322
--- a/docs/system/conf.py
188
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
323
+++ /dev/null
189
index XXXXXXX..XXXXXXX 100644
324
@@ -XXX,XX +XXX,XX @@
190
--- a/hw/ide/qdev.c
325
-# -*- coding: utf-8 -*-
191
+++ b/hw/ide/qdev.c
326
-#
192
@@ -XXX,XX +XXX,XX @@ static const TypeInfo ide_bus_info = {
327
-# QEMU documentation build configuration file for the 'system' manual.
193
void ide_bus_new(IDEBus *idebus, size_t idebus_size, DeviceState *dev,
328
-#
194
int bus_id, int max_units)
329
-# This includes the top level conf file and then makes any necessary tweaks.
195
{
330
-import sys
196
- qbus_create_inplace(idebus, idebus_size, TYPE_IDE_BUS, dev, NULL);
331
-import os
197
+ qbus_init(idebus, idebus_size, TYPE_IDE_BUS, dev, NULL);
332
-
198
idebus->bus_id = bus_id;
333
-qemu_docdir = os.path.abspath("..")
199
idebus->max_units = max_units;
334
-parent_config = os.path.join(qemu_docdir, "conf.py")
200
}
335
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
201
diff --git a/hw/ipack/ipack.c b/hw/ipack/ipack.c
336
-
202
index XXXXXXX..XXXXXXX 100644
337
-# This slightly misuses the 'description', but is the best way to get
203
--- a/hw/ipack/ipack.c
338
-# the manual title to appear in the sidebar.
204
+++ b/hw/ipack/ipack.c
339
-html_theme_options['description'] = u'System Emulation User''s Guide'
205
@@ -XXX,XX +XXX,XX @@ void ipack_bus_init(IPackBus *bus, size_t bus_size,
340
-
206
uint8_t n_slots,
341
-# One entry per manual page. List of tuples
207
qemu_irq_handler handler)
342
-# (source start file, name, description, authors, manual section).
208
{
343
-man_pages = [
209
- qbus_create_inplace(bus, bus_size, TYPE_IPACK_BUS, parent, NULL);
344
- ('qemu-manpage', 'qemu', u'QEMU User Documentation',
210
+ qbus_init(bus, bus_size, TYPE_IPACK_BUS, parent, NULL);
345
- ['Fabrice Bellard'], 1),
211
bus->n_slots = n_slots;
346
- ('qemu-block-drivers', 'qemu-block-drivers',
212
bus->set_irq = handler;
347
- u'QEMU block drivers reference',
213
}
348
- ['Fabrice Bellard and the QEMU Project developers'], 7),
214
diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c
349
- ('qemu-cpu-models', 'qemu-cpu-models',
215
index XXXXXXX..XXXXXXX 100644
350
- u'QEMU CPU Models',
216
--- a/hw/misc/mac_via.c
351
- ['The QEMU Project developers'], 7)
217
+++ b/hw/misc/mac_via.c
352
-]
218
@@ -XXX,XX +XXX,XX @@ static void mos6522_q800_via1_init(Object *obj)
353
diff --git a/docs/tools/conf.py b/docs/tools/conf.py
219
sysbus_init_mmio(sbd, &v1s->via_mem);
354
deleted file mode 100644
220
355
index XXXXXXX..XXXXXXX
221
/* ADB */
356
--- a/docs/tools/conf.py
222
- qbus_create_inplace((BusState *)&v1s->adb_bus, sizeof(v1s->adb_bus),
357
+++ /dev/null
223
- TYPE_ADB_BUS, DEVICE(v1s), "adb.0");
358
@@ -XXX,XX +XXX,XX @@
224
+ qbus_init((BusState *)&v1s->adb_bus, sizeof(v1s->adb_bus),
359
-# -*- coding: utf-8 -*-
225
+ TYPE_ADB_BUS, DEVICE(v1s), "adb.0");
360
-#
226
361
-# QEMU documentation build configuration file for the 'tools' manual.
227
qdev_init_gpio_in(DEVICE(obj), via1_irq_request, VIA1_IRQ_NB);
362
-#
228
}
363
-# This includes the top level conf file and then makes any necessary tweaks.
229
diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c
364
-import sys
230
index XXXXXXX..XXXXXXX 100644
365
-import os
231
--- a/hw/misc/macio/cuda.c
366
-
232
+++ b/hw/misc/macio/cuda.c
367
-qemu_docdir = os.path.abspath("..")
233
@@ -XXX,XX +XXX,XX @@ static void cuda_init(Object *obj)
368
-parent_config = os.path.join(qemu_docdir, "conf.py")
234
memory_region_init_io(&s->mem, obj, &mos6522_cuda_ops, s, "cuda", 0x2000);
369
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
235
sysbus_init_mmio(sbd, &s->mem);
370
-
236
371
-# This slightly misuses the 'description', but is the best way to get
237
- qbus_create_inplace(&s->adb_bus, sizeof(s->adb_bus), TYPE_ADB_BUS,
372
-# the manual title to appear in the sidebar.
238
- DEVICE(obj), "adb.0");
373
-html_theme_options['description'] = \
239
+ qbus_init(&s->adb_bus, sizeof(s->adb_bus), TYPE_ADB_BUS,
374
- u'Tools Guide'
240
+ DEVICE(obj), "adb.0");
375
-
241
}
376
-# One entry per manual page. List of tuples
242
377
-# (source start file, name, description, authors, manual section).
243
static Property cuda_properties[] = {
378
-man_pages = [
244
diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c
379
- ('qemu-img', 'qemu-img', u'QEMU disk image utility',
245
index XXXXXXX..XXXXXXX 100644
380
- ['Fabrice Bellard'], 1),
246
--- a/hw/misc/macio/macio.c
381
- ('qemu-storage-daemon', 'qemu-storage-daemon', u'QEMU storage daemon',
247
+++ b/hw/misc/macio/macio.c
382
- [], 1),
248
@@ -XXX,XX +XXX,XX @@ static void macio_instance_init(Object *obj)
383
- ('qemu-nbd', 'qemu-nbd', u'QEMU Disk Network Block Device Server',
249
384
- ['Anthony Liguori <anthony@codemonkey.ws>'], 8),
250
memory_region_init(&s->bar, obj, "macio", 0x80000);
385
- ('qemu-pr-helper', 'qemu-pr-helper', 'QEMU persistent reservation helper',
251
386
- [], 8),
252
- qbus_create_inplace(&s->macio_bus, sizeof(s->macio_bus), TYPE_MACIO_BUS,
387
- ('qemu-trace-stap', 'qemu-trace-stap', u'QEMU SystemTap trace tool',
253
- DEVICE(obj), "macio.0");
388
- [], 1),
254
+ qbus_init(&s->macio_bus, sizeof(s->macio_bus), TYPE_MACIO_BUS,
389
- ('virtfs-proxy-helper', 'virtfs-proxy-helper',
255
+ DEVICE(obj), "macio.0");
390
- u'QEMU 9p virtfs proxy filesystem helper',
256
391
- ['M. Mohan Kumar'], 1),
257
object_initialize_child(OBJECT(s), "dbdma", &s->dbdma, TYPE_MAC_DBDMA);
392
- ('virtiofsd', 'virtiofsd', u'QEMU virtio-fs shared file system daemon',
258
393
- ['Stefan Hajnoczi <stefanha@redhat.com>',
259
diff --git a/hw/misc/macio/pmu.c b/hw/misc/macio/pmu.c
394
- 'Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>'], 1),
260
index XXXXXXX..XXXXXXX 100644
395
-]
261
--- a/hw/misc/macio/pmu.c
396
diff --git a/docs/user/conf.py b/docs/user/conf.py
262
+++ b/hw/misc/macio/pmu.c
397
deleted file mode 100644
263
@@ -XXX,XX +XXX,XX @@ static void pmu_realize(DeviceState *dev, Error **errp)
398
index XXXXXXX..XXXXXXX
264
timer_mod(s->one_sec_timer, s->one_sec_target);
399
--- a/docs/user/conf.py
265
400
+++ /dev/null
266
if (s->has_adb) {
401
@@ -XXX,XX +XXX,XX @@
267
- qbus_create_inplace(&s->adb_bus, sizeof(s->adb_bus), TYPE_ADB_BUS,
402
-# -*- coding: utf-8 -*-
268
- dev, "adb.0");
403
-#
269
+ qbus_init(&s->adb_bus, sizeof(s->adb_bus), TYPE_ADB_BUS,
404
-# QEMU documentation build configuration file for the 'user' manual.
270
+ dev, "adb.0");
405
-#
271
adb_register_autopoll_callback(adb_bus, pmu_adb_poll, s);
406
-# This includes the top level conf file and then makes any necessary tweaks.
272
}
407
-import sys
273
}
408
-import os
274
diff --git a/hw/nubus/nubus-bridge.c b/hw/nubus/nubus-bridge.c
409
-
275
index XXXXXXX..XXXXXXX 100644
410
-qemu_docdir = os.path.abspath("..")
276
--- a/hw/nubus/nubus-bridge.c
411
-parent_config = os.path.join(qemu_docdir, "conf.py")
277
+++ b/hw/nubus/nubus-bridge.c
412
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
278
@@ -XXX,XX +XXX,XX @@ static void nubus_bridge_init(Object *obj)
413
-
279
NubusBridge *s = NUBUS_BRIDGE(obj);
414
-# This slightly misuses the 'description', but is the best way to get
280
NubusBus *bus = &s->bus;
415
-# the manual title to appear in the sidebar.
281
416
-html_theme_options['description'] = u'User Mode Emulation User''s Guide'
282
- qbus_create_inplace(bus, sizeof(s->bus), TYPE_NUBUS_BUS, DEVICE(s), NULL);
283
+ qbus_init(bus, sizeof(s->bus), TYPE_NUBUS_BUS, DEVICE(s), NULL);
284
285
qdev_init_gpio_out(DEVICE(s), bus->irqs, NUBUS_IRQS);
286
}
287
diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
288
index XXXXXXX..XXXXXXX 100644
289
--- a/hw/nvme/ctrl.c
290
+++ b/hw/nvme/ctrl.c
291
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
292
return;
293
}
294
295
- qbus_create_inplace(&n->bus, sizeof(NvmeBus), TYPE_NVME_BUS,
296
- &pci_dev->qdev, n->parent_obj.qdev.id);
297
+ qbus_init(&n->bus, sizeof(NvmeBus), TYPE_NVME_BUS,
298
+ &pci_dev->qdev, n->parent_obj.qdev.id);
299
300
nvme_init_state(n);
301
if (nvme_init_pci(n, pci_dev, errp)) {
302
diff --git a/hw/nvme/subsys.c b/hw/nvme/subsys.c
303
index XXXXXXX..XXXXXXX 100644
304
--- a/hw/nvme/subsys.c
305
+++ b/hw/nvme/subsys.c
306
@@ -XXX,XX +XXX,XX @@ static void nvme_subsys_realize(DeviceState *dev, Error **errp)
307
{
308
NvmeSubsystem *subsys = NVME_SUBSYS(dev);
309
310
- qbus_create_inplace(&subsys->bus, sizeof(NvmeBus), TYPE_NVME_BUS, dev,
311
- dev->id);
312
+ qbus_init(&subsys->bus, sizeof(NvmeBus), TYPE_NVME_BUS, dev, dev->id);
313
314
nvme_subsys_setup(subsys);
315
}
316
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
317
index XXXXXXX..XXXXXXX 100644
318
--- a/hw/pci/pci.c
319
+++ b/hw/pci/pci.c
320
@@ -XXX,XX +XXX,XX @@ void pci_root_bus_init(PCIBus *bus, size_t bus_size, DeviceState *parent,
321
MemoryRegion *address_space_io,
322
uint8_t devfn_min, const char *typename)
323
{
324
- qbus_create_inplace(bus, bus_size, typename, parent, name);
325
+ qbus_init(bus, bus_size, typename, parent, name);
326
pci_root_bus_internal_init(bus, parent, address_space_mem,
327
address_space_io, devfn_min);
328
}
329
diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
330
index XXXXXXX..XXXXXXX 100644
331
--- a/hw/pci/pci_bridge.c
332
+++ b/hw/pci/pci_bridge.c
333
@@ -XXX,XX +XXX,XX @@ void pci_bridge_initfn(PCIDevice *dev, const char *typename)
334
br->bus_name = dev->qdev.id;
335
}
336
337
- qbus_create_inplace(sec_bus, sizeof(br->sec_bus), typename, DEVICE(dev),
338
- br->bus_name);
339
+ qbus_init(sec_bus, sizeof(br->sec_bus), typename, DEVICE(dev),
340
+ br->bus_name);
341
sec_bus->parent_dev = dev;
342
sec_bus->map_irq = br->map_irq ? br->map_irq : pci_swizzle_map_irq_fn;
343
sec_bus->address_space_mem = &br->address_space_mem;
344
diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c
345
index XXXXXXX..XXXXXXX 100644
346
--- a/hw/s390x/event-facility.c
347
+++ b/hw/s390x/event-facility.c
348
@@ -XXX,XX +XXX,XX @@ static void init_event_facility(Object *obj)
349
sclp_event_set_allow_all_mask_sizes);
350
351
/* Spawn a new bus for SCLP events */
352
- qbus_create_inplace(&event_facility->sbus, sizeof(event_facility->sbus),
353
- TYPE_SCLP_EVENTS_BUS, sdev, NULL);
354
+ qbus_init(&event_facility->sbus, sizeof(event_facility->sbus),
355
+ TYPE_SCLP_EVENTS_BUS, sdev, NULL);
356
357
object_initialize_child(obj, TYPE_SCLP_QUIESCE,
358
&event_facility->quiesce,
359
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
360
index XXXXXXX..XXXXXXX 100644
361
--- a/hw/s390x/virtio-ccw.c
362
+++ b/hw/s390x/virtio-ccw.c
363
@@ -XXX,XX +XXX,XX @@ static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size,
364
DeviceState *qdev = DEVICE(dev);
365
char virtio_bus_name[] = "virtio-bus";
366
367
- qbus_create_inplace(bus, bus_size, TYPE_VIRTIO_CCW_BUS,
368
- qdev, virtio_bus_name);
369
+ qbus_init(bus, bus_size, TYPE_VIRTIO_CCW_BUS, qdev, virtio_bus_name);
370
}
371
372
static void virtio_ccw_bus_class_init(ObjectClass *klass, void *data)
373
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
374
index XXXXXXX..XXXXXXX 100644
375
--- a/hw/scsi/scsi-bus.c
376
+++ b/hw/scsi/scsi-bus.c
377
@@ -XXX,XX +XXX,XX @@ void scsi_device_unit_attention_reported(SCSIDevice *s)
378
void scsi_bus_init_named(SCSIBus *bus, size_t bus_size, DeviceState *host,
379
const SCSIBusInfo *info, const char *bus_name)
380
{
381
- qbus_create_inplace(bus, bus_size, TYPE_SCSI_BUS, host, bus_name);
382
+ qbus_init(bus, bus_size, TYPE_SCSI_BUS, host, bus_name);
383
bus->busnr = next_scsi_bus++;
384
bus->info = info;
385
qbus_set_bus_hotplug_handler(BUS(bus));
386
diff --git a/hw/sd/allwinner-sdhost.c b/hw/sd/allwinner-sdhost.c
387
index XXXXXXX..XXXXXXX 100644
388
--- a/hw/sd/allwinner-sdhost.c
389
+++ b/hw/sd/allwinner-sdhost.c
390
@@ -XXX,XX +XXX,XX @@ static void allwinner_sdhost_init(Object *obj)
391
{
392
AwSdHostState *s = AW_SDHOST(obj);
393
394
- qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
395
- TYPE_AW_SDHOST_BUS, DEVICE(s), "sd-bus");
396
+ qbus_init(&s->sdbus, sizeof(s->sdbus),
397
+ TYPE_AW_SDHOST_BUS, DEVICE(s), "sd-bus");
398
399
memory_region_init_io(&s->iomem, obj, &allwinner_sdhost_ops, s,
400
TYPE_AW_SDHOST, 4 * KiB);
401
diff --git a/hw/sd/bcm2835_sdhost.c b/hw/sd/bcm2835_sdhost.c
402
index XXXXXXX..XXXXXXX 100644
403
--- a/hw/sd/bcm2835_sdhost.c
404
+++ b/hw/sd/bcm2835_sdhost.c
405
@@ -XXX,XX +XXX,XX @@ static void bcm2835_sdhost_init(Object *obj)
406
{
407
BCM2835SDHostState *s = BCM2835_SDHOST(obj);
408
409
- qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
410
- TYPE_BCM2835_SDHOST_BUS, DEVICE(s), "sd-bus");
411
+ qbus_init(&s->sdbus, sizeof(s->sdbus),
412
+ TYPE_BCM2835_SDHOST_BUS, DEVICE(s), "sd-bus");
413
414
memory_region_init_io(&s->iomem, obj, &bcm2835_sdhost_ops, s,
415
TYPE_BCM2835_SDHOST, 0x1000);
416
diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
417
index XXXXXXX..XXXXXXX 100644
418
--- a/hw/sd/pl181.c
419
+++ b/hw/sd/pl181.c
420
@@ -XXX,XX +XXX,XX @@ static void pl181_init(Object *obj)
421
qdev_init_gpio_out_named(dev, &s->card_readonly, "card-read-only", 1);
422
qdev_init_gpio_out_named(dev, &s->card_inserted, "card-inserted", 1);
423
424
- qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
425
- TYPE_PL181_BUS, dev, "sd-bus");
426
+ qbus_init(&s->sdbus, sizeof(s->sdbus), TYPE_PL181_BUS, dev, "sd-bus");
427
}
428
429
static void pl181_class_init(ObjectClass *klass, void *data)
430
diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c
431
index XXXXXXX..XXXXXXX 100644
432
--- a/hw/sd/pxa2xx_mmci.c
433
+++ b/hw/sd/pxa2xx_mmci.c
434
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_mmci_instance_init(Object *obj)
435
qdev_init_gpio_out_named(dev, &s->rx_dma, "rx-dma", 1);
436
qdev_init_gpio_out_named(dev, &s->tx_dma, "tx-dma", 1);
437
438
- qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
439
- TYPE_PXA2XX_MMCI_BUS, DEVICE(obj), "sd-bus");
440
+ qbus_init(&s->sdbus, sizeof(s->sdbus),
441
+ TYPE_PXA2XX_MMCI_BUS, DEVICE(obj), "sd-bus");
442
}
443
444
static void pxa2xx_mmci_class_init(ObjectClass *klass, void *data)
445
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
446
index XXXXXXX..XXXXXXX 100644
447
--- a/hw/sd/sdhci.c
448
+++ b/hw/sd/sdhci.c
449
@@ -XXX,XX +XXX,XX @@ static void sdhci_init_readonly_registers(SDHCIState *s, Error **errp)
450
451
void sdhci_initfn(SDHCIState *s)
452
{
453
- qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
454
- TYPE_SDHCI_BUS, DEVICE(s), "sd-bus");
455
+ qbus_init(&s->sdbus, sizeof(s->sdbus), TYPE_SDHCI_BUS, DEVICE(s), "sd-bus");
456
457
s->insert_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_raise_insertion_irq, s);
458
s->transfer_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_data_transfer, s);
459
diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c
460
index XXXXXXX..XXXXXXX 100644
461
--- a/hw/sd/ssi-sd.c
462
+++ b/hw/sd/ssi-sd.c
463
@@ -XXX,XX +XXX,XX @@ static void ssi_sd_realize(SSIPeripheral *d, Error **errp)
464
DeviceState *carddev;
465
DriveInfo *dinfo;
466
467
- qbus_create_inplace(&s->sdbus, sizeof(s->sdbus), TYPE_SD_BUS,
468
- DEVICE(d), "sd-bus");
469
+ qbus_init(&s->sdbus, sizeof(s->sdbus), TYPE_SD_BUS, DEVICE(d), "sd-bus");
470
471
/* Create and plug in the sd card */
472
/* FIXME use a qdev drive property instead of drive_get_next() */
473
diff --git a/hw/usb/bus.c b/hw/usb/bus.c
474
index XXXXXXX..XXXXXXX 100644
475
--- a/hw/usb/bus.c
476
+++ b/hw/usb/bus.c
477
@@ -XXX,XX +XXX,XX @@ const VMStateDescription vmstate_usb_device = {
478
void usb_bus_new(USBBus *bus, size_t bus_size,
479
USBBusOps *ops, DeviceState *host)
480
{
481
- qbus_create_inplace(bus, bus_size, TYPE_USB_BUS, host, NULL);
482
+ qbus_init(bus, bus_size, TYPE_USB_BUS, host, NULL);
483
qbus_set_bus_hotplug_handler(BUS(bus));
484
bus->ops = ops;
485
bus->busnr = next_usb_bus++;
486
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
487
index XXXXXXX..XXXXXXX 100644
488
--- a/hw/usb/dev-smartcard-reader.c
489
+++ b/hw/usb/dev-smartcard-reader.c
490
@@ -XXX,XX +XXX,XX @@ static void ccid_realize(USBDevice *dev, Error **errp)
491
492
usb_desc_create_serial(dev);
493
usb_desc_init(dev);
494
- qbus_create_inplace(&s->bus, sizeof(s->bus), TYPE_CCID_BUS, DEVICE(dev),
495
- NULL);
496
+ qbus_init(&s->bus, sizeof(s->bus), TYPE_CCID_BUS, DEVICE(dev), NULL);
497
qbus_set_hotplug_handler(BUS(&s->bus), OBJECT(dev));
498
s->intr = usb_ep_get(dev, USB_TOKEN_IN, CCID_INT_IN_EP);
499
s->bulk = usb_ep_get(dev, USB_TOKEN_IN, CCID_BULK_IN_EP);
500
diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c
501
index XXXXXXX..XXXXXXX 100644
502
--- a/hw/virtio/virtio-mmio.c
503
+++ b/hw/virtio/virtio-mmio.c
504
@@ -XXX,XX +XXX,XX @@ static void virtio_mmio_realizefn(DeviceState *d, Error **errp)
505
VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
506
SysBusDevice *sbd = SYS_BUS_DEVICE(d);
507
508
- qbus_create_inplace(&proxy->bus, sizeof(proxy->bus), TYPE_VIRTIO_MMIO_BUS,
509
- d, NULL);
510
+ qbus_init(&proxy->bus, sizeof(proxy->bus), TYPE_VIRTIO_MMIO_BUS, d, NULL);
511
sysbus_init_irq(sbd, &proxy->irq);
512
513
if (!kvm_eventfds_enabled()) {
514
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
515
index XXXXXXX..XXXXXXX 100644
516
--- a/hw/virtio/virtio-pci.c
517
+++ b/hw/virtio/virtio-pci.c
518
@@ -XXX,XX +XXX,XX @@ static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size,
519
DeviceState *qdev = DEVICE(dev);
520
char virtio_bus_name[] = "virtio-bus";
521
522
- qbus_create_inplace(bus, bus_size, TYPE_VIRTIO_PCI_BUS, qdev,
523
- virtio_bus_name);
524
+ qbus_init(bus, bus_size, TYPE_VIRTIO_PCI_BUS, qdev, virtio_bus_name);
525
}
526
527
static void virtio_pci_bus_class_init(ObjectClass *klass, void *data)
528
--
417
--
529
2.20.1
418
2.20.1
530
419
531
420
diff view generated by jsdifflib
1
Currently we send VFP XML which includes D0..D15 or D0..D31, plus
1
In commit cd8be50e58f63413c0 we converted the A32 coprocessor
2
FPSID, FPSCR and FPEXC. The upstream GDB tolerates this, but its
2
insns to decodetree. This accidentally broke XScale/iWMMXt insns,
3
definition of this XML feature does not include FPSID or FPEXC. In
3
because it moved the handling of "cp insns which are handled
4
particular, for M-profile cores there are no FPSID or FPEXC
4
by looking up the cp register in the hashtable" from after the
5
registers, so advertising those is wrong.
5
call to the legacy disas_xscale_insn() decode to before it,
6
with the result that all XScale/iWMMXt insns now UNDEF.
6
7
7
Move FPSID and FPEXC into their own bit of XML which we only send for
8
Update valid_cp() so that it knows that on XScale cp 0 and 1
8
A and R profile cores. This brings our definition of the XML
9
are not standard coprocessor instructions; this will cause
9
org.gnu.gdb.arm.vfp feature into line with GDB's own (at least for
10
the decodetree trans_ functions to ignore them, so that
10
non-Neon cores...) and means we don't claim to have FPSID and FPEXC
11
execution will correctly get through to the legacy decode again.
11
on M-profile.
12
12
13
(It seems unlikely to me that any gdbstub users really care about
13
Cc: qemu-stable@nongnu.org
14
being able to look at FPEXC and FPSID; but we've supplied them to gdb
14
Reported-by: Guenter Roeck <linux@roeck-us.net>
15
for a decade and it's not hard to keep doing so.)
16
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Message-id: 20210921162901.17508-5-peter.maydell@linaro.org
17
Tested-by: Guenter Roeck <linux@roeck-us.net>
18
Message-id: 20210108195157.32067-1-peter.maydell@linaro.org
20
---
19
---
21
configs/targets/aarch64-softmmu.mak | 2 +-
20
target/arm/translate.c | 7 +++++++
22
configs/targets/arm-linux-user.mak | 2 +-
21
1 file changed, 7 insertions(+)
23
configs/targets/arm-softmmu.mak | 2 +-
24
configs/targets/armeb-linux-user.mak | 2 +-
25
target/arm/gdbstub.c | 56 ++++++++++++++++++++--------
26
gdb-xml/arm-neon.xml | 2 -
27
gdb-xml/arm-vfp-sysregs.xml | 17 +++++++++
28
gdb-xml/arm-vfp.xml | 2 -
29
gdb-xml/arm-vfp3.xml | 2 -
30
9 files changed, 61 insertions(+), 26 deletions(-)
31
create mode 100644 gdb-xml/arm-vfp-sysregs.xml
32
22
33
diff --git a/configs/targets/aarch64-softmmu.mak b/configs/targets/aarch64-softmmu.mak
23
diff --git a/target/arm/translate.c b/target/arm/translate.c
34
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
35
--- a/configs/targets/aarch64-softmmu.mak
25
--- a/target/arm/translate.c
36
+++ b/configs/targets/aarch64-softmmu.mak
26
+++ b/target/arm/translate.c
37
@@ -XXX,XX +XXX,XX @@
27
@@ -XXX,XX +XXX,XX @@ static bool valid_cp(DisasContext *s, int cp)
38
TARGET_ARCH=aarch64
28
* only cp14 and cp15 are valid, and other values aren't considered
39
TARGET_BASE_ARCH=arm
29
* to be in the coprocessor-instruction space at all. v8M still
40
TARGET_SUPPORTS_MTTCG=y
30
* permits coprocessors 0..7.
41
-TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
31
+ * For XScale, we must not decode the XScale cp0, cp1 space as
42
+TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
32
+ * a standard coprocessor insn, because we want to fall through to
43
TARGET_NEED_FDT=y
33
+ * the legacy disas_xscale_insn() decoder after decodetree is done.
44
diff --git a/configs/targets/arm-linux-user.mak b/configs/targets/arm-linux-user.mak
34
*/
45
index XXXXXXX..XXXXXXX 100644
35
+ if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cp == 0 || cp == 1)) {
46
--- a/configs/targets/arm-linux-user.mak
36
+ return false;
47
+++ b/configs/targets/arm-linux-user.mak
48
@@ -XXX,XX +XXX,XX @@
49
TARGET_ARCH=arm
50
TARGET_SYSTBL_ABI=common,oabi
51
TARGET_SYSTBL=syscall.tbl
52
-TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
53
+TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
54
TARGET_HAS_BFLT=y
55
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
56
diff --git a/configs/targets/arm-softmmu.mak b/configs/targets/arm-softmmu.mak
57
index XXXXXXX..XXXXXXX 100644
58
--- a/configs/targets/arm-softmmu.mak
59
+++ b/configs/targets/arm-softmmu.mak
60
@@ -XXX,XX +XXX,XX @@
61
TARGET_ARCH=arm
62
TARGET_SUPPORTS_MTTCG=y
63
-TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
64
+TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
65
TARGET_NEED_FDT=y
66
diff --git a/configs/targets/armeb-linux-user.mak b/configs/targets/armeb-linux-user.mak
67
index XXXXXXX..XXXXXXX 100644
68
--- a/configs/targets/armeb-linux-user.mak
69
+++ b/configs/targets/armeb-linux-user.mak
70
@@ -XXX,XX +XXX,XX @@ TARGET_ARCH=arm
71
TARGET_SYSTBL_ABI=common,oabi
72
TARGET_SYSTBL=syscall.tbl
73
TARGET_WORDS_BIGENDIAN=y
74
-TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
75
+TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
76
TARGET_HAS_BFLT=y
77
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
78
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
79
index XXXXXXX..XXXXXXX 100644
80
--- a/target/arm/gdbstub.c
81
+++ b/target/arm/gdbstub.c
82
@@ -XXX,XX +XXX,XX @@ static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
83
}
84
switch (reg - nregs) {
85
case 0:
86
- return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]);
87
- case 1:
88
return gdb_get_reg32(buf, vfp_get_fpscr(env));
89
- case 2:
90
- return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]);
91
}
92
return 0;
93
}
94
@@ -XXX,XX +XXX,XX @@ static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
95
}
96
}
97
switch (reg - nregs) {
98
+ case 0:
99
+ vfp_set_fpscr(env, ldl_p(buf));
100
+ return 4;
101
+ }
37
+ }
102
+ return 0;
103
+}
104
+
38
+
105
+static int vfp_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg)
39
if (arm_dc_feature(s, ARM_FEATURE_V8) &&
106
+{
40
!arm_dc_feature(s, ARM_FEATURE_M)) {
107
+ switch (reg) {
41
return cp >= 14;
108
+ case 0:
109
+ return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]);
110
+ case 1:
111
+ return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]);
112
+ }
113
+ return 0;
114
+}
115
+
116
+static int vfp_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg)
117
+{
118
+ switch (reg) {
119
case 0:
120
env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf);
121
return 4;
122
case 1:
123
- vfp_set_fpscr(env, ldl_p(buf));
124
- return 4;
125
- case 2:
126
env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30);
127
return 4;
128
}
129
@@ -XXX,XX +XXX,XX @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
130
34, "aarch64-fpu.xml", 0);
131
}
132
#endif
133
- } else if (arm_feature(env, ARM_FEATURE_NEON)) {
134
- gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
135
- 51, "arm-neon.xml", 0);
136
- } else if (cpu_isar_feature(aa32_simd_r32, cpu)) {
137
- gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
138
- 35, "arm-vfp3.xml", 0);
139
- } else if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
140
- gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
141
- 19, "arm-vfp.xml", 0);
142
+ } else {
143
+ if (arm_feature(env, ARM_FEATURE_NEON)) {
144
+ gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
145
+ 49, "arm-neon.xml", 0);
146
+ } else if (cpu_isar_feature(aa32_simd_r32, cpu)) {
147
+ gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
148
+ 33, "arm-vfp3.xml", 0);
149
+ } else if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
150
+ gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
151
+ 17, "arm-vfp.xml", 0);
152
+ }
153
+ if (!arm_feature(env, ARM_FEATURE_M)) {
154
+ /*
155
+ * A and R profile have FP sysregs FPEXC and FPSID that we
156
+ * expose to gdb.
157
+ */
158
+ gdb_register_coprocessor(cs, vfp_gdb_get_sysreg, vfp_gdb_set_sysreg,
159
+ 2, "arm-vfp-sysregs.xml", 0);
160
+ }
161
}
162
gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg,
163
arm_gen_dynamic_sysreg_xml(cs, cs->gdb_num_regs),
164
diff --git a/gdb-xml/arm-neon.xml b/gdb-xml/arm-neon.xml
165
index XXXXXXX..XXXXXXX 100644
166
--- a/gdb-xml/arm-neon.xml
167
+++ b/gdb-xml/arm-neon.xml
168
@@ -XXX,XX +XXX,XX @@
169
<reg name="q14" bitsize="128" type="neon_q"/>
170
<reg name="q15" bitsize="128" type="neon_q"/>
171
172
- <reg name="fpsid" bitsize="32" type="int" group="float"/>
173
<reg name="fpscr" bitsize="32" type="int" group="float"/>
174
- <reg name="fpexc" bitsize="32" type="int" group="float"/>
175
</feature>
176
diff --git a/gdb-xml/arm-vfp-sysregs.xml b/gdb-xml/arm-vfp-sysregs.xml
177
new file mode 100644
178
index XXXXXXX..XXXXXXX
179
--- /dev/null
180
+++ b/gdb-xml/arm-vfp-sysregs.xml
181
@@ -XXX,XX +XXX,XX @@
182
+<?xml version="1.0"?>
183
+<!-- Copyright (C) 2021 Linaro Ltd.
184
+
185
+ Copying and distribution of this file, with or without modification,
186
+ are permitted in any medium without royalty provided the copyright
187
+ notice and this notice are preserved.
188
+
189
+ These are A/R profile VFP system registers. Debugger users probably
190
+ don't really care about these, but because we used to (incorrectly)
191
+ provide them to gdb in the org.gnu.gdb.arm.vfp XML we continue
192
+ to do so via this separate XML.
193
+ -->
194
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
195
+<feature name="org.qemu.gdb.arm.vfp-sysregs">
196
+ <reg name="fpsid" bitsize="32" type="int" group="float"/>
197
+ <reg name="fpexc" bitsize="32" type="int" group="float"/>
198
+</feature>
199
diff --git a/gdb-xml/arm-vfp.xml b/gdb-xml/arm-vfp.xml
200
index XXXXXXX..XXXXXXX 100644
201
--- a/gdb-xml/arm-vfp.xml
202
+++ b/gdb-xml/arm-vfp.xml
203
@@ -XXX,XX +XXX,XX @@
204
<reg name="d14" bitsize="64" type="float"/>
205
<reg name="d15" bitsize="64" type="float"/>
206
207
- <reg name="fpsid" bitsize="32" type="int" group="float"/>
208
<reg name="fpscr" bitsize="32" type="int" group="float"/>
209
- <reg name="fpexc" bitsize="32" type="int" group="float"/>
210
</feature>
211
diff --git a/gdb-xml/arm-vfp3.xml b/gdb-xml/arm-vfp3.xml
212
index XXXXXXX..XXXXXXX 100644
213
--- a/gdb-xml/arm-vfp3.xml
214
+++ b/gdb-xml/arm-vfp3.xml
215
@@ -XXX,XX +XXX,XX @@
216
<reg name="d30" bitsize="64" type="float"/>
217
<reg name="d31" bitsize="64" type="float"/>
218
219
- <reg name="fpsid" bitsize="32" type="int" group="float"/>
220
<reg name="fpscr" bitsize="32" type="int" group="float"/>
221
- <reg name="fpexc" bitsize="32" type="int" group="float"/>
222
</feature>
223
--
42
--
224
2.20.1
43
2.20.1
225
44
226
45
diff view generated by jsdifflib
1
Rename ipack_bus_new_inplace() to ipack_bus_init(), to bring it in to
1
A copy-and-paste error meant that the return value for register offset 0x44
2
line with a "_init for in-place init, _new for allocate-and-return"
2
(the RX Status FIFO PEEK register) returned a byte from a bogus offset in
3
convention. Drop the 'name' argument, because the only caller does
3
the rx status FIFO. Fix the typo.
4
not pass in a name. If a future caller does need to specify the bus
5
name, we should create an ipack_bus_init_named() function at that
6
point.
7
4
5
Cc: qemu-stable@nongnu.org
6
Fixes: https://bugs.launchpad.net/qemu/+bug/1904954
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
9
Message-id: 20210108180401.2263-2-peter.maydell@linaro.org
11
Message-id: 20210923121153.23754-3-peter.maydell@linaro.org
12
---
10
---
13
include/hw/ipack/ipack.h | 8 ++++----
11
hw/net/lan9118.c | 2 +-
14
hw/ipack/ipack.c | 10 +++++-----
12
1 file changed, 1 insertion(+), 1 deletion(-)
15
hw/ipack/tpci200.c | 4 ++--
16
3 files changed, 11 insertions(+), 11 deletions(-)
17
13
18
diff --git a/include/hw/ipack/ipack.h b/include/hw/ipack/ipack.h
14
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
19
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/ipack/ipack.h
16
--- a/hw/net/lan9118.c
21
+++ b/include/hw/ipack/ipack.h
17
+++ b/hw/net/lan9118.c
22
@@ -XXX,XX +XXX,XX @@ extern const VMStateDescription vmstate_ipack_device;
18
@@ -XXX,XX +XXX,XX @@ static uint64_t lan9118_readl(void *opaque, hwaddr offset,
23
VMSTATE_STRUCT(_field, _state, 1, vmstate_ipack_device, IPackDevice)
19
case 0x40:
24
20
return rx_status_fifo_pop(s);
25
IPackDevice *ipack_device_find(IPackBus *bus, int32_t slot);
21
case 0x44:
26
-void ipack_bus_new_inplace(IPackBus *bus, size_t bus_size,
22
- return s->rx_status_fifo[s->tx_status_fifo_head];
27
- DeviceState *parent,
23
+ return s->rx_status_fifo[s->rx_status_fifo_head];
28
- const char *name, uint8_t n_slots,
24
case 0x48:
29
- qemu_irq_handler handler);
25
return tx_status_fifo_pop(s);
30
+void ipack_bus_init(IPackBus *bus, size_t bus_size,
26
case 0x4c:
31
+ DeviceState *parent,
32
+ uint8_t n_slots,
33
+ qemu_irq_handler handler);
34
35
#endif
36
diff --git a/hw/ipack/ipack.c b/hw/ipack/ipack.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/hw/ipack/ipack.c
39
+++ b/hw/ipack/ipack.c
40
@@ -XXX,XX +XXX,XX @@ IPackDevice *ipack_device_find(IPackBus *bus, int32_t slot)
41
return NULL;
42
}
43
44
-void ipack_bus_new_inplace(IPackBus *bus, size_t bus_size,
45
- DeviceState *parent,
46
- const char *name, uint8_t n_slots,
47
- qemu_irq_handler handler)
48
+void ipack_bus_init(IPackBus *bus, size_t bus_size,
49
+ DeviceState *parent,
50
+ uint8_t n_slots,
51
+ qemu_irq_handler handler)
52
{
53
- qbus_create_inplace(bus, bus_size, TYPE_IPACK_BUS, parent, name);
54
+ qbus_create_inplace(bus, bus_size, TYPE_IPACK_BUS, parent, NULL);
55
bus->n_slots = n_slots;
56
bus->set_irq = handler;
57
}
58
diff --git a/hw/ipack/tpci200.c b/hw/ipack/tpci200.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/hw/ipack/tpci200.c
61
+++ b/hw/ipack/tpci200.c
62
@@ -XXX,XX +XXX,XX @@ static void tpci200_realize(PCIDevice *pci_dev, Error **errp)
63
pci_register_bar(&s->dev, 4, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->las2);
64
pci_register_bar(&s->dev, 5, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->las3);
65
66
- ipack_bus_new_inplace(&s->bus, sizeof(s->bus), DEVICE(pci_dev), NULL,
67
- N_MODULES, tpci200_set_irq);
68
+ ipack_bus_init(&s->bus, sizeof(s->bus), DEVICE(pci_dev),
69
+ N_MODULES, tpci200_set_irq);
70
}
71
72
static const VMStateDescription vmstate_tpci200 = {
73
--
27
--
74
2.20.1
28
2.20.1
75
29
76
30
diff view generated by jsdifflib
1
We're going to move this code to a different file; fix the coding
1
The lan9118 code mostly uses symbolic constants for register offsets;
2
style first so checkpatch doesn't complain. This includes deleting
2
the exceptions are those which the datasheet doesn't give an official
3
the spurious 'break' statements after returns in the
3
symbolic name to.
4
vfp_gdb_get_reg() function.
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.
5
7
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210108180401.2263-3-peter.maydell@linaro.org
9
Message-id: 20210921162901.17508-3-peter.maydell@linaro.org
10
---
11
---
11
target/arm/helper.c | 23 ++++++++++++++++-------
12
hw/net/lan9118.c | 24 ++++++++++++++++++------
12
1 file changed, 16 insertions(+), 7 deletions(-)
13
1 file changed, 18 insertions(+), 6 deletions(-)
13
14
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
17
--- a/hw/net/lan9118.c
17
+++ b/target/arm/helper.c
18
+++ b/hw/net/lan9118.c
18
@@ -XXX,XX +XXX,XX @@ static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
19
@@ -XXX,XX +XXX,XX @@ do { hw_error("lan9118: error: " fmt , ## __VA_ARGS__);} while (0)
19
}
20
do { fprintf(stderr, "lan9118: error: " fmt , ## __VA_ARGS__);} while (0)
21
#endif
22
23
+/* The tx and rx fifo ports are a range of aliased 32-bit registers */
24
+#define RX_DATA_FIFO_PORT_FIRST 0x00
25
+#define RX_DATA_FIFO_PORT_LAST 0x1f
26
+#define TX_DATA_FIFO_PORT_FIRST 0x20
27
+#define TX_DATA_FIFO_PORT_LAST 0x3f
28
+
29
+#define RX_STATUS_FIFO_PORT 0x40
30
+#define RX_STATUS_FIFO_PEEK 0x44
31
+#define TX_STATUS_FIFO_PORT 0x48
32
+#define TX_STATUS_FIFO_PEEK 0x4c
33
+
34
#define CSR_ID_REV 0x50
35
#define CSR_IRQ_CFG 0x54
36
#define CSR_INT_STS 0x58
37
@@ -XXX,XX +XXX,XX @@ static void lan9118_writel(void *opaque, hwaddr offset,
38
offset &= 0xff;
39
40
//DPRINTF("Write reg 0x%02x = 0x%08x\n", (int)offset, val);
41
- if (offset >= 0x20 && offset < 0x40) {
42
+ if (offset >= TX_DATA_FIFO_PORT_FIRST &&
43
+ offset <= TX_DATA_FIFO_PORT_LAST) {
44
/* TX FIFO */
45
tx_fifo_push(s, val);
46
return;
47
@@ -XXX,XX +XXX,XX @@ static uint64_t lan9118_readl(void *opaque, hwaddr offset,
48
lan9118_state *s = (lan9118_state *)opaque;
49
50
//DPRINTF("Read reg 0x%02x\n", (int)offset);
51
- if (offset < 0x20) {
52
+ if (offset <= RX_DATA_FIFO_PORT_LAST) {
53
/* RX FIFO */
54
return rx_fifo_pop(s);
20
}
55
}
21
switch (reg - nregs) {
56
switch (offset) {
22
- case 0: return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]); break;
57
- case 0x40:
23
- case 1: return gdb_get_reg32(buf, vfp_get_fpscr(env)); break;
58
+ case RX_STATUS_FIFO_PORT:
24
- case 2: return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]); break;
59
return rx_status_fifo_pop(s);
25
+ case 0:
60
- case 0x44:
26
+ return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]);
61
+ case RX_STATUS_FIFO_PEEK:
27
+ case 1:
62
return s->rx_status_fifo[s->rx_status_fifo_head];
28
+ return gdb_get_reg32(buf, vfp_get_fpscr(env));
63
- case 0x48:
29
+ case 2:
64
+ case TX_STATUS_FIFO_PORT:
30
+ return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]);
65
return tx_status_fifo_pop(s);
31
}
66
- case 0x4c:
32
return 0;
67
+ case TX_STATUS_FIFO_PEEK:
33
}
68
return s->tx_status_fifo[s->tx_status_fifo_head];
34
@@ -XXX,XX +XXX,XX @@ static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
69
case CSR_ID_REV:
35
}
70
return 0x01180001;
36
}
37
switch (reg - nregs) {
38
- case 0: env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf); return 4;
39
- case 1: vfp_set_fpscr(env, ldl_p(buf)); return 4;
40
- case 2: env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30); return 4;
41
+ case 0:
42
+ env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf);
43
+ return 4;
44
+ case 1:
45
+ vfp_set_fpscr(env, ldl_p(buf));
46
+ return 4;
47
+ case 2:
48
+ env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30);
49
+ return 4;
50
}
51
return 0;
52
}
53
@@ -XXX,XX +XXX,XX @@ static int aarch64_fpu_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
54
return gdb_get_reg32(buf, vfp_get_fpsr(env));
55
case 33:
56
/* FPCR */
57
- return gdb_get_reg32(buf,vfp_get_fpcr(env));
58
+ return gdb_get_reg32(buf, vfp_get_fpcr(env));
59
default:
60
return 0;
61
}
62
--
71
--
63
2.20.1
72
2.20.1
64
73
65
74
diff view generated by jsdifflib
1
From: Tong Ho <tong.ho@xilinx.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
This implements the Xilinx ZynqMP eFuse, an one-time
3
This patch allows NPCM7XX CLK module to compute clocks that are used by
4
field-programmable non-volatile storage device. There is
4
other NPCM7XX modules.
5
only one such device in the Xilinx ZynqMP product family.
6
5
7
Co-authored-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
6
Add a new struct NPCM7xxClockConverterState which represents a
8
Co-authored-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
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.
9
12
10
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
13
Each converter has a function pointer called "convert" which represents
11
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
14
the unique logic for that converter.
12
Signed-off-by: Tong Ho <tong.ho@xilinx.com>
15
13
Message-id: 20210917052400.1249094-4-tong.ho@xilinx.com
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>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
23
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
24
Message-id: 20210108190945.949196-2-wuhaotsh@google.com
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
26
---
17
include/hw/nvram/xlnx-zynqmp-efuse.h | 44 ++
27
include/hw/misc/npcm7xx_clk.h | 140 +++++-
18
hw/nvram/xlnx-zynqmp-efuse.c | 855 +++++++++++++++++++++++++++
28
hw/misc/npcm7xx_clk.c | 805 +++++++++++++++++++++++++++++++++-
19
hw/nvram/Kconfig | 4 +
29
2 files changed, 932 insertions(+), 13 deletions(-)
20
hw/nvram/meson.build | 2 +
21
4 files changed, 905 insertions(+)
22
create mode 100644 include/hw/nvram/xlnx-zynqmp-efuse.h
23
create mode 100644 hw/nvram/xlnx-zynqmp-efuse.c
24
30
25
diff --git a/include/hw/nvram/xlnx-zynqmp-efuse.h b/include/hw/nvram/xlnx-zynqmp-efuse.h
31
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
26
new file mode 100644
32
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX
33
--- a/include/hw/misc/npcm7xx_clk.h
28
--- /dev/null
34
+++ b/include/hw/misc/npcm7xx_clk.h
29
+++ b/include/hw/nvram/xlnx-zynqmp-efuse.h
30
@@ -XXX,XX +XXX,XX @@
35
@@ -XXX,XX +XXX,XX @@
36
#define NPCM7XX_CLK_H
37
38
#include "exec/memory.h"
39
+#include "hw/clock.h"
40
#include "hw/sysbus.h"
41
42
/*
43
@@ -XXX,XX +XXX,XX @@
44
45
#define NPCM7XX_WATCHDOG_RESET_GPIO_IN "npcm7xx-clk-watchdog-reset-gpio-in"
46
47
-typedef struct NPCM7xxCLKState {
48
+/* Maximum amount of clock inputs in a SEL module. */
49
+#define NPCM7XX_CLK_SEL_MAX_INPUT 5
50
+
51
+/* PLLs in CLK module. */
52
+typedef enum NPCM7xxClockPLL {
53
+ NPCM7XX_CLOCK_PLL0,
54
+ NPCM7XX_CLOCK_PLL1,
55
+ NPCM7XX_CLOCK_PLL2,
56
+ NPCM7XX_CLOCK_PLLG,
57
+ NPCM7XX_CLOCK_NR_PLLS,
58
+} NPCM7xxClockPLL;
59
+
60
+/* SEL/MUX in CLK module. */
61
+typedef enum NPCM7xxClockSEL {
62
+ NPCM7XX_CLOCK_PIXCKSEL,
63
+ NPCM7XX_CLOCK_MCCKSEL,
64
+ NPCM7XX_CLOCK_CPUCKSEL,
65
+ NPCM7XX_CLOCK_CLKOUTSEL,
66
+ NPCM7XX_CLOCK_UARTCKSEL,
67
+ NPCM7XX_CLOCK_TIMCKSEL,
68
+ NPCM7XX_CLOCK_SDCKSEL,
69
+ NPCM7XX_CLOCK_GFXMSEL,
70
+ NPCM7XX_CLOCK_SUCKSEL,
71
+ NPCM7XX_CLOCK_NR_SELS,
72
+} NPCM7xxClockSEL;
73
+
74
+/* Dividers in CLK module. */
75
+typedef enum NPCM7xxClockDivider {
76
+ NPCM7XX_CLOCK_PLL1D2, /* PLL1/2 */
77
+ NPCM7XX_CLOCK_PLL2D2, /* PLL2/2 */
78
+ NPCM7XX_CLOCK_MC_DIVIDER,
79
+ NPCM7XX_CLOCK_AXI_DIVIDER,
80
+ NPCM7XX_CLOCK_AHB_DIVIDER,
81
+ NPCM7XX_CLOCK_AHB3_DIVIDER,
82
+ NPCM7XX_CLOCK_SPI0_DIVIDER,
83
+ NPCM7XX_CLOCK_SPIX_DIVIDER,
84
+ NPCM7XX_CLOCK_APB1_DIVIDER,
85
+ NPCM7XX_CLOCK_APB2_DIVIDER,
86
+ NPCM7XX_CLOCK_APB3_DIVIDER,
87
+ NPCM7XX_CLOCK_APB4_DIVIDER,
88
+ NPCM7XX_CLOCK_APB5_DIVIDER,
89
+ NPCM7XX_CLOCK_CLKOUT_DIVIDER,
90
+ NPCM7XX_CLOCK_UART_DIVIDER,
91
+ NPCM7XX_CLOCK_TIMER_DIVIDER,
92
+ NPCM7XX_CLOCK_ADC_DIVIDER,
93
+ NPCM7XX_CLOCK_MMC_DIVIDER,
94
+ NPCM7XX_CLOCK_SDHC_DIVIDER,
95
+ NPCM7XX_CLOCK_GFXM_DIVIDER, /* divide by 3 */
96
+ NPCM7XX_CLOCK_UTMI_DIVIDER,
97
+ NPCM7XX_CLOCK_NR_DIVIDERS,
98
+} NPCM7xxClockConverter;
99
+
100
+typedef struct NPCM7xxCLKState NPCM7xxCLKState;
101
+
102
+/**
103
+ * struct NPCM7xxClockPLLState - A PLL module in CLK module.
104
+ * @name: The name of the module.
105
+ * @clk: The CLK module that owns this module.
106
+ * @clock_in: The input clock of this module.
107
+ * @clock_out: The output clock of this module.
108
+ * @reg: The control registers for this PLL module.
109
+ */
110
+typedef struct NPCM7xxClockPLLState {
111
+ DeviceState parent;
112
+
113
+ const char *name;
114
+ NPCM7xxCLKState *clk;
115
+ Clock *clock_in;
116
+ Clock *clock_out;
117
+
118
+ int reg;
119
+} NPCM7xxClockPLLState;
120
+
121
+/**
122
+ * struct NPCM7xxClockSELState - A SEL module in CLK module.
123
+ * @name: The name of the module.
124
+ * @clk: The CLK module that owns this module.
125
+ * @input_size: The size of inputs of this module.
126
+ * @clock_in: The input clocks of this module.
127
+ * @clock_out: The output clocks of this module.
128
+ * @offset: The offset of this module in the control register.
129
+ * @len: The length of this module in the control register.
130
+ */
131
+typedef struct NPCM7xxClockSELState {
132
+ DeviceState parent;
133
+
134
+ const char *name;
135
+ NPCM7xxCLKState *clk;
136
+ uint8_t input_size;
137
+ Clock *clock_in[NPCM7XX_CLK_SEL_MAX_INPUT];
138
+ Clock *clock_out;
139
+
140
+ int offset;
141
+ int len;
142
+} NPCM7xxClockSELState;
143
+
144
+/**
145
+ * struct NPCM7xxClockDividerState - A Divider module in CLK module.
146
+ * @name: The name of the module.
147
+ * @clk: The CLK module that owns this module.
148
+ * @clock_in: The input clock of this module.
149
+ * @clock_out: The output clock of this module.
150
+ * @divide: The function the divider uses to divide the input.
151
+ * @reg: The index of the control register that contains the divisor.
152
+ * @offset: The offset of the divisor in the control register.
153
+ * @len: The length of the divisor in the control register.
154
+ * @divisor: The divisor for a constant divisor
155
+ */
156
+typedef struct NPCM7xxClockDividerState {
157
+ DeviceState parent;
158
+
159
+ const char *name;
160
+ NPCM7xxCLKState *clk;
161
+ Clock *clock_in;
162
+ Clock *clock_out;
163
+
164
+ uint32_t (*divide)(struct NPCM7xxClockDividerState *s);
165
+ union {
166
+ struct {
167
+ int reg;
168
+ int offset;
169
+ int len;
170
+ };
171
+ int divisor;
172
+ };
173
+} NPCM7xxClockDividerState;
174
+
175
+struct NPCM7xxCLKState {
176
SysBusDevice parent;
177
178
MemoryRegion iomem;
179
180
+ /* Clock converters */
181
+ NPCM7xxClockPLLState plls[NPCM7XX_CLOCK_NR_PLLS];
182
+ NPCM7xxClockSELState sels[NPCM7XX_CLOCK_NR_SELS];
183
+ NPCM7xxClockDividerState dividers[NPCM7XX_CLOCK_NR_DIVIDERS];
184
+
185
uint32_t regs[NPCM7XX_CLK_NR_REGS];
186
187
/* Time reference for SECCNT and CNTR25M, initialized by power on reset */
188
int64_t ref_ns;
189
-} NPCM7xxCLKState;
190
+
191
+ /* The incoming reference clock. */
192
+ Clock *clkref;
193
+};
194
195
#define TYPE_NPCM7XX_CLK "npcm7xx-clk"
196
#define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), TYPE_NPCM7XX_CLK)
197
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
198
index XXXXXXX..XXXXXXX 100644
199
--- a/hw/misc/npcm7xx_clk.c
200
+++ b/hw/misc/npcm7xx_clk.c
201
@@ -XXX,XX +XXX,XX @@
202
203
#include "hw/misc/npcm7xx_clk.h"
204
#include "hw/timer/npcm7xx_timer.h"
205
+#include "hw/qdev-clock.h"
206
#include "migration/vmstate.h"
207
#include "qemu/error-report.h"
208
#include "qemu/log.h"
209
@@ -XXX,XX +XXX,XX @@
210
#include "trace.h"
211
#include "sysemu/watchdog.h"
212
31
+/*
213
+/*
32
+ * Copyright (c) 2021 Xilinx Inc.
214
+ * The reference clock hz, and the SECCNT and CNTR25M registers in this module,
33
+ *
215
+ * is always 25 MHz.
34
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
35
+ * of this software and associated documentation files (the "Software"), to deal
36
+ * in the Software without restriction, including without limitation the rights
37
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
38
+ * copies of the Software, and to permit persons to whom the Software is
39
+ * furnished to do so, subject to the following conditions:
40
+ *
41
+ * The above copyright notice and this permission notice shall be included in
42
+ * all copies or substantial portions of the Software.
43
+ *
44
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
45
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
46
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
47
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
48
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
49
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
50
+ * THE SOFTWARE.
51
+ */
216
+ */
52
+#ifndef XLNX_ZYNQMP_EFUSE_H
217
+#define NPCM7XX_CLOCK_REF_HZ (25000000)
53
+#define XLNX_ZYNQMP_EFUSE_H
218
+
54
+
219
+/* Register Field Definitions */
55
+#include "hw/irq.h"
220
+#define NPCM7XX_CLK_WDRCR_CA9C BIT(0) /* Cortex A9 Cores */
56
+#include "hw/sysbus.h"
221
+
57
+#include "hw/register.h"
222
#define PLLCON_LOKI BIT(31)
58
+#include "hw/nvram/xlnx-efuse.h"
223
#define PLLCON_LOKS BIT(30)
59
+
224
#define PLLCON_PWDEN BIT(12)
60
+#define XLNX_ZYNQMP_EFUSE_R_MAX ((0x10fc / 4) + 1)
225
+#define PLLCON_FBDV(con) extract32((con), 16, 12)
61
+
226
+#define PLLCON_OTDV2(con) extract32((con), 13, 3)
62
+#define TYPE_XLNX_ZYNQMP_EFUSE "xlnx,zynqmp-efuse"
227
+#define PLLCON_OTDV1(con) extract32((con), 8, 3)
63
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPEFuse, XLNX_ZYNQMP_EFUSE);
228
+#define PLLCON_INDV(con) extract32((con), 0, 6)
64
+
229
65
+struct XlnxZynqMPEFuse {
230
enum NPCM7xxCLKRegisters {
66
+ SysBusDevice parent_obj;
231
NPCM7XX_CLK_CLKEN1,
67
+ qemu_irq irq;
232
@@ -XXX,XX +XXX,XX @@ static const uint32_t cold_reset_values[NPCM7XX_CLK_NR_REGS] = {
68
+
233
[NPCM7XX_CLK_AHBCKFI] = 0x000000c8,
69
+ XlnxEFuse *efuse;
234
};
70
+ uint32_t regs[XLNX_ZYNQMP_EFUSE_R_MAX];
235
71
+ RegisterInfo regs_info[XLNX_ZYNQMP_EFUSE_R_MAX];
236
-/* Register Field Definitions */
237
-#define NPCM7XX_CLK_WDRCR_CA9C BIT(0) /* Cortex A9 Cores */
238
-
239
/* The number of watchdogs that can trigger a reset. */
240
#define NPCM7XX_NR_WATCHDOGS (3)
241
242
+/* Clock converter functions */
243
+
244
+#define TYPE_NPCM7XX_CLOCK_PLL "npcm7xx-clock-pll"
245
+#define NPCM7XX_CLOCK_PLL(obj) OBJECT_CHECK(NPCM7xxClockPLLState, \
246
+ (obj), TYPE_NPCM7XX_CLOCK_PLL)
247
+#define TYPE_NPCM7XX_CLOCK_SEL "npcm7xx-clock-sel"
248
+#define NPCM7XX_CLOCK_SEL(obj) OBJECT_CHECK(NPCM7xxClockSELState, \
249
+ (obj), TYPE_NPCM7XX_CLOCK_SEL)
250
+#define TYPE_NPCM7XX_CLOCK_DIVIDER "npcm7xx-clock-divider"
251
+#define NPCM7XX_CLOCK_DIVIDER(obj) OBJECT_CHECK(NPCM7xxClockDividerState, \
252
+ (obj), TYPE_NPCM7XX_CLOCK_DIVIDER)
253
+
254
+static void npcm7xx_clk_update_pll(void *opaque)
255
+{
256
+ NPCM7xxClockPLLState *s = opaque;
257
+ uint32_t con = s->clk->regs[s->reg];
258
+ uint64_t freq;
259
+
260
+ /* The PLL is grounded if it is not locked yet. */
261
+ if (con & PLLCON_LOKI) {
262
+ freq = clock_get_hz(s->clock_in);
263
+ freq *= PLLCON_FBDV(con);
264
+ freq /= PLLCON_INDV(con) * PLLCON_OTDV1(con) * PLLCON_OTDV2(con);
265
+ } else {
266
+ freq = 0;
267
+ }
268
+
269
+ clock_update_hz(s->clock_out, freq);
270
+}
271
+
272
+static void npcm7xx_clk_update_sel(void *opaque)
273
+{
274
+ NPCM7xxClockSELState *s = opaque;
275
+ uint32_t index = extract32(s->clk->regs[NPCM7XX_CLK_CLKSEL], s->offset,
276
+ s->len);
277
+
278
+ if (index >= s->input_size) {
279
+ qemu_log_mask(LOG_GUEST_ERROR,
280
+ "%s: SEL index: %u out of range\n",
281
+ __func__, index);
282
+ index = 0;
283
+ }
284
+ clock_update_hz(s->clock_out, clock_get_hz(s->clock_in[index]));
285
+}
286
+
287
+static void npcm7xx_clk_update_divider(void *opaque)
288
+{
289
+ NPCM7xxClockDividerState *s = opaque;
290
+ uint32_t freq;
291
+
292
+ freq = s->divide(s);
293
+ clock_update_hz(s->clock_out, freq);
294
+}
295
+
296
+static uint32_t divide_by_constant(NPCM7xxClockDividerState *s)
297
+{
298
+ return clock_get_hz(s->clock_in) / s->divisor;
299
+}
300
+
301
+static uint32_t divide_by_reg_divisor(NPCM7xxClockDividerState *s)
302
+{
303
+ return clock_get_hz(s->clock_in) /
304
+ (extract32(s->clk->regs[s->reg], s->offset, s->len) + 1);
305
+}
306
+
307
+static uint32_t divide_by_reg_divisor_times_2(NPCM7xxClockDividerState *s)
308
+{
309
+ return divide_by_reg_divisor(s) / 2;
310
+}
311
+
312
+static uint32_t shift_by_reg_divisor(NPCM7xxClockDividerState *s)
313
+{
314
+ return clock_get_hz(s->clock_in) >>
315
+ extract32(s->clk->regs[s->reg], s->offset, s->len);
316
+}
317
+
318
+static NPCM7xxClockPLL find_pll_by_reg(enum NPCM7xxCLKRegisters reg)
319
+{
320
+ switch (reg) {
321
+ case NPCM7XX_CLK_PLLCON0:
322
+ return NPCM7XX_CLOCK_PLL0;
323
+ case NPCM7XX_CLK_PLLCON1:
324
+ return NPCM7XX_CLOCK_PLL1;
325
+ case NPCM7XX_CLK_PLLCON2:
326
+ return NPCM7XX_CLOCK_PLL2;
327
+ case NPCM7XX_CLK_PLLCONG:
328
+ return NPCM7XX_CLOCK_PLLG;
329
+ default:
330
+ g_assert_not_reached();
331
+ }
332
+}
333
+
334
+static void npcm7xx_clk_update_all_plls(NPCM7xxCLKState *clk)
335
+{
336
+ int i;
337
+
338
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
339
+ npcm7xx_clk_update_pll(&clk->plls[i]);
340
+ }
341
+}
342
+
343
+static void npcm7xx_clk_update_all_sels(NPCM7xxCLKState *clk)
344
+{
345
+ int i;
346
+
347
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
348
+ npcm7xx_clk_update_sel(&clk->sels[i]);
349
+ }
350
+}
351
+
352
+static void npcm7xx_clk_update_all_dividers(NPCM7xxCLKState *clk)
353
+{
354
+ int i;
355
+
356
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
357
+ npcm7xx_clk_update_divider(&clk->dividers[i]);
358
+ }
359
+}
360
+
361
+static void npcm7xx_clk_update_all_clocks(NPCM7xxCLKState *clk)
362
+{
363
+ clock_update_hz(clk->clkref, NPCM7XX_CLOCK_REF_HZ);
364
+ npcm7xx_clk_update_all_plls(clk);
365
+ npcm7xx_clk_update_all_sels(clk);
366
+ npcm7xx_clk_update_all_dividers(clk);
367
+}
368
+
369
+/* Types of clock sources. */
370
+typedef enum ClockSrcType {
371
+ CLKSRC_REF,
372
+ CLKSRC_PLL,
373
+ CLKSRC_SEL,
374
+ CLKSRC_DIV,
375
+} ClockSrcType;
376
+
377
+typedef struct PLLInitInfo {
378
+ const char *name;
379
+ ClockSrcType src_type;
380
+ int src_index;
381
+ int reg;
382
+ const char *public_name;
383
+} PLLInitInfo;
384
+
385
+typedef struct SELInitInfo {
386
+ const char *name;
387
+ uint8_t input_size;
388
+ ClockSrcType src_type[NPCM7XX_CLK_SEL_MAX_INPUT];
389
+ int src_index[NPCM7XX_CLK_SEL_MAX_INPUT];
390
+ int offset;
391
+ int len;
392
+ const char *public_name;
393
+} SELInitInfo;
394
+
395
+typedef struct DividerInitInfo {
396
+ const char *name;
397
+ ClockSrcType src_type;
398
+ int src_index;
399
+ uint32_t (*divide)(NPCM7xxClockDividerState *s);
400
+ int reg; /* not used when type == CONSTANT */
401
+ int offset; /* not used when type == CONSTANT */
402
+ int len; /* not used when type == CONSTANT */
403
+ int divisor; /* used only when type == CONSTANT */
404
+ const char *public_name;
405
+} DividerInitInfo;
406
+
407
+static const PLLInitInfo pll_init_info_list[] = {
408
+ [NPCM7XX_CLOCK_PLL0] = {
409
+ .name = "pll0",
410
+ .src_type = CLKSRC_REF,
411
+ .reg = NPCM7XX_CLK_PLLCON0,
412
+ },
413
+ [NPCM7XX_CLOCK_PLL1] = {
414
+ .name = "pll1",
415
+ .src_type = CLKSRC_REF,
416
+ .reg = NPCM7XX_CLK_PLLCON1,
417
+ },
418
+ [NPCM7XX_CLOCK_PLL2] = {
419
+ .name = "pll2",
420
+ .src_type = CLKSRC_REF,
421
+ .reg = NPCM7XX_CLK_PLLCON2,
422
+ },
423
+ [NPCM7XX_CLOCK_PLLG] = {
424
+ .name = "pllg",
425
+ .src_type = CLKSRC_REF,
426
+ .reg = NPCM7XX_CLK_PLLCONG,
427
+ },
72
+};
428
+};
73
+
429
+
74
+#endif
430
+static const SELInitInfo sel_init_info_list[] = {
75
diff --git a/hw/nvram/xlnx-zynqmp-efuse.c b/hw/nvram/xlnx-zynqmp-efuse.c
431
+ [NPCM7XX_CLOCK_PIXCKSEL] = {
76
new file mode 100644
432
+ .name = "pixcksel",
77
index XXXXXXX..XXXXXXX
433
+ .input_size = 2,
78
--- /dev/null
434
+ .src_type = {CLKSRC_PLL, CLKSRC_REF},
79
+++ b/hw/nvram/xlnx-zynqmp-efuse.c
435
+ .src_index = {NPCM7XX_CLOCK_PLLG, 0},
80
@@ -XXX,XX +XXX,XX @@
436
+ .offset = 5,
81
+/*
437
+ .len = 1,
82
+ * QEMU model of the ZynqMP eFuse
438
+ .public_name = "pixel-clock",
83
+ *
439
+ },
84
+ * Copyright (c) 2015 Xilinx Inc.
440
+ [NPCM7XX_CLOCK_MCCKSEL] = {
85
+ *
441
+ .name = "mccksel",
86
+ * Written by Edgar E. Iglesias <edgari@xilinx.com>
442
+ .input_size = 4,
87
+ *
443
+ .src_type = {CLKSRC_DIV, CLKSRC_REF, CLKSRC_REF,
88
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
444
+ /*MCBPCK, shouldn't be used in normal operation*/
89
+ * of this software and associated documentation files (the "Software"), to deal
445
+ CLKSRC_REF},
90
+ * in the Software without restriction, including without limitation the rights
446
+ .src_index = {NPCM7XX_CLOCK_PLL1D2, 0, 0, 0},
91
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
447
+ .offset = 12,
92
+ * copies of the Software, and to permit persons to whom the Software is
448
+ .len = 2,
93
+ * furnished to do so, subject to the following conditions:
449
+ .public_name = "mc-phy-clock",
94
+ *
450
+ },
95
+ * The above copyright notice and this permission notice shall be included in
451
+ [NPCM7XX_CLOCK_CPUCKSEL] = {
96
+ * all copies or substantial portions of the Software.
452
+ .name = "cpucksel",
97
+ *
453
+ .input_size = 4,
98
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
454
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF,
99
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
455
+ /*SYSBPCK, shouldn't be used in normal operation*/
100
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
456
+ CLKSRC_REF},
101
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
457
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0, 0},
102
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
458
+ .offset = 0,
103
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
459
+ .len = 2,
104
+ * THE SOFTWARE.
460
+ .public_name = "system-clock",
105
+ */
461
+ },
106
+
462
+ [NPCM7XX_CLOCK_CLKOUTSEL] = {
107
+#include "qemu/osdep.h"
463
+ .name = "clkoutsel",
108
+#include "hw/nvram/xlnx-zynqmp-efuse.h"
464
+ .input_size = 5,
109
+
465
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF,
110
+#include "qemu/log.h"
466
+ CLKSRC_PLL, CLKSRC_DIV},
111
+#include "qapi/error.h"
467
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
112
+#include "migration/vmstate.h"
468
+ NPCM7XX_CLOCK_PLLG, NPCM7XX_CLOCK_PLL2D2},
113
+#include "hw/qdev-properties.h"
469
+ .offset = 18,
114
+
470
+ .len = 3,
115
+#ifndef ZYNQMP_EFUSE_ERR_DEBUG
471
+ .public_name = "tock",
116
+#define ZYNQMP_EFUSE_ERR_DEBUG 0
472
+ },
117
+#endif
473
+ [NPCM7XX_CLOCK_UARTCKSEL] = {
118
+
474
+ .name = "uartcksel",
119
+REG32(WR_LOCK, 0x0)
475
+ .input_size = 4,
120
+ FIELD(WR_LOCK, LOCK, 0, 16)
476
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
121
+REG32(CFG, 0x4)
477
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
122
+ FIELD(CFG, SLVERR_ENABLE, 5, 1)
478
+ NPCM7XX_CLOCK_PLL2D2},
123
+ FIELD(CFG, MARGIN_RD, 2, 2)
479
+ .offset = 8,
124
+ FIELD(CFG, PGM_EN, 1, 1)
480
+ .len = 2,
125
+ FIELD(CFG, EFUSE_CLK_SEL, 0, 1)
481
+ },
126
+REG32(STATUS, 0x8)
482
+ [NPCM7XX_CLOCK_TIMCKSEL] = {
127
+ FIELD(STATUS, AES_CRC_PASS, 7, 1)
483
+ .name = "timcksel",
128
+ FIELD(STATUS, AES_CRC_DONE, 6, 1)
484
+ .input_size = 4,
129
+ FIELD(STATUS, CACHE_DONE, 5, 1)
485
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
130
+ FIELD(STATUS, CACHE_LOAD, 4, 1)
486
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
131
+ FIELD(STATUS, EFUSE_3_TBIT, 2, 1)
487
+ NPCM7XX_CLOCK_PLL2D2},
132
+ FIELD(STATUS, EFUSE_2_TBIT, 1, 1)
488
+ .offset = 14,
133
+ FIELD(STATUS, EFUSE_0_TBIT, 0, 1)
489
+ .len = 2,
134
+REG32(EFUSE_PGM_ADDR, 0xc)
490
+ },
135
+ FIELD(EFUSE_PGM_ADDR, EFUSE, 11, 2)
491
+ [NPCM7XX_CLOCK_SDCKSEL] = {
136
+ FIELD(EFUSE_PGM_ADDR, ROW, 5, 6)
492
+ .name = "sdcksel",
137
+ FIELD(EFUSE_PGM_ADDR, COLUMN, 0, 5)
493
+ .input_size = 4,
138
+REG32(EFUSE_RD_ADDR, 0x10)
494
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
139
+ FIELD(EFUSE_RD_ADDR, EFUSE, 11, 2)
495
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
140
+ FIELD(EFUSE_RD_ADDR, ROW, 5, 6)
496
+ NPCM7XX_CLOCK_PLL2D2},
141
+REG32(EFUSE_RD_DATA, 0x14)
497
+ .offset = 6,
142
+REG32(TPGM, 0x18)
498
+ .len = 2,
143
+ FIELD(TPGM, VALUE, 0, 16)
499
+ },
144
+REG32(TRD, 0x1c)
500
+ [NPCM7XX_CLOCK_GFXMSEL] = {
145
+ FIELD(TRD, VALUE, 0, 8)
501
+ .name = "gfxmksel",
146
+REG32(TSU_H_PS, 0x20)
502
+ .input_size = 2,
147
+ FIELD(TSU_H_PS, VALUE, 0, 8)
503
+ .src_type = {CLKSRC_REF, CLKSRC_PLL},
148
+REG32(TSU_H_PS_CS, 0x24)
504
+ .src_index = {0, NPCM7XX_CLOCK_PLL2},
149
+ FIELD(TSU_H_PS_CS, VALUE, 0, 8)
505
+ .offset = 21,
150
+REG32(TSU_H_CS, 0x2c)
506
+ .len = 1,
151
+ FIELD(TSU_H_CS, VALUE, 0, 4)
507
+ },
152
+REG32(EFUSE_ISR, 0x30)
508
+ [NPCM7XX_CLOCK_SUCKSEL] = {
153
+ FIELD(EFUSE_ISR, APB_SLVERR, 31, 1)
509
+ .name = "sucksel",
154
+ FIELD(EFUSE_ISR, CACHE_ERROR, 4, 1)
510
+ .input_size = 4,
155
+ FIELD(EFUSE_ISR, RD_ERROR, 3, 1)
511
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
156
+ FIELD(EFUSE_ISR, RD_DONE, 2, 1)
512
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
157
+ FIELD(EFUSE_ISR, PGM_ERROR, 1, 1)
513
+ NPCM7XX_CLOCK_PLL2D2},
158
+ FIELD(EFUSE_ISR, PGM_DONE, 0, 1)
514
+ .offset = 10,
159
+REG32(EFUSE_IMR, 0x34)
515
+ .len = 2,
160
+ FIELD(EFUSE_IMR, APB_SLVERR, 31, 1)
516
+ },
161
+ FIELD(EFUSE_IMR, CACHE_ERROR, 4, 1)
517
+};
162
+ FIELD(EFUSE_IMR, RD_ERROR, 3, 1)
518
+
163
+ FIELD(EFUSE_IMR, RD_DONE, 2, 1)
519
+static const DividerInitInfo divider_init_info_list[] = {
164
+ FIELD(EFUSE_IMR, PGM_ERROR, 1, 1)
520
+ [NPCM7XX_CLOCK_PLL1D2] = {
165
+ FIELD(EFUSE_IMR, PGM_DONE, 0, 1)
521
+ .name = "pll1d2",
166
+REG32(EFUSE_IER, 0x38)
522
+ .src_type = CLKSRC_PLL,
167
+ FIELD(EFUSE_IER, APB_SLVERR, 31, 1)
523
+ .src_index = NPCM7XX_CLOCK_PLL1,
168
+ FIELD(EFUSE_IER, CACHE_ERROR, 4, 1)
524
+ .divide = divide_by_constant,
169
+ FIELD(EFUSE_IER, RD_ERROR, 3, 1)
525
+ .divisor = 2,
170
+ FIELD(EFUSE_IER, RD_DONE, 2, 1)
526
+ },
171
+ FIELD(EFUSE_IER, PGM_ERROR, 1, 1)
527
+ [NPCM7XX_CLOCK_PLL2D2] = {
172
+ FIELD(EFUSE_IER, PGM_DONE, 0, 1)
528
+ .name = "pll2d2",
173
+REG32(EFUSE_IDR, 0x3c)
529
+ .src_type = CLKSRC_PLL,
174
+ FIELD(EFUSE_IDR, APB_SLVERR, 31, 1)
530
+ .src_index = NPCM7XX_CLOCK_PLL2,
175
+ FIELD(EFUSE_IDR, CACHE_ERROR, 4, 1)
531
+ .divide = divide_by_constant,
176
+ FIELD(EFUSE_IDR, RD_ERROR, 3, 1)
532
+ .divisor = 2,
177
+ FIELD(EFUSE_IDR, RD_DONE, 2, 1)
533
+ },
178
+ FIELD(EFUSE_IDR, PGM_ERROR, 1, 1)
534
+ [NPCM7XX_CLOCK_MC_DIVIDER] = {
179
+ FIELD(EFUSE_IDR, PGM_DONE, 0, 1)
535
+ .name = "mc-divider",
180
+REG32(EFUSE_CACHE_LOAD, 0x40)
536
+ .src_type = CLKSRC_SEL,
181
+ FIELD(EFUSE_CACHE_LOAD, LOAD, 0, 1)
537
+ .src_index = NPCM7XX_CLOCK_MCCKSEL,
182
+REG32(EFUSE_PGM_LOCK, 0x44)
538
+ .divide = divide_by_constant,
183
+ FIELD(EFUSE_PGM_LOCK, SPK_ID_LOCK, 0, 1)
539
+ .divisor = 2,
184
+REG32(EFUSE_AES_CRC, 0x48)
540
+ .public_name = "mc-clock"
185
+REG32(EFUSE_TBITS_PRGRMG_EN, 0x100)
541
+ },
186
+ FIELD(EFUSE_TBITS_PRGRMG_EN, TBITS_PRGRMG_EN, 3, 1)
542
+ [NPCM7XX_CLOCK_AXI_DIVIDER] = {
187
+REG32(DNA_0, 0x100c)
543
+ .name = "axi-divider",
188
+REG32(DNA_1, 0x1010)
544
+ .src_type = CLKSRC_SEL,
189
+REG32(DNA_2, 0x1014)
545
+ .src_index = NPCM7XX_CLOCK_CPUCKSEL,
190
+REG32(IPDISABLE, 0x1018)
546
+ .divide = shift_by_reg_divisor,
191
+ FIELD(IPDISABLE, VCU_DIS, 8, 1)
547
+ .reg = NPCM7XX_CLK_CLKDIV1,
192
+ FIELD(IPDISABLE, GPU_DIS, 5, 1)
548
+ .offset = 0,
193
+ FIELD(IPDISABLE, APU3_DIS, 3, 1)
549
+ .len = 1,
194
+ FIELD(IPDISABLE, APU2_DIS, 2, 1)
550
+ .public_name = "clk2"
195
+ FIELD(IPDISABLE, APU1_DIS, 1, 1)
551
+ },
196
+ FIELD(IPDISABLE, APU0_DIS, 0, 1)
552
+ [NPCM7XX_CLOCK_AHB_DIVIDER] = {
197
+REG32(SYSOSC_CTRL, 0x101c)
553
+ .name = "ahb-divider",
198
+ FIELD(SYSOSC_CTRL, SYSOSC_EN, 0, 1)
554
+ .src_type = CLKSRC_DIV,
199
+REG32(USER_0, 0x1020)
555
+ .src_index = NPCM7XX_CLOCK_AXI_DIVIDER,
200
+REG32(USER_1, 0x1024)
556
+ .divide = divide_by_reg_divisor,
201
+REG32(USER_2, 0x1028)
557
+ .reg = NPCM7XX_CLK_CLKDIV1,
202
+REG32(USER_3, 0x102c)
558
+ .offset = 26,
203
+REG32(USER_4, 0x1030)
559
+ .len = 2,
204
+REG32(USER_5, 0x1034)
560
+ .public_name = "clk4"
205
+REG32(USER_6, 0x1038)
561
+ },
206
+REG32(USER_7, 0x103c)
562
+ [NPCM7XX_CLOCK_AHB3_DIVIDER] = {
207
+REG32(MISC_USER_CTRL, 0x1040)
563
+ .name = "ahb3-divider",
208
+ FIELD(MISC_USER_CTRL, FPD_SC_EN_0, 14, 1)
564
+ .src_type = CLKSRC_DIV,
209
+ FIELD(MISC_USER_CTRL, LPD_SC_EN_0, 11, 1)
565
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
210
+ FIELD(MISC_USER_CTRL, LBIST_EN, 10, 1)
566
+ .divide = divide_by_reg_divisor,
211
+ FIELD(MISC_USER_CTRL, USR_WRLK_7, 7, 1)
567
+ .reg = NPCM7XX_CLK_CLKDIV1,
212
+ FIELD(MISC_USER_CTRL, USR_WRLK_6, 6, 1)
568
+ .offset = 6,
213
+ FIELD(MISC_USER_CTRL, USR_WRLK_5, 5, 1)
569
+ .len = 5,
214
+ FIELD(MISC_USER_CTRL, USR_WRLK_4, 4, 1)
570
+ .public_name = "ahb3-spi3-clock"
215
+ FIELD(MISC_USER_CTRL, USR_WRLK_3, 3, 1)
571
+ },
216
+ FIELD(MISC_USER_CTRL, USR_WRLK_2, 2, 1)
572
+ [NPCM7XX_CLOCK_SPI0_DIVIDER] = {
217
+ FIELD(MISC_USER_CTRL, USR_WRLK_1, 1, 1)
573
+ .name = "spi0-divider",
218
+ FIELD(MISC_USER_CTRL, USR_WRLK_0, 0, 1)
574
+ .src_type = CLKSRC_DIV,
219
+REG32(ROM_RSVD, 0x1044)
575
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
220
+ FIELD(ROM_RSVD, PBR_BOOT_ERROR, 0, 3)
576
+ .divide = divide_by_reg_divisor,
221
+REG32(PUF_CHASH, 0x1050)
577
+ .reg = NPCM7XX_CLK_CLKDIV3,
222
+REG32(PUF_MISC, 0x1054)
578
+ .offset = 6,
223
+ FIELD(PUF_MISC, REGISTER_DIS, 31, 1)
579
+ .len = 5,
224
+ FIELD(PUF_MISC, SYN_WRLK, 30, 1)
580
+ .public_name = "spi0-clock",
225
+ FIELD(PUF_MISC, SYN_INVLD, 29, 1)
581
+ },
226
+ FIELD(PUF_MISC, TEST2_DIS, 28, 1)
582
+ [NPCM7XX_CLOCK_SPIX_DIVIDER] = {
227
+ FIELD(PUF_MISC, UNUSED27, 27, 1)
583
+ .name = "spix-divider",
228
+ FIELD(PUF_MISC, UNUSED26, 26, 1)
584
+ .src_type = CLKSRC_DIV,
229
+ FIELD(PUF_MISC, UNUSED25, 25, 1)
585
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
230
+ FIELD(PUF_MISC, UNUSED24, 24, 1)
586
+ .divide = divide_by_reg_divisor,
231
+ FIELD(PUF_MISC, AUX, 0, 24)
587
+ .reg = NPCM7XX_CLK_CLKDIV3,
232
+REG32(SEC_CTRL, 0x1058)
588
+ .offset = 1,
233
+ FIELD(SEC_CTRL, PPK1_INVLD, 30, 2)
589
+ .len = 5,
234
+ FIELD(SEC_CTRL, PPK1_WRLK, 29, 1)
590
+ .public_name = "spix-clock",
235
+ FIELD(SEC_CTRL, PPK0_INVLD, 27, 2)
591
+ },
236
+ FIELD(SEC_CTRL, PPK0_WRLK, 26, 1)
592
+ [NPCM7XX_CLOCK_APB1_DIVIDER] = {
237
+ FIELD(SEC_CTRL, RSA_EN, 11, 15)
593
+ .name = "apb1-divider",
238
+ FIELD(SEC_CTRL, SEC_LOCK, 10, 1)
594
+ .src_type = CLKSRC_DIV,
239
+ FIELD(SEC_CTRL, PROG_GATE_2, 9, 1)
595
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
240
+ FIELD(SEC_CTRL, PROG_GATE_1, 8, 1)
596
+ .divide = shift_by_reg_divisor,
241
+ FIELD(SEC_CTRL, PROG_GATE_0, 7, 1)
597
+ .reg = NPCM7XX_CLK_CLKDIV2,
242
+ FIELD(SEC_CTRL, DFT_DIS, 6, 1)
598
+ .offset = 24,
243
+ FIELD(SEC_CTRL, JTAG_DIS, 5, 1)
599
+ .len = 2,
244
+ FIELD(SEC_CTRL, ERROR_DIS, 4, 1)
600
+ .public_name = "apb1-clock",
245
+ FIELD(SEC_CTRL, BBRAM_DIS, 3, 1)
601
+ },
246
+ FIELD(SEC_CTRL, ENC_ONLY, 2, 1)
602
+ [NPCM7XX_CLOCK_APB2_DIVIDER] = {
247
+ FIELD(SEC_CTRL, AES_WRLK, 1, 1)
603
+ .name = "apb2-divider",
248
+ FIELD(SEC_CTRL, AES_RDLK, 0, 1)
604
+ .src_type = CLKSRC_DIV,
249
+REG32(SPK_ID, 0x105c)
605
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
250
+REG32(PPK0_0, 0x10a0)
606
+ .divide = shift_by_reg_divisor,
251
+REG32(PPK0_1, 0x10a4)
607
+ .reg = NPCM7XX_CLK_CLKDIV2,
252
+REG32(PPK0_2, 0x10a8)
608
+ .offset = 26,
253
+REG32(PPK0_3, 0x10ac)
609
+ .len = 2,
254
+REG32(PPK0_4, 0x10b0)
610
+ .public_name = "apb2-clock",
255
+REG32(PPK0_5, 0x10b4)
611
+ },
256
+REG32(PPK0_6, 0x10b8)
612
+ [NPCM7XX_CLOCK_APB3_DIVIDER] = {
257
+REG32(PPK0_7, 0x10bc)
613
+ .name = "apb3-divider",
258
+REG32(PPK0_8, 0x10c0)
614
+ .src_type = CLKSRC_DIV,
259
+REG32(PPK0_9, 0x10c4)
615
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
260
+REG32(PPK0_10, 0x10c8)
616
+ .divide = shift_by_reg_divisor,
261
+REG32(PPK0_11, 0x10cc)
617
+ .reg = NPCM7XX_CLK_CLKDIV2,
262
+REG32(PPK1_0, 0x10d0)
618
+ .offset = 28,
263
+REG32(PPK1_1, 0x10d4)
619
+ .len = 2,
264
+REG32(PPK1_2, 0x10d8)
620
+ .public_name = "apb3-clock",
265
+REG32(PPK1_3, 0x10dc)
621
+ },
266
+REG32(PPK1_4, 0x10e0)
622
+ [NPCM7XX_CLOCK_APB4_DIVIDER] = {
267
+REG32(PPK1_5, 0x10e4)
623
+ .name = "apb4-divider",
268
+REG32(PPK1_6, 0x10e8)
624
+ .src_type = CLKSRC_DIV,
269
+REG32(PPK1_7, 0x10ec)
625
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
270
+REG32(PPK1_8, 0x10f0)
626
+ .divide = shift_by_reg_divisor,
271
+REG32(PPK1_9, 0x10f4)
627
+ .reg = NPCM7XX_CLK_CLKDIV2,
272
+REG32(PPK1_10, 0x10f8)
628
+ .offset = 30,
273
+REG32(PPK1_11, 0x10fc)
629
+ .len = 2,
274
+
630
+ .public_name = "apb4-clock",
275
+#define BIT_POS(ROW, COLUMN) (ROW * 32 + COLUMN)
631
+ },
276
+#define R_MAX (R_PPK1_11 + 1)
632
+ [NPCM7XX_CLOCK_APB5_DIVIDER] = {
277
+
633
+ .name = "apb5-divider",
278
+/* #define EFUSE_XOSC 26 */
634
+ .src_type = CLKSRC_DIV,
279
+
635
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
280
+/*
636
+ .divide = shift_by_reg_divisor,
281
+ * eFUSE layout references:
637
+ .reg = NPCM7XX_CLK_CLKDIV2,
282
+ * ZynqMP: UG1085 (v2.1) August 21, 2019, p.277, Table 12-13
638
+ .offset = 22,
283
+ */
639
+ .len = 2,
284
+#define EFUSE_AES_RDLK BIT_POS(22, 0)
640
+ .public_name = "apb5-clock",
285
+#define EFUSE_AES_WRLK BIT_POS(22, 1)
641
+ },
286
+#define EFUSE_ENC_ONLY BIT_POS(22, 2)
642
+ [NPCM7XX_CLOCK_CLKOUT_DIVIDER] = {
287
+#define EFUSE_BBRAM_DIS BIT_POS(22, 3)
643
+ .name = "clkout-divider",
288
+#define EFUSE_ERROR_DIS BIT_POS(22, 4)
644
+ .src_type = CLKSRC_SEL,
289
+#define EFUSE_JTAG_DIS BIT_POS(22, 5)
645
+ .src_index = NPCM7XX_CLOCK_CLKOUTSEL,
290
+#define EFUSE_DFT_DIS BIT_POS(22, 6)
646
+ .divide = divide_by_reg_divisor,
291
+#define EFUSE_PROG_GATE_0 BIT_POS(22, 7)
647
+ .reg = NPCM7XX_CLK_CLKDIV2,
292
+#define EFUSE_PROG_GATE_1 BIT_POS(22, 7)
648
+ .offset = 16,
293
+#define EFUSE_PROG_GATE_2 BIT_POS(22, 9)
649
+ .len = 5,
294
+#define EFUSE_SEC_LOCK BIT_POS(22, 10)
650
+ .public_name = "clkout",
295
+#define EFUSE_RSA_EN BIT_POS(22, 11)
651
+ },
296
+#define EFUSE_RSA_EN14 BIT_POS(22, 25)
652
+ [NPCM7XX_CLOCK_UART_DIVIDER] = {
297
+#define EFUSE_PPK0_WRLK BIT_POS(22, 26)
653
+ .name = "uart-divider",
298
+#define EFUSE_PPK0_INVLD BIT_POS(22, 27)
654
+ .src_type = CLKSRC_SEL,
299
+#define EFUSE_PPK0_INVLD_1 BIT_POS(22, 28)
655
+ .src_index = NPCM7XX_CLOCK_UARTCKSEL,
300
+#define EFUSE_PPK1_WRLK BIT_POS(22, 29)
656
+ .divide = divide_by_reg_divisor,
301
+#define EFUSE_PPK1_INVLD BIT_POS(22, 30)
657
+ .reg = NPCM7XX_CLK_CLKDIV1,
302
+#define EFUSE_PPK1_INVLD_1 BIT_POS(22, 31)
658
+ .offset = 16,
303
+
659
+ .len = 5,
304
+/* Areas. */
660
+ .public_name = "uart-clock",
305
+#define EFUSE_TRIM_START BIT_POS(1, 0)
661
+ },
306
+#define EFUSE_TRIM_END BIT_POS(1, 30)
662
+ [NPCM7XX_CLOCK_TIMER_DIVIDER] = {
307
+#define EFUSE_DNA_START BIT_POS(3, 0)
663
+ .name = "timer-divider",
308
+#define EFUSE_DNA_END BIT_POS(5, 31)
664
+ .src_type = CLKSRC_SEL,
309
+#define EFUSE_AES_START BIT_POS(24, 0)
665
+ .src_index = NPCM7XX_CLOCK_TIMCKSEL,
310
+#define EFUSE_AES_END BIT_POS(31, 31)
666
+ .divide = divide_by_reg_divisor,
311
+#define EFUSE_ROM_START BIT_POS(17, 0)
667
+ .reg = NPCM7XX_CLK_CLKDIV1,
312
+#define EFUSE_ROM_END BIT_POS(17, 31)
668
+ .offset = 21,
313
+#define EFUSE_IPDIS_START BIT_POS(6, 0)
669
+ .len = 5,
314
+#define EFUSE_IPDIS_END BIT_POS(6, 31)
670
+ .public_name = "timer-clock",
315
+#define EFUSE_USER_START BIT_POS(8, 0)
671
+ },
316
+#define EFUSE_USER_END BIT_POS(15, 31)
672
+ [NPCM7XX_CLOCK_ADC_DIVIDER] = {
317
+#define EFUSE_BISR_START BIT_POS(32, 0)
673
+ .name = "adc-divider",
318
+#define EFUSE_BISR_END BIT_POS(39, 31)
674
+ .src_type = CLKSRC_DIV,
319
+
675
+ .src_index = NPCM7XX_CLOCK_TIMER_DIVIDER,
320
+#define EFUSE_USER_CTRL_START BIT_POS(16, 0)
676
+ .divide = shift_by_reg_divisor,
321
+#define EFUSE_USER_CTRL_END BIT_POS(16, 16)
677
+ .reg = NPCM7XX_CLK_CLKDIV1,
322
+#define EFUSE_USER_CTRL_MASK ((uint32_t)MAKE_64BIT_MASK(0, 17))
678
+ .offset = 28,
323
+
679
+ .len = 3,
324
+#define EFUSE_PUF_CHASH_START BIT_POS(20, 0)
680
+ .public_name = "adc-clock",
325
+#define EFUSE_PUF_CHASH_END BIT_POS(20, 31)
681
+ },
326
+#define EFUSE_PUF_MISC_START BIT_POS(21, 0)
682
+ [NPCM7XX_CLOCK_MMC_DIVIDER] = {
327
+#define EFUSE_PUF_MISC_END BIT_POS(21, 31)
683
+ .name = "mmc-divider",
328
+#define EFUSE_PUF_SYN_WRLK BIT_POS(21, 30)
684
+ .src_type = CLKSRC_SEL,
329
+
685
+ .src_index = NPCM7XX_CLOCK_SDCKSEL,
330
+#define EFUSE_SPK_START BIT_POS(23, 0)
686
+ .divide = divide_by_reg_divisor,
331
+#define EFUSE_SPK_END BIT_POS(23, 31)
687
+ .reg = NPCM7XX_CLK_CLKDIV1,
332
+
688
+ .offset = 11,
333
+#define EFUSE_PPK0_START BIT_POS(40, 0)
689
+ .len = 5,
334
+#define EFUSE_PPK0_END BIT_POS(51, 31)
690
+ .public_name = "mmc-clock",
335
+#define EFUSE_PPK1_START BIT_POS(52, 0)
691
+ },
336
+#define EFUSE_PPK1_END BIT_POS(63, 31)
692
+ [NPCM7XX_CLOCK_SDHC_DIVIDER] = {
337
+
693
+ .name = "sdhc-divider",
338
+#define EFUSE_CACHE_FLD(s, reg, field) \
694
+ .src_type = CLKSRC_SEL,
339
+ ARRAY_FIELD_DP32((s)->regs, reg, field, \
695
+ .src_index = NPCM7XX_CLOCK_SDCKSEL,
340
+ (xlnx_efuse_get_row((s->efuse), EFUSE_ ## field) \
696
+ .divide = divide_by_reg_divisor_times_2,
341
+ >> (EFUSE_ ## field % 32)))
697
+ .reg = NPCM7XX_CLK_CLKDIV2,
342
+
698
+ .offset = 0,
343
+#define EFUSE_CACHE_BIT(s, reg, field) \
699
+ .len = 4,
344
+ ARRAY_FIELD_DP32((s)->regs, reg, field, xlnx_efuse_get_bit((s->efuse), \
700
+ .public_name = "sdhc-clock",
345
+ EFUSE_ ## field))
701
+ },
346
+
702
+ [NPCM7XX_CLOCK_GFXM_DIVIDER] = {
347
+#define FBIT_UNKNOWN (~0)
703
+ .name = "gfxm-divider",
348
+
704
+ .src_type = CLKSRC_SEL,
349
+QEMU_BUILD_BUG_ON(R_MAX != ARRAY_SIZE(((XlnxZynqMPEFuse *)0)->regs));
705
+ .src_index = NPCM7XX_CLOCK_GFXMSEL,
350
+
706
+ .divide = divide_by_constant,
351
+static void update_tbit_status(XlnxZynqMPEFuse *s)
707
+ .divisor = 3,
352
+{
708
+ .public_name = "gfxm-clock",
353
+ unsigned int check = xlnx_efuse_tbits_check(s->efuse);
709
+ },
354
+ uint32_t val = s->regs[R_STATUS];
710
+ [NPCM7XX_CLOCK_UTMI_DIVIDER] = {
355
+
711
+ .name = "utmi-divider",
356
+ val = FIELD_DP32(val, STATUS, EFUSE_0_TBIT, !!(check & (1 << 0)));
712
+ .src_type = CLKSRC_SEL,
357
+ val = FIELD_DP32(val, STATUS, EFUSE_2_TBIT, !!(check & (1 << 1)));
713
+ .src_index = NPCM7XX_CLOCK_SUCKSEL,
358
+ val = FIELD_DP32(val, STATUS, EFUSE_3_TBIT, !!(check & (1 << 2)));
714
+ .divide = divide_by_reg_divisor,
359
+
715
+ .reg = NPCM7XX_CLK_CLKDIV2,
360
+ s->regs[R_STATUS] = val;
716
+ .offset = 8,
361
+}
717
+ .len = 5,
362
+
718
+ .public_name = "utmi-clock",
363
+/* Update the u32 array from efuse bits. Slow but simple approach. */
719
+ },
364
+static void cache_sync_u32(XlnxZynqMPEFuse *s, unsigned int r_start,
720
+};
365
+ unsigned int f_start, unsigned int f_end,
721
+
366
+ unsigned int f_written)
722
+static void npcm7xx_clk_pll_init(Object *obj)
367
+{
723
+{
368
+ uint32_t *u32 = &s->regs[r_start];
724
+ NPCM7xxClockPLLState *pll = NPCM7XX_CLOCK_PLL(obj);
369
+ unsigned int fbit, wbits = 0, u32_off = 0;
725
+
370
+
726
+ pll->clock_in = qdev_init_clock_in(DEVICE(pll), "clock-in",
371
+ /* Avoid working on bits that are not relevant. */
727
+ npcm7xx_clk_update_pll, pll);
372
+ if (f_written != FBIT_UNKNOWN
728
+ pll->clock_out = qdev_init_clock_out(DEVICE(pll), "clock-out");
373
+ && (f_written < f_start || f_written > f_end)) {
729
+}
374
+ return;
730
+
375
+ }
731
+static void npcm7xx_clk_sel_init(Object *obj)
376
+
732
+{
377
+ for (fbit = f_start; fbit <= f_end; fbit++, wbits++) {
733
+ int i;
378
+ if (wbits == 32) {
734
+ NPCM7xxClockSELState *sel = NPCM7XX_CLOCK_SEL(obj);
379
+ /* Update the key offset. */
735
+
380
+ u32_off += 1;
736
+ for (i = 0; i < NPCM7XX_CLK_SEL_MAX_INPUT; ++i) {
381
+ wbits = 0;
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);
382
+ }
833
+ }
383
+ u32[u32_off] |= xlnx_efuse_get_bit(s->efuse, fbit) << wbits;
834
+ }
384
+ }
835
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
385
+}
836
+ src = npcm7xx_get_clock(clk, divider_init_info_list[i].src_type,
386
+
837
+ divider_init_info_list[i].src_index);
387
+/*
838
+ clock_set_source(clk->dividers[i].clock_in, src);
388
+ * Keep the syncs in bit order so we can bail out for the
839
+ }
389
+ * slower ones.
840
+}
390
+ */
841
+
391
+static void zynqmp_efuse_sync_cache(XlnxZynqMPEFuse *s, unsigned int bit)
842
static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size)
392
+{
843
{
393
+ EFUSE_CACHE_BIT(s, SEC_CTRL, AES_RDLK);
844
uint32_t reg = offset / sizeof(uint32_t);
394
+ EFUSE_CACHE_BIT(s, SEC_CTRL, AES_WRLK);
845
@@ -XXX,XX +XXX,XX @@ static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size)
395
+ EFUSE_CACHE_BIT(s, SEC_CTRL, ENC_ONLY);
846
*
396
+ EFUSE_CACHE_BIT(s, SEC_CTRL, BBRAM_DIS);
847
* The 4 LSBs are always zero: (1e9 / 640) << 4 = 25000000.
397
+ EFUSE_CACHE_BIT(s, SEC_CTRL, ERROR_DIS);
848
*/
398
+ EFUSE_CACHE_BIT(s, SEC_CTRL, JTAG_DIS);
849
- value = (((now_ns - s->ref_ns) / 640) << 4) % NPCM7XX_TIMER_REF_HZ;
399
+ EFUSE_CACHE_BIT(s, SEC_CTRL, DFT_DIS);
850
+ value = (((now_ns - s->ref_ns) / 640) << 4) % NPCM7XX_CLOCK_REF_HZ;
400
+ EFUSE_CACHE_BIT(s, SEC_CTRL, PROG_GATE_0);
851
break;
401
+ EFUSE_CACHE_BIT(s, SEC_CTRL, PROG_GATE_1);
852
402
+ EFUSE_CACHE_BIT(s, SEC_CTRL, PROG_GATE_2);
853
default:
403
+ EFUSE_CACHE_BIT(s, SEC_CTRL, SEC_LOCK);
854
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_write(void *opaque, hwaddr offset,
404
+ EFUSE_CACHE_BIT(s, SEC_CTRL, PPK0_WRLK);
855
value |= (value & PLLCON_LOKS);
405
+ EFUSE_CACHE_BIT(s, SEC_CTRL, PPK1_WRLK);
856
}
406
+
857
}
407
+ EFUSE_CACHE_FLD(s, SEC_CTRL, RSA_EN);
858
+ /* Only update PLL when it is locked. */
408
+ EFUSE_CACHE_FLD(s, SEC_CTRL, PPK0_INVLD);
859
+ if (value & PLLCON_LOKI) {
409
+ EFUSE_CACHE_FLD(s, SEC_CTRL, PPK1_INVLD);
860
+ npcm7xx_clk_update_pll(&s->plls[find_pll_by_reg(reg)]);
410
+
411
+ /* Update the tbits. */
412
+ update_tbit_status(s);
413
+
414
+ /* Sync the various areas. */
415
+ s->regs[R_MISC_USER_CTRL] = xlnx_efuse_get_row(s->efuse,
416
+ EFUSE_USER_CTRL_START)
417
+ & EFUSE_USER_CTRL_MASK;
418
+ s->regs[R_PUF_CHASH] = xlnx_efuse_get_row(s->efuse, EFUSE_PUF_CHASH_START);
419
+ s->regs[R_PUF_MISC] = xlnx_efuse_get_row(s->efuse, EFUSE_PUF_MISC_START);
420
+
421
+ cache_sync_u32(s, R_DNA_0, EFUSE_DNA_START, EFUSE_DNA_END, bit);
422
+
423
+ if (bit < EFUSE_AES_START) {
424
+ return;
425
+ }
426
+
427
+ cache_sync_u32(s, R_ROM_RSVD, EFUSE_ROM_START, EFUSE_ROM_END, bit);
428
+ cache_sync_u32(s, R_IPDISABLE, EFUSE_IPDIS_START, EFUSE_IPDIS_END, bit);
429
+ cache_sync_u32(s, R_USER_0, EFUSE_USER_START, EFUSE_USER_END, bit);
430
+ cache_sync_u32(s, R_SPK_ID, EFUSE_SPK_START, EFUSE_SPK_END, bit);
431
+ cache_sync_u32(s, R_PPK0_0, EFUSE_PPK0_START, EFUSE_PPK0_END, bit);
432
+ cache_sync_u32(s, R_PPK1_0, EFUSE_PPK1_START, EFUSE_PPK1_END, bit);
433
+}
434
+
435
+static void zynqmp_efuse_update_irq(XlnxZynqMPEFuse *s)
436
+{
437
+ bool pending = s->regs[R_EFUSE_ISR] & s->regs[R_EFUSE_IMR];
438
+ qemu_set_irq(s->irq, pending);
439
+}
440
+
441
+static void zynqmp_efuse_isr_postw(RegisterInfo *reg, uint64_t val64)
442
+{
443
+ XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(reg->opaque);
444
+ zynqmp_efuse_update_irq(s);
445
+}
446
+
447
+static uint64_t zynqmp_efuse_ier_prew(RegisterInfo *reg, uint64_t val64)
448
+{
449
+ XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(reg->opaque);
450
+ uint32_t val = val64;
451
+
452
+ s->regs[R_EFUSE_IMR] |= val;
453
+ zynqmp_efuse_update_irq(s);
454
+ return 0;
455
+}
456
+
457
+static uint64_t zynqmp_efuse_idr_prew(RegisterInfo *reg, uint64_t val64)
458
+{
459
+ XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(reg->opaque);
460
+ uint32_t val = val64;
461
+
462
+ s->regs[R_EFUSE_IMR] &= ~val;
463
+ zynqmp_efuse_update_irq(s);
464
+ return 0;
465
+}
466
+
467
+static void zynqmp_efuse_pgm_addr_postw(RegisterInfo *reg, uint64_t val64)
468
+{
469
+ XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(reg->opaque);
470
+ unsigned bit = val64;
471
+ unsigned page = FIELD_EX32(bit, EFUSE_PGM_ADDR, EFUSE);
472
+ bool puf_prot = false;
473
+ const char *errmsg = NULL;
474
+
475
+ /* Allow only valid array, and adjust for skipped array 1 */
476
+ switch (page) {
477
+ case 0:
478
+ break;
479
+ case 2 ... 3:
480
+ bit = FIELD_DP32(bit, EFUSE_PGM_ADDR, EFUSE, page - 1);
481
+ puf_prot = xlnx_efuse_get_bit(s->efuse, EFUSE_PUF_SYN_WRLK);
482
+ break;
483
+ default:
484
+ errmsg = "Invalid address";
485
+ goto pgm_done;
486
+ }
487
+
488
+ if (ARRAY_FIELD_EX32(s->regs, WR_LOCK, LOCK)) {
489
+ errmsg = "Array write-locked";
490
+ goto pgm_done;
491
+ }
492
+
493
+ if (!ARRAY_FIELD_EX32(s->regs, CFG, PGM_EN)) {
494
+ errmsg = "Array pgm-disabled";
495
+ goto pgm_done;
496
+ }
497
+
498
+ if (puf_prot) {
499
+ errmsg = "PUF_HD-store write-locked";
500
+ goto pgm_done;
501
+ }
502
+
503
+ if (ARRAY_FIELD_EX32(s->regs, SEC_CTRL, AES_WRLK)
504
+ && bit >= EFUSE_AES_START && bit <= EFUSE_AES_END) {
505
+ errmsg = "AES key-store Write-locked";
506
+ goto pgm_done;
507
+ }
508
+
509
+ if (!xlnx_efuse_set_bit(s->efuse, bit)) {
510
+ errmsg = "Write failed";
511
+ }
512
+
513
+ pgm_done:
514
+ if (!errmsg) {
515
+ ARRAY_FIELD_DP32(s->regs, EFUSE_ISR, PGM_ERROR, 0);
516
+ } else {
517
+ ARRAY_FIELD_DP32(s->regs, EFUSE_ISR, PGM_ERROR, 1);
518
+ qemu_log_mask(LOG_GUEST_ERROR,
519
+ "%s - eFuse write error: %s; addr=0x%x\n",
520
+ object_get_canonical_path(OBJECT(s)),
521
+ errmsg, (unsigned)val64);
522
+ }
523
+
524
+ ARRAY_FIELD_DP32(s->regs, EFUSE_ISR, PGM_DONE, 1);
525
+ zynqmp_efuse_update_irq(s);
526
+}
527
+
528
+static void zynqmp_efuse_rd_addr_postw(RegisterInfo *reg, uint64_t val64)
529
+{
530
+ XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(reg->opaque);
531
+
532
+ /*
533
+ * Grant reads only to allowed bits; reference sources:
534
+ * 1/ XilSKey - XilSKey_ZynqMp_EfusePs_ReadRow()
535
+ * 2/ UG1085, v2.0, table 12-13
536
+ * (note: enumerates the masks as <first, last> per described in
537
+ * references to avoid mental translation).
538
+ */
539
+#define COL_MASK(L_, H_) \
540
+ ((uint32_t)MAKE_64BIT_MASK((L_), (1 + (H_) - (L_))))
541
+
542
+ static const uint32_t ary0_col_mask[] = {
543
+ /* XilSKey - XSK_ZYNQMP_EFUSEPS_TBITS_ROW */
544
+ [0] = COL_MASK(28, 31),
545
+
546
+ /* XilSKey - XSK_ZYNQMP_EFUSEPS_USR{0:7}_FUSE_ROW */
547
+ [8] = COL_MASK(0, 31), [9] = COL_MASK(0, 31),
548
+ [10] = COL_MASK(0, 31), [11] = COL_MASK(0, 31),
549
+ [12] = COL_MASK(0, 31), [13] = COL_MASK(0, 31),
550
+ [14] = COL_MASK(0, 31), [15] = COL_MASK(0, 31),
551
+
552
+ /* XilSKey - XSK_ZYNQMP_EFUSEPS_MISC_USR_CTRL_ROW */
553
+ [16] = COL_MASK(0, 7) | COL_MASK(10, 16),
554
+
555
+ /* XilSKey - XSK_ZYNQMP_EFUSEPS_PBR_BOOT_ERR_ROW */
556
+ [17] = COL_MASK(0, 2),
557
+
558
+ /* XilSKey - XSK_ZYNQMP_EFUSEPS_PUF_CHASH_ROW */
559
+ [20] = COL_MASK(0, 31),
560
+
561
+ /* XilSKey - XSK_ZYNQMP_EFUSEPS_PUF_AUX_ROW */
562
+ [21] = COL_MASK(0, 23) | COL_MASK(29, 31),
563
+
564
+ /* XilSKey - XSK_ZYNQMP_EFUSEPS_SEC_CTRL_ROW */
565
+ [22] = COL_MASK(0, 31),
566
+
567
+ /* XilSKey - XSK_ZYNQMP_EFUSEPS_SPK_ID_ROW */
568
+ [23] = COL_MASK(0, 31),
569
+
570
+ /* XilSKey - XSK_ZYNQMP_EFUSEPS_PPK0_START_ROW */
571
+ [40] = COL_MASK(0, 31), [41] = COL_MASK(0, 31),
572
+ [42] = COL_MASK(0, 31), [43] = COL_MASK(0, 31),
573
+ [44] = COL_MASK(0, 31), [45] = COL_MASK(0, 31),
574
+ [46] = COL_MASK(0, 31), [47] = COL_MASK(0, 31),
575
+ [48] = COL_MASK(0, 31), [49] = COL_MASK(0, 31),
576
+ [50] = COL_MASK(0, 31), [51] = COL_MASK(0, 31),
577
+
578
+ /* XilSKey - XSK_ZYNQMP_EFUSEPS_PPK1_START_ROW */
579
+ [52] = COL_MASK(0, 31), [53] = COL_MASK(0, 31),
580
+ [54] = COL_MASK(0, 31), [55] = COL_MASK(0, 31),
581
+ [56] = COL_MASK(0, 31), [57] = COL_MASK(0, 31),
582
+ [58] = COL_MASK(0, 31), [59] = COL_MASK(0, 31),
583
+ [60] = COL_MASK(0, 31), [61] = COL_MASK(0, 31),
584
+ [62] = COL_MASK(0, 31), [63] = COL_MASK(0, 31),
585
+ };
586
+
587
+ uint32_t col_mask = COL_MASK(0, 31);
588
+#undef COL_MASK
589
+
590
+ uint32_t efuse_idx = s->regs[R_EFUSE_RD_ADDR];
591
+ uint32_t efuse_ary = FIELD_EX32(efuse_idx, EFUSE_RD_ADDR, EFUSE);
592
+ uint32_t efuse_row = FIELD_EX32(efuse_idx, EFUSE_RD_ADDR, ROW);
593
+
594
+ switch (efuse_ary) {
595
+ case 0: /* Various */
596
+ if (efuse_row >= ARRAY_SIZE(ary0_col_mask)) {
597
+ goto denied;
598
+ }
599
+
600
+ col_mask = ary0_col_mask[efuse_row];
601
+ if (!col_mask) {
602
+ goto denied;
603
+ }
861
+ }
604
+ break;
862
+ break;
605
+ case 2: /* PUF helper data, adjust for skipped array 1 */
863
+
606
+ case 3:
864
+ case NPCM7XX_CLK_CLKSEL:
607
+ val64 = FIELD_DP32(efuse_idx, EFUSE_RD_ADDR, EFUSE, efuse_ary - 1);
865
+ npcm7xx_clk_update_all_sels(s);
608
+ break;
866
+ break;
609
+ default:
867
+
610
+ goto denied;
868
+ case NPCM7XX_CLK_CLKDIV1:
611
+ }
869
+ case NPCM7XX_CLK_CLKDIV2:
612
+
870
+ case NPCM7XX_CLK_CLKDIV3:
613
+ s->regs[R_EFUSE_RD_DATA] = xlnx_efuse_get_row(s->efuse, val64) & col_mask;
871
+ npcm7xx_clk_update_all_dividers(s);
614
+
872
break;
615
+ ARRAY_FIELD_DP32(s->regs, EFUSE_ISR, RD_ERROR, 0);
873
616
+ ARRAY_FIELD_DP32(s->regs, EFUSE_ISR, RD_DONE, 1);
874
case NPCM7XX_CLK_CNTR25M:
617
+ zynqmp_efuse_update_irq(s);
875
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_enter_reset(Object *obj, ResetType type)
618
+ return;
876
case RESET_TYPE_COLD:
619
+
877
memcpy(s->regs, cold_reset_values, sizeof(cold_reset_values));
620
+ denied:
878
s->ref_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
621
+ qemu_log_mask(LOG_GUEST_ERROR,
879
+ npcm7xx_clk_update_all_clocks(s);
622
+ "%s: Denied efuse read from array %u, row %u\n",
880
return;
623
+ object_get_canonical_path(OBJECT(s)),
881
}
624
+ efuse_ary, efuse_row);
882
625
+
883
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_enter_reset(Object *obj, ResetType type)
626
+ s->regs[R_EFUSE_RD_DATA] = 0;
884
__func__, type);
627
+
885
}
628
+ ARRAY_FIELD_DP32(s->regs, EFUSE_ISR, RD_ERROR, 1);
886
629
+ ARRAY_FIELD_DP32(s->regs, EFUSE_ISR, RD_DONE, 0);
887
+static void npcm7xx_clk_init_clock_hierarchy(NPCM7xxCLKState *s)
630
+ zynqmp_efuse_update_irq(s);
888
+{
631
+}
889
+ int i;
632
+
890
+
633
+static void zynqmp_efuse_aes_crc_postw(RegisterInfo *reg, uint64_t val64)
891
+ s->clkref = qdev_init_clock_in(DEVICE(s), "clkref", NULL, NULL);
634
+{
892
+
635
+ XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(reg->opaque);
893
+ /* First pass: init all converter modules */
636
+ bool ok;
894
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(pll_init_info_list) != NPCM7XX_CLOCK_NR_PLLS);
637
+
895
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(sel_init_info_list) != NPCM7XX_CLOCK_NR_SELS);
638
+ ok = xlnx_efuse_k256_check(s->efuse, (uint32_t)val64, EFUSE_AES_START);
896
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(divider_init_info_list)
639
+
897
+ != NPCM7XX_CLOCK_NR_DIVIDERS);
640
+ ARRAY_FIELD_DP32(s->regs, STATUS, AES_CRC_PASS, (ok ? 1 : 0));
898
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
641
+ ARRAY_FIELD_DP32(s->regs, STATUS, AES_CRC_DONE, 1);
899
+ object_initialize_child(OBJECT(s), pll_init_info_list[i].name,
642
+
900
+ &s->plls[i], TYPE_NPCM7XX_CLOCK_PLL);
643
+ s->regs[R_EFUSE_AES_CRC] = 0; /* crc value is write-only */
901
+ npcm7xx_init_clock_pll(&s->plls[i], s,
644
+}
902
+ &pll_init_info_list[i]);
645
+
903
+ }
646
+static uint64_t zynqmp_efuse_cache_load_prew(RegisterInfo *reg,
904
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
647
+ uint64_t valu64)
905
+ object_initialize_child(OBJECT(s), sel_init_info_list[i].name,
648
+{
906
+ &s->sels[i], TYPE_NPCM7XX_CLOCK_SEL);
649
+ XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(reg->opaque);
907
+ npcm7xx_init_clock_sel(&s->sels[i], s,
650
+
908
+ &sel_init_info_list[i]);
651
+ if (valu64 & R_EFUSE_CACHE_LOAD_LOAD_MASK) {
909
+ }
652
+ zynqmp_efuse_sync_cache(s, FBIT_UNKNOWN);
910
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
653
+ ARRAY_FIELD_DP32(s->regs, STATUS, CACHE_DONE, 1);
911
+ object_initialize_child(OBJECT(s), divider_init_info_list[i].name,
654
+ zynqmp_efuse_update_irq(s);
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);
655
+ }
942
+ }
656
+
943
+
657
+ return 0;
944
+ return 0;
658
+}
945
+}
659
+
946
+
660
+static uint64_t zynqmp_efuse_wr_lock_prew(RegisterInfo *reg, uint64_t val)
947
+static void npcm7xx_clk_realize(DeviceState *dev, Error **errp)
661
+{
948
+{
662
+ return val == 0xDF0D ? 0 : 1;
949
+ int i;
663
+}
950
+ NPCM7xxCLKState *s = NPCM7XX_CLK(dev);
664
+
951
+
665
+static RegisterAccessInfo zynqmp_efuse_regs_info[] = {
952
+ qdev_init_gpio_in_named(DEVICE(s), npcm7xx_clk_perform_watchdog_reset,
666
+ { .name = "WR_LOCK", .addr = A_WR_LOCK,
953
+ NPCM7XX_WATCHDOG_RESET_GPIO_IN, NPCM7XX_NR_WATCHDOGS);
667
+ .reset = 0x1,
954
+ npcm7xx_clk_init_clock_hierarchy(s);
668
+ .pre_write = zynqmp_efuse_wr_lock_prew,
955
+
669
+ },{ .name = "CFG", .addr = A_CFG,
956
+ /* Realize child devices */
670
+ },{ .name = "STATUS", .addr = A_STATUS,
957
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
671
+ .rsvd = 0x8,
958
+ if (!qdev_realize(DEVICE(&s->plls[i]), NULL, errp)) {
672
+ .ro = 0xff,
959
+ return;
673
+ },{ .name = "EFUSE_PGM_ADDR", .addr = A_EFUSE_PGM_ADDR,
960
+ }
674
+ .post_write = zynqmp_efuse_pgm_addr_postw
961
+ }
675
+ },{ .name = "EFUSE_RD_ADDR", .addr = A_EFUSE_RD_ADDR,
962
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
676
+ .rsvd = 0x1f,
963
+ if (!qdev_realize(DEVICE(&s->sels[i]), NULL, errp)) {
677
+ .post_write = zynqmp_efuse_rd_addr_postw,
964
+ return;
678
+ },{ .name = "EFUSE_RD_DATA", .addr = A_EFUSE_RD_DATA,
965
+ }
679
+ .ro = 0xffffffff,
966
+ }
680
+ },{ .name = "TPGM", .addr = A_TPGM,
967
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
681
+ },{ .name = "TRD", .addr = A_TRD,
968
+ if (!qdev_realize(DEVICE(&s->dividers[i]), NULL, errp)) {
682
+ .reset = 0x1b,
969
+ return;
683
+ },{ .name = "TSU_H_PS", .addr = A_TSU_H_PS,
970
+ }
684
+ .reset = 0xff,
971
+ }
685
+ },{ .name = "TSU_H_PS_CS", .addr = A_TSU_H_PS_CS,
972
+}
686
+ .reset = 0xb,
973
+
687
+ },{ .name = "TSU_H_CS", .addr = A_TSU_H_CS,
974
+static const VMStateDescription vmstate_npcm7xx_clk_pll = {
688
+ .reset = 0x7,
975
+ .name = "npcm7xx-clock-pll",
689
+ },{ .name = "EFUSE_ISR", .addr = A_EFUSE_ISR,
976
.version_id = 0,
690
+ .rsvd = 0x7fffffe0,
977
.minimum_version_id = 0,
691
+ .w1c = 0x8000001f,
978
- .fields = (VMStateField[]) {
692
+ .post_write = zynqmp_efuse_isr_postw,
979
- VMSTATE_UINT32_ARRAY(regs, NPCM7xxCLKState, NPCM7XX_CLK_NR_REGS),
693
+ },{ .name = "EFUSE_IMR", .addr = A_EFUSE_IMR,
980
- VMSTATE_INT64(ref_ns, NPCM7xxCLKState),
694
+ .reset = 0x8000001f,
981
+ .fields = (VMStateField[]) {
695
+ .rsvd = 0x7fffffe0,
982
+ VMSTATE_CLOCK(clock_in, NPCM7xxClockPLLState),
696
+ .ro = 0xffffffff,
983
VMSTATE_END_OF_LIST(),
697
+ },{ .name = "EFUSE_IER", .addr = A_EFUSE_IER,
984
},
698
+ .rsvd = 0x7fffffe0,
985
};
699
+ .pre_write = zynqmp_efuse_ier_prew,
986
700
+ },{ .name = "EFUSE_IDR", .addr = A_EFUSE_IDR,
987
+static const VMStateDescription vmstate_npcm7xx_clk_sel = {
701
+ .rsvd = 0x7fffffe0,
988
+ .name = "npcm7xx-clock-sel",
702
+ .pre_write = zynqmp_efuse_idr_prew,
989
+ .version_id = 0,
703
+ },{ .name = "EFUSE_CACHE_LOAD", .addr = A_EFUSE_CACHE_LOAD,
990
+ .minimum_version_id = 0,
704
+ .pre_write = zynqmp_efuse_cache_load_prew,
991
+ .fields = (VMStateField[]) {
705
+ },{ .name = "EFUSE_PGM_LOCK", .addr = A_EFUSE_PGM_LOCK,
992
+ VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(clock_in, NPCM7xxClockSELState,
706
+ },{ .name = "EFUSE_AES_CRC", .addr = A_EFUSE_AES_CRC,
993
+ NPCM7XX_CLK_SEL_MAX_INPUT, 0, vmstate_clock, Clock),
707
+ .post_write = zynqmp_efuse_aes_crc_postw,
994
+ VMSTATE_END_OF_LIST(),
708
+ },{ .name = "EFUSE_TBITS_PRGRMG_EN", .addr = A_EFUSE_TBITS_PRGRMG_EN,
995
+ },
709
+ .reset = R_EFUSE_TBITS_PRGRMG_EN_TBITS_PRGRMG_EN_MASK,
710
+ },{ .name = "DNA_0", .addr = A_DNA_0,
711
+ .ro = 0xffffffff,
712
+ },{ .name = "DNA_1", .addr = A_DNA_1,
713
+ .ro = 0xffffffff,
714
+ },{ .name = "DNA_2", .addr = A_DNA_2,
715
+ .ro = 0xffffffff,
716
+ },{ .name = "IPDISABLE", .addr = A_IPDISABLE,
717
+ .ro = 0xffffffff,
718
+ },{ .name = "SYSOSC_CTRL", .addr = A_SYSOSC_CTRL,
719
+ .ro = 0xffffffff,
720
+ },{ .name = "USER_0", .addr = A_USER_0,
721
+ .ro = 0xffffffff,
722
+ },{ .name = "USER_1", .addr = A_USER_1,
723
+ .ro = 0xffffffff,
724
+ },{ .name = "USER_2", .addr = A_USER_2,
725
+ .ro = 0xffffffff,
726
+ },{ .name = "USER_3", .addr = A_USER_3,
727
+ .ro = 0xffffffff,
728
+ },{ .name = "USER_4", .addr = A_USER_4,
729
+ .ro = 0xffffffff,
730
+ },{ .name = "USER_5", .addr = A_USER_5,
731
+ .ro = 0xffffffff,
732
+ },{ .name = "USER_6", .addr = A_USER_6,
733
+ .ro = 0xffffffff,
734
+ },{ .name = "USER_7", .addr = A_USER_7,
735
+ .ro = 0xffffffff,
736
+ },{ .name = "MISC_USER_CTRL", .addr = A_MISC_USER_CTRL,
737
+ .ro = 0xffffffff,
738
+ },{ .name = "ROM_RSVD", .addr = A_ROM_RSVD,
739
+ .ro = 0xffffffff,
740
+ },{ .name = "PUF_CHASH", .addr = A_PUF_CHASH,
741
+ .ro = 0xffffffff,
742
+ },{ .name = "PUF_MISC", .addr = A_PUF_MISC,
743
+ .ro = 0xffffffff,
744
+ },{ .name = "SEC_CTRL", .addr = A_SEC_CTRL,
745
+ .ro = 0xffffffff,
746
+ },{ .name = "SPK_ID", .addr = A_SPK_ID,
747
+ .ro = 0xffffffff,
748
+ },{ .name = "PPK0_0", .addr = A_PPK0_0,
749
+ .ro = 0xffffffff,
750
+ },{ .name = "PPK0_1", .addr = A_PPK0_1,
751
+ .ro = 0xffffffff,
752
+ },{ .name = "PPK0_2", .addr = A_PPK0_2,
753
+ .ro = 0xffffffff,
754
+ },{ .name = "PPK0_3", .addr = A_PPK0_3,
755
+ .ro = 0xffffffff,
756
+ },{ .name = "PPK0_4", .addr = A_PPK0_4,
757
+ .ro = 0xffffffff,
758
+ },{ .name = "PPK0_5", .addr = A_PPK0_5,
759
+ .ro = 0xffffffff,
760
+ },{ .name = "PPK0_6", .addr = A_PPK0_6,
761
+ .ro = 0xffffffff,
762
+ },{ .name = "PPK0_7", .addr = A_PPK0_7,
763
+ .ro = 0xffffffff,
764
+ },{ .name = "PPK0_8", .addr = A_PPK0_8,
765
+ .ro = 0xffffffff,
766
+ },{ .name = "PPK0_9", .addr = A_PPK0_9,
767
+ .ro = 0xffffffff,
768
+ },{ .name = "PPK0_10", .addr = A_PPK0_10,
769
+ .ro = 0xffffffff,
770
+ },{ .name = "PPK0_11", .addr = A_PPK0_11,
771
+ .ro = 0xffffffff,
772
+ },{ .name = "PPK1_0", .addr = A_PPK1_0,
773
+ .ro = 0xffffffff,
774
+ },{ .name = "PPK1_1", .addr = A_PPK1_1,
775
+ .ro = 0xffffffff,
776
+ },{ .name = "PPK1_2", .addr = A_PPK1_2,
777
+ .ro = 0xffffffff,
778
+ },{ .name = "PPK1_3", .addr = A_PPK1_3,
779
+ .ro = 0xffffffff,
780
+ },{ .name = "PPK1_4", .addr = A_PPK1_4,
781
+ .ro = 0xffffffff,
782
+ },{ .name = "PPK1_5", .addr = A_PPK1_5,
783
+ .ro = 0xffffffff,
784
+ },{ .name = "PPK1_6", .addr = A_PPK1_6,
785
+ .ro = 0xffffffff,
786
+ },{ .name = "PPK1_7", .addr = A_PPK1_7,
787
+ .ro = 0xffffffff,
788
+ },{ .name = "PPK1_8", .addr = A_PPK1_8,
789
+ .ro = 0xffffffff,
790
+ },{ .name = "PPK1_9", .addr = A_PPK1_9,
791
+ .ro = 0xffffffff,
792
+ },{ .name = "PPK1_10", .addr = A_PPK1_10,
793
+ .ro = 0xffffffff,
794
+ },{ .name = "PPK1_11", .addr = A_PPK1_11,
795
+ .ro = 0xffffffff,
796
+ }
797
+};
996
+};
798
+
997
+
799
+static void zynqmp_efuse_reg_write(void *opaque, hwaddr addr,
998
+static const VMStateDescription vmstate_npcm7xx_clk_divider = {
800
+ uint64_t data, unsigned size)
999
+ .name = "npcm7xx-clock-divider",
801
+{
1000
+ .version_id = 0,
802
+ RegisterInfoArray *reg_array = opaque;
1001
+ .minimum_version_id = 0,
803
+ XlnxZynqMPEFuse *s;
1002
+ .fields = (VMStateField[]) {
804
+ Object *dev;
1003
+ VMSTATE_CLOCK(clock_in, NPCM7xxClockDividerState),
805
+
1004
+ VMSTATE_END_OF_LIST(),
806
+ assert(reg_array != NULL);
807
+
808
+ dev = reg_array->mem.owner;
809
+ assert(dev);
810
+
811
+ s = XLNX_ZYNQMP_EFUSE(dev);
812
+
813
+ if (addr != A_WR_LOCK && s->regs[R_WR_LOCK]) {
814
+ qemu_log_mask(LOG_GUEST_ERROR,
815
+ "%s[reg_0x%02lx]: Attempt to write locked register.\n",
816
+ object_get_canonical_path(OBJECT(s)), (long)addr);
817
+ } else {
818
+ register_write_memory(opaque, addr, data, size);
819
+ }
820
+}
821
+
822
+static const MemoryRegionOps zynqmp_efuse_ops = {
823
+ .read = register_read_memory,
824
+ .write = zynqmp_efuse_reg_write,
825
+ .endianness = DEVICE_LITTLE_ENDIAN,
826
+ .valid = {
827
+ .min_access_size = 4,
828
+ .max_access_size = 4,
829
+ },
1005
+ },
830
+};
1006
+};
831
+
1007
+
832
+static void zynqmp_efuse_register_reset(RegisterInfo *reg)
1008
+static const VMStateDescription vmstate_npcm7xx_clk = {
833
+{
1009
+ .name = "npcm7xx-clk",
834
+ if (!reg->data || !reg->access) {
835
+ return;
836
+ }
837
+
838
+ /* Reset must not trigger some registers' writers */
839
+ switch (reg->access->addr) {
840
+ case A_EFUSE_AES_CRC:
841
+ *(uint32_t *)reg->data = reg->access->reset;
842
+ return;
843
+ }
844
+
845
+ register_reset(reg);
846
+}
847
+
848
+static void zynqmp_efuse_reset(DeviceState *dev)
849
+{
850
+ XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(dev);
851
+ unsigned int i;
852
+
853
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
854
+ zynqmp_efuse_register_reset(&s->regs_info[i]);
855
+ }
856
+
857
+ zynqmp_efuse_sync_cache(s, FBIT_UNKNOWN);
858
+ ARRAY_FIELD_DP32(s->regs, STATUS, CACHE_DONE, 1);
859
+ zynqmp_efuse_update_irq(s);
860
+}
861
+
862
+static void zynqmp_efuse_realize(DeviceState *dev, Error **errp)
863
+{
864
+ XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(dev);
865
+
866
+ if (!s->efuse) {
867
+ error_setg(errp, "%s.efuse: link property not connected to XLNX-EFUSE",
868
+ object_get_canonical_path(OBJECT(dev)));
869
+ return;
870
+ }
871
+
872
+ s->efuse->dev = dev;
873
+}
874
+
875
+static void zynqmp_efuse_init(Object *obj)
876
+{
877
+ XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(obj);
878
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
879
+ RegisterInfoArray *reg_array;
880
+
881
+ reg_array =
882
+ register_init_block32(DEVICE(obj), zynqmp_efuse_regs_info,
883
+ ARRAY_SIZE(zynqmp_efuse_regs_info),
884
+ s->regs_info, s->regs,
885
+ &zynqmp_efuse_ops,
886
+ ZYNQMP_EFUSE_ERR_DEBUG,
887
+ R_MAX * 4);
888
+
889
+ sysbus_init_mmio(sbd, &reg_array->mem);
890
+ sysbus_init_irq(sbd, &s->irq);
891
+}
892
+
893
+static const VMStateDescription vmstate_efuse = {
894
+ .name = TYPE_XLNX_ZYNQMP_EFUSE,
895
+ .version_id = 1,
1010
+ .version_id = 1,
896
+ .minimum_version_id = 1,
1011
+ .minimum_version_id = 1,
1012
+ .post_load = npcm7xx_clk_post_load,
897
+ .fields = (VMStateField[]) {
1013
+ .fields = (VMStateField[]) {
898
+ VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPEFuse, R_MAX),
1014
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxCLKState, NPCM7XX_CLK_NR_REGS),
1015
+ VMSTATE_INT64(ref_ns, NPCM7xxCLKState),
1016
+ VMSTATE_CLOCK(clkref, NPCM7xxCLKState),
899
+ VMSTATE_END_OF_LIST(),
1017
+ VMSTATE_END_OF_LIST(),
900
+ }
1018
+ },
901
+};
1019
+};
902
+
1020
+
903
+static Property zynqmp_efuse_props[] = {
1021
+static void npcm7xx_clk_pll_class_init(ObjectClass *klass, void *data)
904
+ DEFINE_PROP_LINK("efuse",
1022
+{
905
+ XlnxZynqMPEFuse, efuse,
1023
+ DeviceClass *dc = DEVICE_CLASS(klass);
906
+ TYPE_XLNX_EFUSE, XlnxEFuse *),
1024
+
907
+
1025
+ dc->desc = "NPCM7xx Clock PLL Module";
908
+ DEFINE_PROP_END_OF_LIST(),
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,
909
+};
1062
+};
910
+
1063
+
911
+static void zynqmp_efuse_class_init(ObjectClass *klass, void *data)
1064
+static const TypeInfo npcm7xx_clk_sel_info = {
912
+{
1065
+ .name = TYPE_NPCM7XX_CLOCK_SEL,
913
+ DeviceClass *dc = DEVICE_CLASS(klass);
1066
+ .parent = TYPE_DEVICE,
914
+
1067
+ .instance_size = sizeof(NPCM7xxClockSELState),
915
+ dc->reset = zynqmp_efuse_reset;
1068
+ .instance_init = npcm7xx_clk_sel_init,
916
+ dc->realize = zynqmp_efuse_realize;
1069
+ .class_init = npcm7xx_clk_sel_class_init,
917
+ dc->vmsd = &vmstate_efuse;
918
+ device_class_set_props(dc, zynqmp_efuse_props);
919
+}
920
+
921
+
922
+static const TypeInfo efuse_info = {
923
+ .name = TYPE_XLNX_ZYNQMP_EFUSE,
924
+ .parent = TYPE_SYS_BUS_DEVICE,
925
+ .instance_size = sizeof(XlnxZynqMPEFuse),
926
+ .class_init = zynqmp_efuse_class_init,
927
+ .instance_init = zynqmp_efuse_init,
928
+};
1070
+};
929
+
1071
+
930
+static void efuse_register_types(void)
1072
+static const TypeInfo npcm7xx_clk_divider_info = {
931
+{
1073
+ .name = TYPE_NPCM7XX_CLOCK_DIVIDER,
932
+ type_register_static(&efuse_info);
1074
+ .parent = TYPE_DEVICE,
933
+}
1075
+ .instance_size = sizeof(NPCM7xxClockDividerState),
934
+
1076
+ .instance_init = npcm7xx_clk_divider_init,
935
+type_init(efuse_register_types)
1077
+ .class_init = npcm7xx_clk_divider_class_init,
936
diff --git a/hw/nvram/Kconfig b/hw/nvram/Kconfig
1078
+};
937
index XXXXXXX..XXXXXXX 100644
1079
+
938
--- a/hw/nvram/Kconfig
1080
static const TypeInfo npcm7xx_clk_info = {
939
+++ b/hw/nvram/Kconfig
1081
.name = TYPE_NPCM7XX_CLK,
940
@@ -XXX,XX +XXX,XX @@ config XLNX_EFUSE
1082
.parent = TYPE_SYS_BUS_DEVICE,
941
config XLNX_EFUSE_VERSAL
1083
@@ -XXX,XX +XXX,XX @@ static const TypeInfo npcm7xx_clk_info = {
942
bool
1084
943
select XLNX_EFUSE
1085
static void npcm7xx_clk_register_type(void)
944
+
1086
{
945
+config XLNX_EFUSE_ZYNQMP
1087
+ type_register_static(&npcm7xx_clk_pll_info);
946
+ bool
1088
+ type_register_static(&npcm7xx_clk_sel_info);
947
+ select XLNX_EFUSE
1089
+ type_register_static(&npcm7xx_clk_divider_info);
948
diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build
1090
type_register_static(&npcm7xx_clk_info);
949
index XXXXXXX..XXXXXXX 100644
1091
}
950
--- a/hw/nvram/meson.build
1092
type_init(npcm7xx_clk_register_type);
951
+++ b/hw/nvram/meson.build
952
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE', if_true: files('xlnx-efuse.c'))
953
softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_VERSAL', if_true: files(
954
'xlnx-versal-efuse-cache.c',
955
'xlnx-versal-efuse-ctrl.c'))
956
+softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_ZYNQMP', if_true: files(
957
+ 'xlnx-zynqmp-efuse.c'))
958
959
specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_nvram.c'))
960
--
1093
--
961
2.20.1
1094
2.20.1
962
1095
963
1096
diff view generated by jsdifflib
1
From: Tong Ho <tong.ho@xilinx.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
Connect the support for Versal Battery-Backed RAM (BBRAM)
3
This patch makes NPCM7XX Timer to use a the timer clock generated by the
4
CLK module instead of the magic number TIMER_REF_HZ.
4
5
5
The command argument:
6
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
6
-drive if=pflash,index=0,...
7
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
7
Can be used to optionally connect the bbram to a backend
8
Signed-off-by: Hao Wu <wuhaotsh@google.com>
8
storage, such that field-programmed values in one
9
Message-id: 20210108190945.949196-3-wuhaotsh@google.com
9
invocation can be made available to next invocation.
10
11
The backend storage must be a seekable binary file, and
12
its size must be 36 bytes or larger. A file with all
13
binary 0's is a 'blank'.
14
15
Signed-off-by: Tong Ho <tong.ho@xilinx.com>
16
Message-id: 20210917052400.1249094-6-tong.ho@xilinx.com
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
12
---
20
include/hw/arm/xlnx-versal.h | 5 +++++
13
include/hw/misc/npcm7xx_clk.h | 6 -----
21
hw/arm/xlnx-versal-virt.c | 36 ++++++++++++++++++++++++++++++++++++
14
include/hw/timer/npcm7xx_timer.h | 1 +
22
hw/arm/xlnx-versal.c | 18 ++++++++++++++++++
15
hw/arm/npcm7xx.c | 5 ++++
23
hw/arm/Kconfig | 1 +
16
hw/timer/npcm7xx_timer.c | 39 +++++++++++++++-----------------
24
4 files changed, 60 insertions(+)
17
4 files changed, 24 insertions(+), 27 deletions(-)
25
18
26
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
19
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
27
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
28
--- a/include/hw/arm/xlnx-versal.h
21
--- a/include/hw/misc/npcm7xx_clk.h
29
+++ b/include/hw/arm/xlnx-versal.h
22
+++ b/include/hw/misc/npcm7xx_clk.h
30
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@
31
#include "qom/object.h"
24
#include "hw/clock.h"
32
#include "hw/usb/xlnx-usb-subsystem.h"
25
#include "hw/sysbus.h"
33
#include "hw/misc/xlnx-versal-xramc.h"
26
34
+#include "hw/nvram/xlnx-bbram.h"
27
-/*
35
28
- * The reference clock frequency for the timer modules, and the SECCNT and
36
#define TYPE_XLNX_VERSAL "xlnx-versal"
29
- * CNTR25M registers in this module, is always 25 MHz.
37
OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
30
- */
38
@@ -XXX,XX +XXX,XX @@ struct Versal {
31
-#define NPCM7XX_TIMER_REF_HZ (25000000)
39
} iou;
32
-
40
33
/*
41
XlnxZynqMPRTC rtc;
34
* Number of registers in our device state structure. Don't change this without
42
+ XlnxBBRam bbram;
35
* incrementing the version_id in the vmstate.
43
} pmc;
36
diff --git a/include/hw/timer/npcm7xx_timer.h b/include/hw/timer/npcm7xx_timer.h
44
45
struct {
46
@@ -XXX,XX +XXX,XX @@ struct Versal {
47
#define VERSAL_GEM1_WAKE_IRQ_0 59
48
#define VERSAL_ADMA_IRQ_0 60
49
#define VERSAL_XRAM_IRQ_0 79
50
+#define VERSAL_BBRAM_APB_IRQ_0 121
51
#define VERSAL_RTC_APB_ERR_IRQ 121
52
#define VERSAL_SD0_IRQ_0 126
53
#define VERSAL_RTC_ALARM_IRQ 142
54
@@ -XXX,XX +XXX,XX @@ struct Versal {
55
56
#define MM_PMC_SD0 0xf1040000U
57
#define MM_PMC_SD0_SIZE 0x10000
58
+#define MM_PMC_BBRAM_CTRL 0xf11f0000
59
+#define MM_PMC_BBRAM_CTRL_SIZE 0x00050
60
#define MM_PMC_CRP 0xf1260000U
61
#define MM_PMC_CRP_SIZE 0x10000
62
#define MM_PMC_RTC 0xf12a0000
63
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
64
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
65
--- a/hw/arm/xlnx-versal-virt.c
38
--- a/include/hw/timer/npcm7xx_timer.h
66
+++ b/hw/arm/xlnx-versal-virt.c
39
+++ b/include/hw/timer/npcm7xx_timer.h
67
@@ -XXX,XX +XXX,XX @@ static void fdt_add_rtc_node(VersalVirt *s)
40
@@ -XXX,XX +XXX,XX @@ struct NPCM7xxTimerCtrlState {
68
g_free(name);
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
52
@@ -XXX,XX +XXX,XX @@
53
#include "hw/char/serial.h"
54
#include "hw/loader.h"
55
#include "hw/misc/unimp.h"
56
+#include "hw/qdev-clock.h"
57
#include "hw/qdev-properties.h"
58
#include "qapi/error.h"
59
#include "qemu/units.h"
60
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
61
int first_irq;
62
int j;
63
64
+ /* Connect the timer clock. */
65
+ qdev_connect_clock_in(DEVICE(&s->tim[i]), "clock", qdev_get_clock_out(
66
+ DEVICE(&s->clk), "timer-clock"));
67
+
68
sysbus_realize(sbd, &error_abort);
69
sysbus_mmio_map(sbd, 0, npcm7xx_tim_addr[i]);
70
71
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/hw/timer/npcm7xx_timer.c
74
+++ b/hw/timer/npcm7xx_timer.c
75
@@ -XXX,XX +XXX,XX @@
76
#include "qemu/osdep.h"
77
78
#include "hw/irq.h"
79
+#include "hw/qdev-clock.h"
80
#include "hw/qdev-properties.h"
81
-#include "hw/misc/npcm7xx_clk.h"
82
#include "hw/timer/npcm7xx_timer.h"
83
#include "migration/vmstate.h"
84
#include "qemu/bitops.h"
85
@@ -XXX,XX +XXX,XX @@ static uint32_t npcm7xx_tcsr_prescaler(uint32_t tcsr)
86
/* Convert a timer cycle count to a time interval in nanoseconds. */
87
static int64_t npcm7xx_timer_count_to_ns(NPCM7xxTimer *t, uint32_t count)
88
{
89
- int64_t ns = count;
90
+ int64_t ticks = count;
91
92
- ns *= NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ;
93
- ns *= npcm7xx_tcsr_prescaler(t->tcsr);
94
+ ticks *= npcm7xx_tcsr_prescaler(t->tcsr);
95
96
- return ns;
97
+ return clock_ticks_to_ns(t->ctrl->clock, ticks);
69
}
98
}
70
99
71
+static void fdt_add_bbram_node(VersalVirt *s)
100
/* Convert a time interval in nanoseconds to a timer cycle count. */
72
+{
101
static uint32_t npcm7xx_timer_ns_to_count(NPCM7xxTimer *t, int64_t ns)
73
+ const char compat[] = TYPE_XLNX_BBRAM;
74
+ const char interrupt_names[] = "bbram-error";
75
+ char *name = g_strdup_printf("/bbram@%x", MM_PMC_BBRAM_CTRL);
76
+
77
+ qemu_fdt_add_subnode(s->fdt, name);
78
+
79
+ qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
80
+ GIC_FDT_IRQ_TYPE_SPI, VERSAL_BBRAM_APB_IRQ_0,
81
+ GIC_FDT_IRQ_FLAGS_LEVEL_HI);
82
+ qemu_fdt_setprop(s->fdt, name, "interrupt-names",
83
+ interrupt_names, sizeof(interrupt_names));
84
+ qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
85
+ 2, MM_PMC_BBRAM_CTRL,
86
+ 2, MM_PMC_BBRAM_CTRL_SIZE);
87
+ qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
88
+ g_free(name);
89
+}
90
+
91
static void fdt_nop_memory_nodes(void *fdt, Error **errp)
92
{
102
{
93
Error *err = NULL;
103
- int64_t count;
94
@@ -XXX,XX +XXX,XX @@ static void create_virtio_regions(VersalVirt *s)
104
-
95
}
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));
96
}
111
}
97
112
98
+static void bbram_attach_drive(XlnxBBRam *dev)
113
static uint32_t npcm7xx_watchdog_timer_prescaler(const NPCM7xxWatchdogTimer *t)
99
+{
114
@@ -XXX,XX +XXX,XX @@ static uint32_t npcm7xx_watchdog_timer_prescaler(const NPCM7xxWatchdogTimer *t)
100
+ DriveInfo *dinfo;
115
static void npcm7xx_watchdog_timer_reset_cycles(NPCM7xxWatchdogTimer *t,
101
+ BlockBackend *blk;
116
int64_t cycles)
102
+
103
+ dinfo = drive_get_by_index(IF_PFLASH, 0);
104
+ blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
105
+ if (blk) {
106
+ qdev_prop_set_drive(DEVICE(dev), "drive", blk);
107
+ }
108
+}
109
+
110
static void sd_plugin_card(SDHCIState *sd, DriveInfo *di)
111
{
117
{
112
BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL;
118
- uint32_t prescaler = npcm7xx_watchdog_timer_prescaler(t);
113
@@ -XXX,XX +XXX,XX @@ static void versal_virt_init(MachineState *machine)
119
- int64_t ns = (NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ) * cycles;
114
fdt_add_usb_xhci_nodes(s);
120
+ int64_t ticks = cycles * npcm7xx_watchdog_timer_prescaler(t);
115
fdt_add_sd_nodes(s);
121
+ int64_t ns = clock_ticks_to_ns(t->ctrl->clock, ticks);
116
fdt_add_rtc_node(s);
122
117
+ fdt_add_bbram_node(s);
123
/*
118
fdt_add_cpu_nodes(s, psci_conduit);
124
* The reset function always clears the current timer. The caller of the
119
fdt_add_clk_node(s, "/clk125", 125000000, s->phandle.clk_125Mhz);
125
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_watchdog_timer_reset_cycles(NPCM7xxWatchdogTimer *t,
120
fdt_add_clk_node(s, "/clk25", 25000000, s->phandle.clk_25Mhz);
126
*/
121
@@ -XXX,XX +XXX,XX @@ static void versal_virt_init(MachineState *machine)
127
npcm7xx_timer_clear(&t->base_timer);
122
memory_region_add_subregion_overlap(get_system_memory(),
128
123
0, &s->soc.fpd.apu.mr, 0);
129
- ns *= prescaler;
124
130
t->base_timer.remaining_ns = ns;
125
+ /* Attach bbram backend, if given */
126
+ bbram_attach_drive(&s->soc.pmc.bbram);
127
+
128
/* Plugin SD cards. */
129
for (i = 0; i < ARRAY_SIZE(s->soc.pmc.iou.sd); i++) {
130
sd_plugin_card(&s->soc.pmc.iou.sd[i], drive_get_next(IF_SD));
131
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
132
index XXXXXXX..XXXXXXX 100644
133
--- a/hw/arm/xlnx-versal.c
134
+++ b/hw/arm/xlnx-versal.c
135
@@ -XXX,XX +XXX,XX @@ static void versal_create_xrams(Versal *s, qemu_irq *pic)
136
}
137
}
131
}
138
132
139
+static void versal_create_bbram(Versal *s, qemu_irq *pic)
133
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_hold_reset(Object *obj)
140
+{
134
qemu_irq_lower(s->watchdog_timer.irq);
141
+ SysBusDevice *sbd;
135
}
142
+
136
143
+ object_initialize_child_with_props(OBJECT(s), "bbram", &s->pmc.bbram,
137
-static void npcm7xx_timer_realize(DeviceState *dev, Error **errp)
144
+ sizeof(s->pmc.bbram), TYPE_XLNX_BBRAM,
138
+static void npcm7xx_timer_init(Object *obj)
145
+ &error_fatal,
139
{
146
+ "crc-zpads", "0",
140
- NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(dev);
147
+ NULL);
141
- SysBusDevice *sbd = &s->parent;
148
+ sbd = SYS_BUS_DEVICE(&s->pmc.bbram);
142
+ NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(obj);
149
+
143
+ DeviceState *dev = DEVICE(obj);
150
+ sysbus_realize(sbd, &error_fatal);
144
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
151
+ memory_region_add_subregion(&s->mr_ps, MM_PMC_BBRAM_CTRL,
145
int i;
152
+ sysbus_mmio_get_region(sbd, 0));
146
NPCM7xxWatchdogTimer *w;
153
+ sysbus_connect_irq(sbd, 0, pic[VERSAL_BBRAM_APB_IRQ_0]);
147
154
+}
148
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_realize(DeviceState *dev, Error **errp)
155
+
149
npcm7xx_watchdog_timer_expired, w);
156
/* This takes the board allocated linear DDR memory and creates aliases
150
sysbus_init_irq(sbd, &w->irq);
157
* for each split DDR range/aperture on the Versal address map.
151
158
*/
152
- memory_region_init_io(&s->iomem, OBJECT(s), &npcm7xx_timer_ops, s,
159
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
153
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_timer_ops, s,
160
versal_create_sds(s, pic);
154
TYPE_NPCM7XX_TIMER, 4 * KiB);
161
versal_create_rtc(s, pic);
155
sysbus_init_mmio(sbd, &s->iomem);
162
versal_create_xrams(s, pic);
156
qdev_init_gpio_out_named(dev, &w->reset_signal,
163
+ versal_create_bbram(s, pic);
157
NPCM7XX_WATCHDOG_RESET_GPIO_OUT, 1);
164
versal_map_ddr(s);
158
+ s->clock = qdev_init_clock_in(dev, "clock", NULL, NULL);
165
versal_unimp(s);
159
}
166
160
167
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
161
static const VMStateDescription vmstate_npcm7xx_base_timer = {
168
index XXXXXXX..XXXXXXX 100644
162
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_npcm7xx_watchdog_timer = {
169
--- a/hw/arm/Kconfig
163
170
+++ b/hw/arm/Kconfig
164
static const VMStateDescription vmstate_npcm7xx_timer_ctrl = {
171
@@ -XXX,XX +XXX,XX @@ config XLNX_VERSAL
165
.name = "npcm7xx-timer-ctrl",
172
select XLNX_ZDMA
166
- .version_id = 1,
173
select XLNX_ZYNQMP
167
- .minimum_version_id = 1,
174
select OR_IRQ
168
+ .version_id = 2,
175
+ select XLNX_BBRAM
169
+ .minimum_version_id = 2,
176
170
.fields = (VMStateField[]) {
177
config NPCM7XX
171
VMSTATE_UINT32(tisr, NPCM7xxTimerCtrlState),
178
bool
172
+ VMSTATE_CLOCK(clock, NPCM7xxTimerCtrlState),
173
VMSTATE_STRUCT_ARRAY(timer, NPCM7xxTimerCtrlState,
174
NPCM7XX_TIMERS_PER_CTRL, 0, vmstate_npcm7xx_timer,
175
NPCM7xxTimer),
176
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_class_init(ObjectClass *klass, void *data)
177
QEMU_BUILD_BUG_ON(NPCM7XX_TIMER_REGS_END > NPCM7XX_TIMER_NR_REGS);
178
179
dc->desc = "NPCM7xx Timer Controller";
180
- dc->realize = npcm7xx_timer_realize;
181
dc->vmsd = &vmstate_npcm7xx_timer_ctrl;
182
rc->phases.enter = npcm7xx_timer_enter_reset;
183
rc->phases.hold = npcm7xx_timer_hold_reset;
184
@@ -XXX,XX +XXX,XX @@ static const TypeInfo npcm7xx_timer_info = {
185
.parent = TYPE_SYS_BUS_DEVICE,
186
.instance_size = sizeof(NPCM7xxTimerCtrlState),
187
.class_init = npcm7xx_timer_class_init,
188
+ .instance_init = npcm7xx_timer_init,
189
};
190
191
static void npcm7xx_timer_register_type(void)
179
--
192
--
180
2.20.1
193
2.20.1
181
194
182
195
diff view generated by jsdifflib
1
From: Tong Ho <tong.ho@xilinx.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
This implements the Xilinx Versal eFuse, an one-time
3
The ADC is part of NPCM7XX Module. Its behavior is controled by the
4
field-programmable non-volatile storage device. There is
4
ADC_CON register. It converts one of the eight analog inputs into a
5
only one such device in the Xilinx Versal product family.
5
digital input and stores it in the ADC_DATA register when enabled.
6
6
7
This device has two separate mmio interfaces, a controller
7
Users can alter input value by using qom-set QMP command.
8
and a flatten readback.
9
8
10
The controller provides interfaces for field-programming,
9
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
11
configuration, control, and status.
10
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
12
11
Signed-off-by: Hao Wu <wuhaotsh@google.com>
13
The flatten readback is a cache to provide a byte-accessible
12
Message-id: 20210108190945.949196-4-wuhaotsh@google.com
14
read-only interface to efficiently read efuse array.
13
[PMM: Added missing hw/adc/trace.h file]
15
16
Co-authored-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
17
Co-authored-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
18
19
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
20
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
21
Signed-off-by: Tong Ho <tong.ho@xilinx.com>
22
Message-id: 20210917052400.1249094-3-tong.ho@xilinx.com
23
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
---
16
---
26
include/hw/nvram/xlnx-versal-efuse.h | 68 +++
17
docs/system/arm/nuvoton.rst | 2 +-
27
hw/nvram/xlnx-versal-efuse-cache.c | 114 ++++
18
meson.build | 1 +
28
hw/nvram/xlnx-versal-efuse-ctrl.c | 783 +++++++++++++++++++++++++++
19
hw/adc/trace.h | 1 +
29
hw/nvram/Kconfig | 4 +
20
include/hw/adc/npcm7xx_adc.h | 69 ++++++
30
hw/nvram/meson.build | 3 +
21
include/hw/arm/npcm7xx.h | 2 +
31
5 files changed, 972 insertions(+)
22
hw/adc/npcm7xx_adc.c | 301 ++++++++++++++++++++++++++
32
create mode 100644 include/hw/nvram/xlnx-versal-efuse.h
23
hw/arm/npcm7xx.c | 24 ++-
33
create mode 100644 hw/nvram/xlnx-versal-efuse-cache.c
24
tests/qtest/npcm7xx_adc-test.c | 377 +++++++++++++++++++++++++++++++++
34
create mode 100644 hw/nvram/xlnx-versal-efuse-ctrl.c
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
35
34
36
diff --git a/include/hw/nvram/xlnx-versal-efuse.h b/include/hw/nvram/xlnx-versal-efuse.h
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
37
new file mode 100644
68
new file mode 100644
38
index XXXXXXX..XXXXXXX
69
index XXXXXXX..XXXXXXX
39
--- /dev/null
70
--- /dev/null
40
+++ b/include/hw/nvram/xlnx-versal-efuse.h
71
+++ b/hw/adc/trace.h
41
@@ -XXX,XX +XXX,XX @@
72
@@ -0,0 +1 @@
42
+/*
73
+#include "trace/trace-hw_adc.h"
43
+ * Copyright (c) 2020 Xilinx Inc.
74
diff --git a/include/hw/adc/npcm7xx_adc.h b/include/hw/adc/npcm7xx_adc.h
44
+ *
45
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
46
+ * of this software and associated documentation files (the "Software"), to deal
47
+ * in the Software without restriction, including without limitation the rights
48
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
49
+ * copies of the Software, and to permit persons to whom the Software is
50
+ * furnished to do so, subject to the following conditions:
51
+ *
52
+ * The above copyright notice and this permission notice shall be included in
53
+ * all copies or substantial portions of the Software.
54
+ *
55
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
56
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
57
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
58
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
59
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
60
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
61
+ * THE SOFTWARE.
62
+ */
63
+#ifndef XLNX_VERSAL_EFUSE_H
64
+#define XLNX_VERSAL_EFUSE_H
65
+
66
+#include "hw/irq.h"
67
+#include "hw/sysbus.h"
68
+#include "hw/register.h"
69
+#include "hw/nvram/xlnx-efuse.h"
70
+
71
+#define XLNX_VERSAL_EFUSE_CTRL_R_MAX ((0x100 / 4) + 1)
72
+
73
+#define TYPE_XLNX_VERSAL_EFUSE_CTRL "xlnx,versal-efuse"
74
+#define TYPE_XLNX_VERSAL_EFUSE_CACHE "xlnx,pmc-efuse-cache"
75
+
76
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalEFuseCtrl, XLNX_VERSAL_EFUSE_CTRL);
77
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalEFuseCache, XLNX_VERSAL_EFUSE_CACHE);
78
+
79
+struct XlnxVersalEFuseCtrl {
80
+ SysBusDevice parent_obj;
81
+ qemu_irq irq_efuse_imr;
82
+
83
+ XlnxEFuse *efuse;
84
+
85
+ void *extra_pg0_lock_spec; /* Opaque property */
86
+ uint32_t extra_pg0_lock_n16;
87
+
88
+ uint32_t regs[XLNX_VERSAL_EFUSE_CTRL_R_MAX];
89
+ RegisterInfo regs_info[XLNX_VERSAL_EFUSE_CTRL_R_MAX];
90
+};
91
+
92
+struct XlnxVersalEFuseCache {
93
+ SysBusDevice parent_obj;
94
+ MemoryRegion iomem;
95
+
96
+ XlnxEFuse *efuse;
97
+};
98
+
99
+/**
100
+ * xlnx_versal_efuse_read_row:
101
+ * @s: the efuse object
102
+ * @bit: the bit-address within the 32-bit row to be read
103
+ * @denied: if non-NULL, to receive true if the row is write-only
104
+ *
105
+ * Returns: the 32-bit word containing address @bit; 0 if @denies is true
106
+ */
107
+uint32_t xlnx_versal_efuse_read_row(XlnxEFuse *s, uint32_t bit, bool *denied);
108
+
109
+#endif
110
diff --git a/hw/nvram/xlnx-versal-efuse-cache.c b/hw/nvram/xlnx-versal-efuse-cache.c
111
new file mode 100644
75
new file mode 100644
112
index XXXXXXX..XXXXXXX
76
index XXXXXXX..XXXXXXX
113
--- /dev/null
77
--- /dev/null
114
+++ b/hw/nvram/xlnx-versal-efuse-cache.c
78
+++ b/include/hw/adc/npcm7xx_adc.h
115
@@ -XXX,XX +XXX,XX @@
79
@@ -XXX,XX +XXX,XX @@
116
+/*
80
+/*
117
+ * QEMU model of the EFuse_Cache
81
+ * Nuvoton NPCM7xx ADC Module
118
+ *
82
+ *
119
+ * Copyright (c) 2017 Xilinx Inc.
83
+ * Copyright 2020 Google LLC
120
+ *
84
+ *
121
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
85
+ * This program is free software; you can redistribute it and/or modify it
122
+ * of this software and associated documentation files (the "Software"), to deal
86
+ * under the terms of the GNU General Public License as published by the
123
+ * in the Software without restriction, including without limitation the rights
87
+ * Free Software Foundation; either version 2 of the License, or
124
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
88
+ * (at your option) any later version.
125
+ * copies of the Software, and to permit persons to whom the Software is
126
+ * furnished to do so, subject to the following conditions:
127
+ *
89
+ *
128
+ * The above copyright notice and this permission notice shall be included in
90
+ * This program is distributed in the hope that it will be useful, but WITHOUT
129
+ * all copies or substantial portions of the Software.
91
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
130
+ *
92
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
131
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
93
+ * for more details.
132
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
133
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
134
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
135
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
136
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
137
+ * THE SOFTWARE.
138
+ */
94
+ */
139
+
95
+#ifndef NPCM7XX_ADC_H
140
+#include "qemu/osdep.h"
96
+#define NPCM7XX_ADC_H
141
+#include "hw/nvram/xlnx-versal-efuse.h"
97
+
142
+
98
+#include "hw/clock.h"
143
+#include "qemu/log.h"
99
+#include "hw/irq.h"
144
+#include "hw/qdev-properties.h"
100
+#include "hw/sysbus.h"
145
+
101
+#include "qemu/timer.h"
146
+#define MR_SIZE 0xC00
102
+
147
+
103
+#define NPCM7XX_ADC_NUM_INPUTS 8
148
+static uint64_t efuse_cache_read(void *opaque, hwaddr addr, unsigned size)
104
+/**
149
+{
105
+ * This value should not be changed unless write_adc_calibration function in
150
+ XlnxVersalEFuseCache *s = XLNX_VERSAL_EFUSE_CACHE(opaque);
106
+ * hw/arm/npcm7xx.c is also changed.
151
+ unsigned int w0 = QEMU_ALIGN_DOWN(addr * 8, 32);
107
+ */
152
+ unsigned int w1 = QEMU_ALIGN_DOWN((addr + size - 1) * 8, 32);
108
+#define NPCM7XX_ADC_NUM_CALIB 2
153
+
109
+
154
+ uint64_t ret;
110
+/**
155
+
111
+ * struct NPCM7xxADCState - Analog to Digital Converter Module device state.
156
+ assert(w0 == w1 || (w0 + 32) == w1);
112
+ * @parent: System bus device.
157
+
113
+ * @iomem: Memory region through which registers are accessed.
158
+ ret = xlnx_versal_efuse_read_row(s->efuse, w1, NULL);
114
+ * @conv_timer: The timer counts down remaining cycles for the conversion.
159
+ if (w0 < w1) {
115
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
160
+ ret <<= 32;
116
+ * @con: The Control Register.
161
+ ret |= xlnx_versal_efuse_read_row(s->efuse, w0, NULL);
117
+ * @data: The Data Buffer.
162
+ }
118
+ * @clock: The ADC Clock.
163
+
119
+ * @adci: The input voltage in units of uV. 1uv = 1e-6V.
164
+ /* If 'addr' unaligned, the guest is always assumed to be little-endian. */
120
+ * @vref: The external reference voltage.
165
+ addr &= 3;
121
+ * @iref: The internal reference voltage, initialized at launch time.
166
+ if (addr) {
122
+ * @rv: The calibrated output values of 0.5V and 1.5V for the ADC.
167
+ ret >>= 8 * addr;
123
+ */
168
+ }
124
+typedef struct {
169
+
125
+ SysBusDevice parent;
170
+ return ret;
126
+
171
+}
127
+ MemoryRegion iomem;
172
+
128
+
173
+static void efuse_cache_write(void *opaque, hwaddr addr, uint64_t value,
129
+ QEMUTimer conv_timer;
174
+ unsigned size)
130
+
175
+{
131
+ qemu_irq irq;
176
+ /* No Register Writes allowed */
132
+ uint32_t con;
177
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: efuse cache registers are read-only",
133
+ uint32_t data;
178
+ __func__);
134
+ Clock *clock;
179
+}
135
+
180
+
136
+ /* Voltages are in unit of uV. 1V = 1000000uV. */
181
+static const MemoryRegionOps efuse_cache_ops = {
137
+ uint32_t adci[NPCM7XX_ADC_NUM_INPUTS];
182
+ .read = efuse_cache_read,
138
+ uint32_t vref;
183
+ .write = efuse_cache_write,
139
+ uint32_t iref;
184
+ .endianness = DEVICE_LITTLE_ENDIAN,
140
+
185
+ .valid = {
141
+ uint16_t calibration_r_values[NPCM7XX_ADC_NUM_CALIB];
186
+ .min_access_size = 1,
142
+} NPCM7xxADCState;
187
+ .max_access_size = 4,
143
+
188
+ },
144
+#define TYPE_NPCM7XX_ADC "npcm7xx-adc"
189
+};
145
+#define NPCM7XX_ADC(obj) \
190
+
146
+ OBJECT_CHECK(NPCM7xxADCState, (obj), TYPE_NPCM7XX_ADC)
191
+static void efuse_cache_init(Object *obj)
147
+
192
+{
148
+#endif /* NPCM7XX_ADC_H */
193
+ XlnxVersalEFuseCache *s = XLNX_VERSAL_EFUSE_CACHE(obj);
149
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
194
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
150
index XXXXXXX..XXXXXXX 100644
195
+
151
--- a/include/hw/arm/npcm7xx.h
196
+ memory_region_init_io(&s->iomem, obj, &efuse_cache_ops, s,
152
+++ b/include/hw/arm/npcm7xx.h
197
+ TYPE_XLNX_VERSAL_EFUSE_CACHE, MR_SIZE);
153
@@ -XXX,XX +XXX,XX @@
198
+ sysbus_init_mmio(sbd, &s->iomem);
154
#define NPCM7XX_H
199
+}
155
200
+
156
#include "hw/boards.h"
201
+static Property efuse_cache_props[] = {
157
+#include "hw/adc/npcm7xx_adc.h"
202
+ DEFINE_PROP_LINK("efuse",
158
#include "hw/cpu/a9mpcore.h"
203
+ XlnxVersalEFuseCache, efuse,
159
#include "hw/gpio/npcm7xx_gpio.h"
204
+ TYPE_XLNX_EFUSE, XlnxEFuse *),
160
#include "hw/mem/npcm7xx_mc.h"
205
+
161
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
206
+ DEFINE_PROP_END_OF_LIST(),
162
NPCM7xxGCRState gcr;
207
+};
163
NPCM7xxCLKState clk;
208
+
164
NPCM7xxTimerCtrlState tim[3];
209
+static void efuse_cache_class_init(ObjectClass *klass, void *data)
165
+ NPCM7xxADCState adc;
210
+{
166
NPCM7xxOTPState key_storage;
211
+ DeviceClass *dc = DEVICE_CLASS(klass);
167
NPCM7xxOTPState fuse_array;
212
+
168
NPCM7xxMCState mc;
213
+ device_class_set_props(dc, efuse_cache_props);
169
diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c
214
+}
215
+
216
+static const TypeInfo efuse_cache_info = {
217
+ .name = TYPE_XLNX_VERSAL_EFUSE_CACHE,
218
+ .parent = TYPE_SYS_BUS_DEVICE,
219
+ .instance_size = sizeof(XlnxVersalEFuseCache),
220
+ .class_init = efuse_cache_class_init,
221
+ .instance_init = efuse_cache_init,
222
+};
223
+
224
+static void efuse_cache_register_types(void)
225
+{
226
+ type_register_static(&efuse_cache_info);
227
+}
228
+
229
+type_init(efuse_cache_register_types)
230
diff --git a/hw/nvram/xlnx-versal-efuse-ctrl.c b/hw/nvram/xlnx-versal-efuse-ctrl.c
231
new file mode 100644
170
new file mode 100644
232
index XXXXXXX..XXXXXXX
171
index XXXXXXX..XXXXXXX
233
--- /dev/null
172
--- /dev/null
234
+++ b/hw/nvram/xlnx-versal-efuse-ctrl.c
173
+++ b/hw/adc/npcm7xx_adc.c
235
@@ -XXX,XX +XXX,XX @@
174
@@ -XXX,XX +XXX,XX @@
236
+/*
175
+/*
237
+ * QEMU model of the Versal eFuse controller
176
+ * Nuvoton NPCM7xx ADC Module
238
+ *
177
+ *
239
+ * Copyright (c) 2020 Xilinx Inc.
178
+ * Copyright 2020 Google LLC
240
+ *
179
+ *
241
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
180
+ * This program is free software; you can redistribute it and/or modify it
242
+ * of this software and associated documentation files (the "Software"), to deal
181
+ * under the terms of the GNU General Public License as published by the
243
+ * in the Software without restriction, including without limitation the rights
182
+ * Free Software Foundation; either version 2 of the License, or
244
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
183
+ * (at your option) any later version.
245
+ * copies of the Software, and to permit persons to whom the Software is
246
+ * furnished to do so, subject to the following conditions:
247
+ *
184
+ *
248
+ * The above copyright notice and this permission notice shall be included in
185
+ * This program is distributed in the hope that it will be useful, but WITHOUT
249
+ * all copies or substantial portions of the Software.
186
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
250
+ *
187
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
251
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
188
+ * for more details.
252
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
253
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
254
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
255
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
256
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
257
+ * THE SOFTWARE.
258
+ */
189
+ */
259
+
190
+
260
+#include "qemu/osdep.h"
191
+#include "qemu/osdep.h"
261
+#include "hw/nvram/xlnx-versal-efuse.h"
192
+#include "hw/adc/npcm7xx_adc.h"
262
+
193
+#include "hw/qdev-clock.h"
194
+#include "hw/qdev-properties.h"
195
+#include "hw/registerfields.h"
196
+#include "migration/vmstate.h"
263
+#include "qemu/log.h"
197
+#include "qemu/log.h"
264
+#include "qapi/error.h"
198
+#include "qemu/module.h"
265
+#include "migration/vmstate.h"
199
+#include "qemu/timer.h"
266
+#include "hw/qdev-properties.h"
200
+#include "qemu/units.h"
267
+
201
+#include "trace.h"
268
+#ifndef XLNX_VERSAL_EFUSE_CTRL_ERR_DEBUG
202
+
269
+#define XLNX_VERSAL_EFUSE_CTRL_ERR_DEBUG 0
203
+REG32(NPCM7XX_ADC_CON, 0x0)
270
+#endif
204
+REG32(NPCM7XX_ADC_DATA, 0x4)
271
+
205
+
272
+REG32(WR_LOCK, 0x0)
206
+/* Register field definitions. */
273
+ FIELD(WR_LOCK, LOCK, 0, 16)
207
+#define NPCM7XX_ADC_CON_MUX(rv) extract32(rv, 24, 4)
274
+REG32(CFG, 0x4)
208
+#define NPCM7XX_ADC_CON_INT_EN BIT(21)
275
+ FIELD(CFG, SLVERR_ENABLE, 5, 1)
209
+#define NPCM7XX_ADC_CON_REFSEL BIT(19)
276
+ FIELD(CFG, MARGIN_RD, 2, 1)
210
+#define NPCM7XX_ADC_CON_INT BIT(18)
277
+ FIELD(CFG, PGM_EN, 1, 1)
211
+#define NPCM7XX_ADC_CON_EN BIT(17)
278
+REG32(STATUS, 0x8)
212
+#define NPCM7XX_ADC_CON_RST BIT(16)
279
+ FIELD(STATUS, AES_USER_KEY_1_CRC_PASS, 11, 1)
213
+#define NPCM7XX_ADC_CON_CONV BIT(14)
280
+ FIELD(STATUS, AES_USER_KEY_1_CRC_DONE, 10, 1)
214
+#define NPCM7XX_ADC_CON_DIV(rv) extract32(rv, 1, 8)
281
+ FIELD(STATUS, AES_USER_KEY_0_CRC_PASS, 9, 1)
215
+
282
+ FIELD(STATUS, AES_USER_KEY_0_CRC_DONE, 8, 1)
216
+#define NPCM7XX_ADC_MAX_RESULT 1023
283
+ FIELD(STATUS, AES_CRC_PASS, 7, 1)
217
+#define NPCM7XX_ADC_DEFAULT_IREF 2000000
284
+ FIELD(STATUS, AES_CRC_DONE, 6, 1)
218
+#define NPCM7XX_ADC_CONV_CYCLES 20
285
+ FIELD(STATUS, CACHE_DONE, 5, 1)
219
+#define NPCM7XX_ADC_RESET_CYCLES 10
286
+ FIELD(STATUS, CACHE_LOAD, 4, 1)
220
+#define NPCM7XX_ADC_R0_INPUT 500000
287
+ FIELD(STATUS, EFUSE_2_TBIT, 2, 1)
221
+#define NPCM7XX_ADC_R1_INPUT 1500000
288
+ FIELD(STATUS, EFUSE_1_TBIT, 1, 1)
222
+
289
+ FIELD(STATUS, EFUSE_0_TBIT, 0, 1)
223
+static void npcm7xx_adc_reset(NPCM7xxADCState *s)
290
+REG32(EFUSE_PGM_ADDR, 0xc)
224
+{
291
+ FIELD(EFUSE_PGM_ADDR, PAGE, 13, 4)
225
+ timer_del(&s->conv_timer);
292
+ FIELD(EFUSE_PGM_ADDR, ROW, 5, 8)
226
+ s->con = 0x000c0001;
293
+ FIELD(EFUSE_PGM_ADDR, COLUMN, 0, 5)
227
+ s->data = 0x00000000;
294
+REG32(EFUSE_RD_ADDR, 0x10)
228
+}
295
+ FIELD(EFUSE_RD_ADDR, PAGE, 13, 4)
229
+
296
+ FIELD(EFUSE_RD_ADDR, ROW, 5, 8)
230
+static uint32_t npcm7xx_adc_convert(uint32_t input, uint32_t ref)
297
+REG32(EFUSE_RD_DATA, 0x14)
231
+{
298
+REG32(TPGM, 0x18)
232
+ uint32_t result;
299
+ FIELD(TPGM, VALUE, 0, 16)
233
+
300
+REG32(TRD, 0x1c)
234
+ result = input * (NPCM7XX_ADC_MAX_RESULT + 1) / ref;
301
+ FIELD(TRD, VALUE, 0, 8)
235
+ if (result > NPCM7XX_ADC_MAX_RESULT) {
302
+REG32(TSU_H_PS, 0x20)
236
+ result = NPCM7XX_ADC_MAX_RESULT;
303
+ FIELD(TSU_H_PS, VALUE, 0, 8)
237
+ }
304
+REG32(TSU_H_PS_CS, 0x24)
238
+
305
+ FIELD(TSU_H_PS_CS, VALUE, 0, 8)
239
+ return result;
306
+REG32(TRDM, 0x28)
240
+}
307
+ FIELD(TRDM, VALUE, 0, 8)
241
+
308
+REG32(TSU_H_CS, 0x2c)
242
+static uint32_t npcm7xx_adc_prescaler(NPCM7xxADCState *s)
309
+ FIELD(TSU_H_CS, VALUE, 0, 8)
243
+{
310
+REG32(EFUSE_ISR, 0x30)
244
+ return 2 * (NPCM7XX_ADC_CON_DIV(s->con) + 1);
311
+ FIELD(EFUSE_ISR, APB_SLVERR, 31, 1)
245
+}
312
+ FIELD(EFUSE_ISR, CACHE_PARITY_E2, 14, 1)
246
+
313
+ FIELD(EFUSE_ISR, CACHE_PARITY_E1, 13, 1)
247
+static void npcm7xx_adc_start_timer(Clock *clk, QEMUTimer *timer,
314
+ FIELD(EFUSE_ISR, CACHE_PARITY_E0S, 12, 1)
248
+ uint32_t cycles, uint32_t prescaler)
315
+ FIELD(EFUSE_ISR, CACHE_PARITY_E0R, 11, 1)
249
+{
316
+ FIELD(EFUSE_ISR, CACHE_APB_SLVERR, 10, 1)
250
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
317
+ FIELD(EFUSE_ISR, CACHE_REQ_ERROR, 9, 1)
251
+ int64_t ticks = cycles;
318
+ FIELD(EFUSE_ISR, MAIN_REQ_ERROR, 8, 1)
252
+ int64_t ns;
319
+ FIELD(EFUSE_ISR, READ_ON_CACHE_LD, 7, 1)
253
+
320
+ FIELD(EFUSE_ISR, CACHE_FSM_ERROR, 6, 1)
254
+ ticks *= prescaler;
321
+ FIELD(EFUSE_ISR, MAIN_FSM_ERROR, 5, 1)
255
+ ns = clock_ticks_to_ns(clk, ticks);
322
+ FIELD(EFUSE_ISR, CACHE_ERROR, 4, 1)
256
+ ns += now;
323
+ FIELD(EFUSE_ISR, RD_ERROR, 3, 1)
257
+ timer_mod(timer, ns);
324
+ FIELD(EFUSE_ISR, RD_DONE, 2, 1)
258
+}
325
+ FIELD(EFUSE_ISR, PGM_ERROR, 1, 1)
259
+
326
+ FIELD(EFUSE_ISR, PGM_DONE, 0, 1)
260
+static void npcm7xx_adc_start_convert(NPCM7xxADCState *s)
327
+REG32(EFUSE_IMR, 0x34)
261
+{
328
+ FIELD(EFUSE_IMR, APB_SLVERR, 31, 1)
262
+ uint32_t prescaler = npcm7xx_adc_prescaler(s);
329
+ FIELD(EFUSE_IMR, CACHE_PARITY_E2, 14, 1)
263
+
330
+ FIELD(EFUSE_IMR, CACHE_PARITY_E1, 13, 1)
264
+ npcm7xx_adc_start_timer(s->clock, &s->conv_timer, NPCM7XX_ADC_CONV_CYCLES,
331
+ FIELD(EFUSE_IMR, CACHE_PARITY_E0S, 12, 1)
265
+ prescaler);
332
+ FIELD(EFUSE_IMR, CACHE_PARITY_E0R, 11, 1)
266
+}
333
+ FIELD(EFUSE_IMR, CACHE_APB_SLVERR, 10, 1)
267
+
334
+ FIELD(EFUSE_IMR, CACHE_REQ_ERROR, 9, 1)
268
+static void npcm7xx_adc_convert_done(void *opaque)
335
+ FIELD(EFUSE_IMR, MAIN_REQ_ERROR, 8, 1)
269
+{
336
+ FIELD(EFUSE_IMR, READ_ON_CACHE_LD, 7, 1)
270
+ NPCM7xxADCState *s = opaque;
337
+ FIELD(EFUSE_IMR, CACHE_FSM_ERROR, 6, 1)
271
+ uint32_t input = NPCM7XX_ADC_CON_MUX(s->con);
338
+ FIELD(EFUSE_IMR, MAIN_FSM_ERROR, 5, 1)
272
+ uint32_t ref = (s->con & NPCM7XX_ADC_CON_REFSEL)
339
+ FIELD(EFUSE_IMR, CACHE_ERROR, 4, 1)
273
+ ? s->iref : s->vref;
340
+ FIELD(EFUSE_IMR, RD_ERROR, 3, 1)
274
+
341
+ FIELD(EFUSE_IMR, RD_DONE, 2, 1)
275
+ if (input >= NPCM7XX_ADC_NUM_INPUTS) {
342
+ FIELD(EFUSE_IMR, PGM_ERROR, 1, 1)
276
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid input: %u\n",
343
+ FIELD(EFUSE_IMR, PGM_DONE, 0, 1)
277
+ __func__, input);
344
+REG32(EFUSE_IER, 0x38)
345
+ FIELD(EFUSE_IER, APB_SLVERR, 31, 1)
346
+ FIELD(EFUSE_IER, CACHE_PARITY_E2, 14, 1)
347
+ FIELD(EFUSE_IER, CACHE_PARITY_E1, 13, 1)
348
+ FIELD(EFUSE_IER, CACHE_PARITY_E0S, 12, 1)
349
+ FIELD(EFUSE_IER, CACHE_PARITY_E0R, 11, 1)
350
+ FIELD(EFUSE_IER, CACHE_APB_SLVERR, 10, 1)
351
+ FIELD(EFUSE_IER, CACHE_REQ_ERROR, 9, 1)
352
+ FIELD(EFUSE_IER, MAIN_REQ_ERROR, 8, 1)
353
+ FIELD(EFUSE_IER, READ_ON_CACHE_LD, 7, 1)
354
+ FIELD(EFUSE_IER, CACHE_FSM_ERROR, 6, 1)
355
+ FIELD(EFUSE_IER, MAIN_FSM_ERROR, 5, 1)
356
+ FIELD(EFUSE_IER, CACHE_ERROR, 4, 1)
357
+ FIELD(EFUSE_IER, RD_ERROR, 3, 1)
358
+ FIELD(EFUSE_IER, RD_DONE, 2, 1)
359
+ FIELD(EFUSE_IER, PGM_ERROR, 1, 1)
360
+ FIELD(EFUSE_IER, PGM_DONE, 0, 1)
361
+REG32(EFUSE_IDR, 0x3c)
362
+ FIELD(EFUSE_IDR, APB_SLVERR, 31, 1)
363
+ FIELD(EFUSE_IDR, CACHE_PARITY_E2, 14, 1)
364
+ FIELD(EFUSE_IDR, CACHE_PARITY_E1, 13, 1)
365
+ FIELD(EFUSE_IDR, CACHE_PARITY_E0S, 12, 1)
366
+ FIELD(EFUSE_IDR, CACHE_PARITY_E0R, 11, 1)
367
+ FIELD(EFUSE_IDR, CACHE_APB_SLVERR, 10, 1)
368
+ FIELD(EFUSE_IDR, CACHE_REQ_ERROR, 9, 1)
369
+ FIELD(EFUSE_IDR, MAIN_REQ_ERROR, 8, 1)
370
+ FIELD(EFUSE_IDR, READ_ON_CACHE_LD, 7, 1)
371
+ FIELD(EFUSE_IDR, CACHE_FSM_ERROR, 6, 1)
372
+ FIELD(EFUSE_IDR, MAIN_FSM_ERROR, 5, 1)
373
+ FIELD(EFUSE_IDR, CACHE_ERROR, 4, 1)
374
+ FIELD(EFUSE_IDR, RD_ERROR, 3, 1)
375
+ FIELD(EFUSE_IDR, RD_DONE, 2, 1)
376
+ FIELD(EFUSE_IDR, PGM_ERROR, 1, 1)
377
+ FIELD(EFUSE_IDR, PGM_DONE, 0, 1)
378
+REG32(EFUSE_CACHE_LOAD, 0x40)
379
+ FIELD(EFUSE_CACHE_LOAD, LOAD, 0, 1)
380
+REG32(EFUSE_PGM_LOCK, 0x44)
381
+ FIELD(EFUSE_PGM_LOCK, SPK_ID_LOCK, 0, 1)
382
+REG32(EFUSE_AES_CRC, 0x48)
383
+REG32(EFUSE_AES_USR_KEY0_CRC, 0x4c)
384
+REG32(EFUSE_AES_USR_KEY1_CRC, 0x50)
385
+REG32(EFUSE_PD, 0x54)
386
+REG32(EFUSE_ANLG_OSC_SW_1LP, 0x60)
387
+REG32(EFUSE_TEST_CTRL, 0x100)
388
+
389
+#define R_MAX (R_EFUSE_TEST_CTRL + 1)
390
+
391
+#define R_WR_LOCK_UNLOCK_PASSCODE (0xDF0D)
392
+
393
+/*
394
+ * eFuse layout references:
395
+ * https://github.com/Xilinx/embeddedsw/blob/release-2019.2/lib/sw_services/xilnvm/src/xnvm_efuse_hw.h
396
+ */
397
+#define BIT_POS_OF(A_) \
398
+ ((uint32_t)((A_) & (R_EFUSE_PGM_ADDR_ROW_MASK | \
399
+ R_EFUSE_PGM_ADDR_COLUMN_MASK)))
400
+
401
+#define BIT_POS(R_, C_) \
402
+ ((uint32_t)((R_EFUSE_PGM_ADDR_ROW_MASK \
403
+ & ((R_) << R_EFUSE_PGM_ADDR_ROW_SHIFT)) \
404
+ | \
405
+ (R_EFUSE_PGM_ADDR_COLUMN_MASK \
406
+ & ((C_) << R_EFUSE_PGM_ADDR_COLUMN_SHIFT))))
407
+
408
+#define EFUSE_TBIT_POS(A_) (BIT_POS_OF(A_) >= BIT_POS(0, 28))
409
+
410
+#define EFUSE_ANCHOR_ROW (0)
411
+#define EFUSE_ANCHOR_3_COL (27)
412
+#define EFUSE_ANCHOR_1_COL (1)
413
+
414
+#define EFUSE_AES_KEY_START BIT_POS(12, 0)
415
+#define EFUSE_AES_KEY_END BIT_POS(19, 31)
416
+#define EFUSE_USER_KEY_0_START BIT_POS(20, 0)
417
+#define EFUSE_USER_KEY_0_END BIT_POS(27, 31)
418
+#define EFUSE_USER_KEY_1_START BIT_POS(28, 0)
419
+#define EFUSE_USER_KEY_1_END BIT_POS(35, 31)
420
+
421
+#define EFUSE_RD_BLOCKED_START EFUSE_AES_KEY_START
422
+#define EFUSE_RD_BLOCKED_END EFUSE_USER_KEY_1_END
423
+
424
+#define EFUSE_GLITCH_DET_WR_LK BIT_POS(4, 31)
425
+#define EFUSE_PPK0_WR_LK BIT_POS(43, 6)
426
+#define EFUSE_PPK1_WR_LK BIT_POS(43, 7)
427
+#define EFUSE_PPK2_WR_LK BIT_POS(43, 8)
428
+#define EFUSE_AES_WR_LK BIT_POS(43, 11)
429
+#define EFUSE_USER_KEY_0_WR_LK BIT_POS(43, 13)
430
+#define EFUSE_USER_KEY_1_WR_LK BIT_POS(43, 15)
431
+#define EFUSE_PUF_SYN_LK BIT_POS(43, 16)
432
+#define EFUSE_DNA_WR_LK BIT_POS(43, 27)
433
+#define EFUSE_BOOT_ENV_WR_LK BIT_POS(43, 28)
434
+
435
+#define EFUSE_PGM_LOCKED_START BIT_POS(44, 0)
436
+#define EFUSE_PGM_LOCKED_END BIT_POS(51, 31)
437
+
438
+#define EFUSE_PUF_PAGE (2)
439
+#define EFUSE_PUF_SYN_START BIT_POS(129, 0)
440
+#define EFUSE_PUF_SYN_END BIT_POS(255, 27)
441
+
442
+#define EFUSE_KEY_CRC_LK_ROW (43)
443
+#define EFUSE_AES_KEY_CRC_LK_MASK ((1U << 9) | (1U << 10))
444
+#define EFUSE_USER_KEY_0_CRC_LK_MASK (1U << 12)
445
+#define EFUSE_USER_KEY_1_CRC_LK_MASK (1U << 14)
446
+
447
+/*
448
+ * A handy macro to return value of an array element,
449
+ * or a specific default if given index is out of bound.
450
+ */
451
+#define ARRAY_GET(A_, I_, D_) \
452
+ ((unsigned int)(I_) < ARRAY_SIZE(A_) ? (A_)[I_] : (D_))
453
+
454
+QEMU_BUILD_BUG_ON(R_MAX != ARRAY_SIZE(((XlnxVersalEFuseCtrl *)0)->regs));
455
+
456
+typedef struct XlnxEFuseLkSpec {
457
+ uint16_t row;
458
+ uint16_t lk_bit;
459
+} XlnxEFuseLkSpec;
460
+
461
+static void efuse_imr_update_irq(XlnxVersalEFuseCtrl *s)
462
+{
463
+ bool pending = s->regs[R_EFUSE_ISR] & ~s->regs[R_EFUSE_IMR];
464
+ qemu_set_irq(s->irq_efuse_imr, pending);
465
+}
466
+
467
+static void efuse_isr_postw(RegisterInfo *reg, uint64_t val64)
468
+{
469
+ XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(reg->opaque);
470
+ efuse_imr_update_irq(s);
471
+}
472
+
473
+static uint64_t efuse_ier_prew(RegisterInfo *reg, uint64_t val64)
474
+{
475
+ XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(reg->opaque);
476
+ uint32_t val = val64;
477
+
478
+ s->regs[R_EFUSE_IMR] &= ~val;
479
+ efuse_imr_update_irq(s);
480
+ return 0;
481
+}
482
+
483
+static uint64_t efuse_idr_prew(RegisterInfo *reg, uint64_t val64)
484
+{
485
+ XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(reg->opaque);
486
+ uint32_t val = val64;
487
+
488
+ s->regs[R_EFUSE_IMR] |= val;
489
+ efuse_imr_update_irq(s);
490
+ return 0;
491
+}
492
+
493
+static void efuse_status_tbits_sync(XlnxVersalEFuseCtrl *s)
494
+{
495
+ uint32_t check = xlnx_efuse_tbits_check(s->efuse);
496
+ uint32_t val = s->regs[R_STATUS];
497
+
498
+ val = FIELD_DP32(val, STATUS, EFUSE_0_TBIT, !!(check & (1 << 0)));
499
+ val = FIELD_DP32(val, STATUS, EFUSE_1_TBIT, !!(check & (1 << 1)));
500
+ val = FIELD_DP32(val, STATUS, EFUSE_2_TBIT, !!(check & (1 << 2)));
501
+
502
+ s->regs[R_STATUS] = val;
503
+}
504
+
505
+static void efuse_anchor_bits_check(XlnxVersalEFuseCtrl *s)
506
+{
507
+ unsigned page;
508
+
509
+ if (!s->efuse || !s->efuse->init_tbits) {
510
+ return;
278
+ return;
511
+ }
279
+ }
512
+
280
+ s->data = npcm7xx_adc_convert(s->adci[input], ref);
513
+ for (page = 0; page < s->efuse->efuse_nr; page++) {
281
+ if (s->con & NPCM7XX_ADC_CON_INT_EN) {
514
+ uint32_t row = 0, bit;
282
+ s->con |= NPCM7XX_ADC_CON_INT;
515
+
283
+ qemu_irq_raise(s->irq);
516
+ row = FIELD_DP32(row, EFUSE_PGM_ADDR, PAGE, page);
284
+ }
517
+ row = FIELD_DP32(row, EFUSE_PGM_ADDR, ROW, EFUSE_ANCHOR_ROW);
285
+ s->con &= ~NPCM7XX_ADC_CON_CONV;
518
+
286
+}
519
+ bit = FIELD_DP32(row, EFUSE_PGM_ADDR, COLUMN, EFUSE_ANCHOR_3_COL);
287
+
520
+ if (!xlnx_efuse_get_bit(s->efuse, bit)) {
288
+static void npcm7xx_adc_calibrate(NPCM7xxADCState *adc)
521
+ xlnx_efuse_set_bit(s->efuse, bit);
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);
522
+ }
322
+ }
523
+
323
+ }
524
+ bit = FIELD_DP32(row, EFUSE_PGM_ADDR, COLUMN, EFUSE_ANCHOR_1_COL);
324
+}
525
+ if (!xlnx_efuse_get_bit(s->efuse, bit)) {
325
+
526
+ xlnx_efuse_set_bit(s->efuse, bit);
326
+static uint64_t npcm7xx_adc_read(void *opaque, hwaddr offset, unsigned size)
527
+ }
327
+{
528
+ }
328
+ uint64_t value = 0;
529
+}
329
+ NPCM7xxADCState *s = opaque;
530
+
330
+
531
+static void efuse_key_crc_check(RegisterInfo *reg, uint32_t crc,
331
+ switch (offset) {
532
+ uint32_t pass_mask, uint32_t done_mask,
332
+ case A_NPCM7XX_ADC_CON:
533
+ unsigned first, uint32_t lk_mask)
333
+ value = s->con;
534
+{
535
+ XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(reg->opaque);
536
+ uint32_t r, lk_bits;
537
+
538
+ /*
539
+ * To start, assume both DONE and PASS, and clear PASS by xor
540
+ * if CRC-check fails or CRC-check disabled by lock fuse.
541
+ */
542
+ r = s->regs[R_STATUS] | done_mask | pass_mask;
543
+
544
+ lk_bits = xlnx_efuse_get_row(s->efuse, EFUSE_KEY_CRC_LK_ROW) & lk_mask;
545
+ if (lk_bits == 0 && xlnx_efuse_k256_check(s->efuse, crc, first)) {
546
+ pass_mask = 0;
547
+ }
548
+
549
+ s->regs[R_STATUS] = r ^ pass_mask;
550
+}
551
+
552
+static void efuse_data_sync(XlnxVersalEFuseCtrl *s)
553
+{
554
+ efuse_status_tbits_sync(s);
555
+}
556
+
557
+static int efuse_lk_spec_cmp(const void *a, const void *b)
558
+{
559
+ uint16_t r1 = ((const XlnxEFuseLkSpec *)a)->row;
560
+ uint16_t r2 = ((const XlnxEFuseLkSpec *)b)->row;
561
+
562
+ return (r1 > r2) - (r1 < r2);
563
+}
564
+
565
+static void efuse_lk_spec_sort(XlnxVersalEFuseCtrl *s)
566
+{
567
+ XlnxEFuseLkSpec *ary = s->extra_pg0_lock_spec;
568
+ const uint32_t n8 = s->extra_pg0_lock_n16 * 2;
569
+ const uint32_t sz = sizeof(ary[0]);
570
+ const uint32_t cnt = n8 / sz;
571
+
572
+ if (ary && cnt) {
573
+ qsort(ary, cnt, sz, efuse_lk_spec_cmp);
574
+ }
575
+}
576
+
577
+static uint32_t efuse_lk_spec_find(XlnxVersalEFuseCtrl *s, uint32_t row)
578
+{
579
+ const XlnxEFuseLkSpec *ary = s->extra_pg0_lock_spec;
580
+ const uint32_t n8 = s->extra_pg0_lock_n16 * 2;
581
+ const uint32_t sz = sizeof(ary[0]);
582
+ const uint32_t cnt = n8 / sz;
583
+ const XlnxEFuseLkSpec *item = NULL;
584
+
585
+ if (ary && cnt) {
586
+ XlnxEFuseLkSpec k = { .row = row, };
587
+
588
+ item = bsearch(&k, ary, cnt, sz, efuse_lk_spec_cmp);
589
+ }
590
+
591
+ return item ? item->lk_bit : 0;
592
+}
593
+
594
+static uint32_t efuse_bit_locked(XlnxVersalEFuseCtrl *s, uint32_t bit)
595
+{
596
+ /* Hard-coded locks */
597
+ static const uint16_t pg0_hard_lock[] = {
598
+ [4] = EFUSE_GLITCH_DET_WR_LK,
599
+ [37] = EFUSE_BOOT_ENV_WR_LK,
600
+
601
+ [8 ... 11] = EFUSE_DNA_WR_LK,
602
+ [12 ... 19] = EFUSE_AES_WR_LK,
603
+ [20 ... 27] = EFUSE_USER_KEY_0_WR_LK,
604
+ [28 ... 35] = EFUSE_USER_KEY_1_WR_LK,
605
+ [64 ... 71] = EFUSE_PPK0_WR_LK,
606
+ [72 ... 79] = EFUSE_PPK1_WR_LK,
607
+ [80 ... 87] = EFUSE_PPK2_WR_LK,
608
+ };
609
+
610
+ uint32_t row = FIELD_EX32(bit, EFUSE_PGM_ADDR, ROW);
611
+ uint32_t lk_bit = ARRAY_GET(pg0_hard_lock, row, 0);
612
+
613
+ return lk_bit ? lk_bit : efuse_lk_spec_find(s, row);
614
+}
615
+
616
+static bool efuse_pgm_locked(XlnxVersalEFuseCtrl *s, unsigned int bit)
617
+{
618
+
619
+ unsigned int lock = 1;
620
+
621
+ /* Global lock */
622
+ if (!ARRAY_FIELD_EX32(s->regs, CFG, PGM_EN)) {
623
+ goto ret_lock;
624
+ }
625
+
626
+ /* Row lock */
627
+ switch (FIELD_EX32(bit, EFUSE_PGM_ADDR, PAGE)) {
628
+ case 0:
629
+ if (ARRAY_FIELD_EX32(s->regs, EFUSE_PGM_LOCK, SPK_ID_LOCK) &&
630
+ bit >= EFUSE_PGM_LOCKED_START && bit <= EFUSE_PGM_LOCKED_END) {
631
+ goto ret_lock;
632
+ }
633
+
634
+ lock = efuse_bit_locked(s, bit);
635
+ break;
334
+ break;
636
+ case EFUSE_PUF_PAGE:
335
+
637
+ if (bit < EFUSE_PUF_SYN_START || bit > EFUSE_PUF_SYN_END) {
336
+ case A_NPCM7XX_ADC_DATA:
638
+ lock = 0;
337
+ value = s->data;
639
+ goto ret_lock;
640
+ }
641
+
642
+ lock = EFUSE_PUF_SYN_LK;
643
+ break;
338
+ break;
339
+
644
+ default:
340
+ default:
645
+ lock = 0;
646
+ goto ret_lock;
647
+ }
648
+
649
+ /* Row lock by an efuse bit */
650
+ if (lock) {
651
+ lock = xlnx_efuse_get_bit(s->efuse, lock);
652
+ }
653
+
654
+ ret_lock:
655
+ return lock != 0;
656
+}
657
+
658
+static void efuse_pgm_addr_postw(RegisterInfo *reg, uint64_t val64)
659
+{
660
+ XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(reg->opaque);
661
+ unsigned bit = val64;
662
+ bool ok = false;
663
+
664
+ /* Always zero out PGM_ADDR because it is write-only */
665
+ s->regs[R_EFUSE_PGM_ADDR] = 0;
666
+
667
+ /*
668
+ * Indicate error if bit is write-protected (or read-only
669
+ * as guarded by efuse_set_bit()).
670
+ *
671
+ * Keep it simple by not modeling program timing.
672
+ *
673
+ * Note: model must NEVER clear the PGM_ERROR bit; it is
674
+ * up to guest to do so (or by reset).
675
+ */
676
+ if (efuse_pgm_locked(s, bit)) {
677
+ qemu_log_mask(LOG_GUEST_ERROR,
341
+ qemu_log_mask(LOG_GUEST_ERROR,
678
+ "%s: Denied setting of efuse<%u, %u, %u>\n",
342
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
679
+ object_get_canonical_path(OBJECT(s)),
343
+ __func__, offset);
680
+ FIELD_EX32(bit, EFUSE_PGM_ADDR, PAGE),
344
+ break;
681
+ FIELD_EX32(bit, EFUSE_PGM_ADDR, ROW),
345
+ }
682
+ FIELD_EX32(bit, EFUSE_PGM_ADDR, COLUMN));
346
+
683
+ } else if (xlnx_efuse_set_bit(s->efuse, bit)) {
347
+ trace_npcm7xx_adc_read(DEVICE(s)->canonical_path, offset, value);
684
+ ok = true;
348
+ return value;
685
+ if (EFUSE_TBIT_POS(bit)) {
349
+}
686
+ efuse_status_tbits_sync(s);
350
+
687
+ }
351
+static void npcm7xx_adc_write(void *opaque, hwaddr offset, uint64_t v,
688
+ }
352
+ unsigned size)
689
+
353
+{
690
+ if (!ok) {
354
+ NPCM7xxADCState *s = opaque;
691
+ ARRAY_FIELD_DP32(s->regs, EFUSE_ISR, PGM_ERROR, 1);
355
+
692
+ }
356
+ trace_npcm7xx_adc_write(DEVICE(s)->canonical_path, offset, v);
693
+
357
+ switch (offset) {
694
+ ARRAY_FIELD_DP32(s->regs, EFUSE_ISR, PGM_DONE, 1);
358
+ case A_NPCM7XX_ADC_CON:
695
+ efuse_imr_update_irq(s);
359
+ npcm7xx_adc_write_con(s, v);
696
+}
360
+ break;
697
+
361
+
698
+static void efuse_rd_addr_postw(RegisterInfo *reg, uint64_t val64)
362
+ case A_NPCM7XX_ADC_DATA:
699
+{
700
+ XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(reg->opaque);
701
+ unsigned bit = val64;
702
+ bool denied;
703
+
704
+ /* Always zero out RD_ADDR because it is write-only */
705
+ s->regs[R_EFUSE_RD_ADDR] = 0;
706
+
707
+ /*
708
+ * Indicate error if row is read-blocked.
709
+ *
710
+ * Note: model must NEVER clear the RD_ERROR bit; it is
711
+ * up to guest to do so (or by reset).
712
+ */
713
+ s->regs[R_EFUSE_RD_DATA] = xlnx_versal_efuse_read_row(s->efuse,
714
+ bit, &denied);
715
+ if (denied) {
716
+ qemu_log_mask(LOG_GUEST_ERROR,
363
+ qemu_log_mask(LOG_GUEST_ERROR,
717
+ "%s: Denied reading of efuse<%u, %u>\n",
364
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
718
+ object_get_canonical_path(OBJECT(s)),
365
+ __func__, offset);
719
+ FIELD_EX32(bit, EFUSE_RD_ADDR, PAGE),
366
+ break;
720
+ FIELD_EX32(bit, EFUSE_RD_ADDR, ROW));
367
+
721
+
368
+ default:
722
+ ARRAY_FIELD_DP32(s->regs, EFUSE_ISR, RD_ERROR, 1);
723
+ }
724
+
725
+ ARRAY_FIELD_DP32(s->regs, EFUSE_ISR, RD_DONE, 1);
726
+ efuse_imr_update_irq(s);
727
+ return;
728
+}
729
+
730
+static uint64_t efuse_cache_load_prew(RegisterInfo *reg, uint64_t val64)
731
+{
732
+ XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(reg->opaque);
733
+
734
+ if (val64 & R_EFUSE_CACHE_LOAD_LOAD_MASK) {
735
+ efuse_data_sync(s);
736
+
737
+ ARRAY_FIELD_DP32(s->regs, STATUS, CACHE_DONE, 1);
738
+ efuse_imr_update_irq(s);
739
+ }
740
+
741
+ return 0;
742
+}
743
+
744
+static uint64_t efuse_pgm_lock_prew(RegisterInfo *reg, uint64_t val64)
745
+{
746
+ XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(reg->opaque);
747
+
748
+ /* Ignore all other bits */
749
+ val64 = FIELD_EX32(val64, EFUSE_PGM_LOCK, SPK_ID_LOCK);
750
+
751
+ /* Once the bit is written 1, only reset will clear it to 0 */
752
+ val64 |= ARRAY_FIELD_EX32(s->regs, EFUSE_PGM_LOCK, SPK_ID_LOCK);
753
+
754
+ return val64;
755
+}
756
+
757
+static void efuse_aes_crc_postw(RegisterInfo *reg, uint64_t val64)
758
+{
759
+ efuse_key_crc_check(reg, val64,
760
+ R_STATUS_AES_CRC_PASS_MASK,
761
+ R_STATUS_AES_CRC_DONE_MASK,
762
+ EFUSE_AES_KEY_START,
763
+ EFUSE_AES_KEY_CRC_LK_MASK);
764
+}
765
+
766
+static void efuse_aes_u0_crc_postw(RegisterInfo *reg, uint64_t val64)
767
+{
768
+ efuse_key_crc_check(reg, val64,
769
+ R_STATUS_AES_USER_KEY_0_CRC_PASS_MASK,
770
+ R_STATUS_AES_USER_KEY_0_CRC_DONE_MASK,
771
+ EFUSE_USER_KEY_0_START,
772
+ EFUSE_USER_KEY_0_CRC_LK_MASK);
773
+}
774
+
775
+static void efuse_aes_u1_crc_postw(RegisterInfo *reg, uint64_t val64)
776
+{
777
+ efuse_key_crc_check(reg, val64,
778
+ R_STATUS_AES_USER_KEY_1_CRC_PASS_MASK,
779
+ R_STATUS_AES_USER_KEY_1_CRC_DONE_MASK,
780
+ EFUSE_USER_KEY_1_START,
781
+ EFUSE_USER_KEY_1_CRC_LK_MASK);
782
+}
783
+
784
+static uint64_t efuse_wr_lock_prew(RegisterInfo *reg, uint64_t val)
785
+{
786
+ return val != R_WR_LOCK_UNLOCK_PASSCODE;
787
+}
788
+
789
+static const RegisterAccessInfo efuse_ctrl_regs_info[] = {
790
+ { .name = "WR_LOCK", .addr = A_WR_LOCK,
791
+ .reset = 0x1,
792
+ .pre_write = efuse_wr_lock_prew,
793
+ },{ .name = "CFG", .addr = A_CFG,
794
+ .rsvd = 0x9,
795
+ },{ .name = "STATUS", .addr = A_STATUS,
796
+ .rsvd = 0x8,
797
+ .ro = 0xfff,
798
+ },{ .name = "EFUSE_PGM_ADDR", .addr = A_EFUSE_PGM_ADDR,
799
+ .post_write = efuse_pgm_addr_postw,
800
+ },{ .name = "EFUSE_RD_ADDR", .addr = A_EFUSE_RD_ADDR,
801
+ .rsvd = 0x1f,
802
+ .post_write = efuse_rd_addr_postw,
803
+ },{ .name = "EFUSE_RD_DATA", .addr = A_EFUSE_RD_DATA,
804
+ .ro = 0xffffffff,
805
+ },{ .name = "TPGM", .addr = A_TPGM,
806
+ },{ .name = "TRD", .addr = A_TRD,
807
+ .reset = 0x19,
808
+ },{ .name = "TSU_H_PS", .addr = A_TSU_H_PS,
809
+ .reset = 0xff,
810
+ },{ .name = "TSU_H_PS_CS", .addr = A_TSU_H_PS_CS,
811
+ .reset = 0x11,
812
+ },{ .name = "TRDM", .addr = A_TRDM,
813
+ .reset = 0x3a,
814
+ },{ .name = "TSU_H_CS", .addr = A_TSU_H_CS,
815
+ .reset = 0x16,
816
+ },{ .name = "EFUSE_ISR", .addr = A_EFUSE_ISR,
817
+ .rsvd = 0x7fff8000,
818
+ .w1c = 0x80007fff,
819
+ .post_write = efuse_isr_postw,
820
+ },{ .name = "EFUSE_IMR", .addr = A_EFUSE_IMR,
821
+ .reset = 0x80007fff,
822
+ .rsvd = 0x7fff8000,
823
+ .ro = 0xffffffff,
824
+ },{ .name = "EFUSE_IER", .addr = A_EFUSE_IER,
825
+ .rsvd = 0x7fff8000,
826
+ .pre_write = efuse_ier_prew,
827
+ },{ .name = "EFUSE_IDR", .addr = A_EFUSE_IDR,
828
+ .rsvd = 0x7fff8000,
829
+ .pre_write = efuse_idr_prew,
830
+ },{ .name = "EFUSE_CACHE_LOAD", .addr = A_EFUSE_CACHE_LOAD,
831
+ .pre_write = efuse_cache_load_prew,
832
+ },{ .name = "EFUSE_PGM_LOCK", .addr = A_EFUSE_PGM_LOCK,
833
+ .pre_write = efuse_pgm_lock_prew,
834
+ },{ .name = "EFUSE_AES_CRC", .addr = A_EFUSE_AES_CRC,
835
+ .post_write = efuse_aes_crc_postw,
836
+ },{ .name = "EFUSE_AES_USR_KEY0_CRC", .addr = A_EFUSE_AES_USR_KEY0_CRC,
837
+ .post_write = efuse_aes_u0_crc_postw,
838
+ },{ .name = "EFUSE_AES_USR_KEY1_CRC", .addr = A_EFUSE_AES_USR_KEY1_CRC,
839
+ .post_write = efuse_aes_u1_crc_postw,
840
+ },{ .name = "EFUSE_PD", .addr = A_EFUSE_PD,
841
+ .ro = 0xfffffffe,
842
+ },{ .name = "EFUSE_ANLG_OSC_SW_1LP", .addr = A_EFUSE_ANLG_OSC_SW_1LP,
843
+ },{ .name = "EFUSE_TEST_CTRL", .addr = A_EFUSE_TEST_CTRL,
844
+ .reset = 0x8,
845
+ }
846
+};
847
+
848
+static void efuse_ctrl_reg_write(void *opaque, hwaddr addr,
849
+ uint64_t data, unsigned size)
850
+{
851
+ RegisterInfoArray *reg_array = opaque;
852
+ XlnxVersalEFuseCtrl *s;
853
+ Object *dev;
854
+
855
+ assert(reg_array != NULL);
856
+
857
+ dev = reg_array->mem.owner;
858
+ assert(dev);
859
+
860
+ s = XLNX_VERSAL_EFUSE_CTRL(dev);
861
+
862
+ if (addr != A_WR_LOCK && s->regs[R_WR_LOCK]) {
863
+ qemu_log_mask(LOG_GUEST_ERROR,
369
+ qemu_log_mask(LOG_GUEST_ERROR,
864
+ "%s[reg_0x%02lx]: Attempt to write locked register.\n",
370
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
865
+ object_get_canonical_path(OBJECT(s)), (long)addr);
371
+ __func__, offset);
866
+ } else {
372
+ break;
867
+ register_write_memory(opaque, addr, data, size);
373
+ }
868
+ }
374
+
869
+}
375
+}
870
+
376
+
871
+static void efuse_ctrl_register_reset(RegisterInfo *reg)
377
+static const struct MemoryRegionOps npcm7xx_adc_ops = {
872
+{
378
+ .read = npcm7xx_adc_read,
873
+ if (!reg->data || !reg->access) {
379
+ .write = npcm7xx_adc_write,
874
+ return;
875
+ }
876
+
877
+ /* Reset must not trigger some registers' writers */
878
+ switch (reg->access->addr) {
879
+ case A_EFUSE_AES_CRC:
880
+ case A_EFUSE_AES_USR_KEY0_CRC:
881
+ case A_EFUSE_AES_USR_KEY1_CRC:
882
+ *(uint32_t *)reg->data = reg->access->reset;
883
+ return;
884
+ }
885
+
886
+ register_reset(reg);
887
+}
888
+
889
+static void efuse_ctrl_reset(DeviceState *dev)
890
+{
891
+ XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(dev);
892
+ unsigned int i;
893
+
894
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
895
+ efuse_ctrl_register_reset(&s->regs_info[i]);
896
+ }
897
+
898
+ efuse_anchor_bits_check(s);
899
+ efuse_data_sync(s);
900
+ efuse_imr_update_irq(s);
901
+}
902
+
903
+static const MemoryRegionOps efuse_ctrl_ops = {
904
+ .read = register_read_memory,
905
+ .write = efuse_ctrl_reg_write,
906
+ .endianness = DEVICE_LITTLE_ENDIAN,
380
+ .endianness = DEVICE_LITTLE_ENDIAN,
907
+ .valid = {
381
+ .valid = {
908
+ .min_access_size = 4,
382
+ .min_access_size = 4,
909
+ .max_access_size = 4,
383
+ .max_access_size = 4,
384
+ .unaligned = false,
910
+ },
385
+ },
911
+};
386
+};
912
+
387
+
913
+static void efuse_ctrl_realize(DeviceState *dev, Error **errp)
388
+static void npcm7xx_adc_enter_reset(Object *obj, ResetType type)
914
+{
389
+{
915
+ XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(dev);
390
+ NPCM7xxADCState *s = NPCM7XX_ADC(obj);
916
+ const uint32_t lks_sz = sizeof(XlnxEFuseLkSpec) / 2;
391
+
917
+
392
+ npcm7xx_adc_reset(s);
918
+ if (!s->efuse) {
393
+}
919
+ error_setg(errp, "%s.efuse: link property not connected to XLNX-EFUSE",
394
+
920
+ object_get_canonical_path(OBJECT(dev)));
395
+static void npcm7xx_adc_hold_reset(Object *obj)
921
+ return;
396
+{
922
+ }
397
+ NPCM7xxADCState *s = NPCM7XX_ADC(obj);
923
+
398
+
924
+ /* Sort property-defined pgm-locks for bsearch lookup */
399
+ qemu_irq_lower(s->irq);
925
+ if ((s->extra_pg0_lock_n16 % lks_sz) != 0) {
400
+}
926
+ error_setg(errp,
401
+
927
+ "%s.pg0-lock: array property item-count not multiple of %u",
402
+static void npcm7xx_adc_init(Object *obj)
928
+ object_get_canonical_path(OBJECT(dev)), lks_sz);
403
+{
929
+ return;
404
+ NPCM7xxADCState *s = NPCM7XX_ADC(obj);
930
+ }
931
+
932
+ efuse_lk_spec_sort(s);
933
+}
934
+
935
+static void efuse_ctrl_init(Object *obj)
936
+{
937
+ XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(obj);
938
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
405
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
939
+ RegisterInfoArray *reg_array;
406
+ int i;
940
+
407
+
941
+ reg_array =
408
+ sysbus_init_irq(sbd, &s->irq);
942
+ register_init_block32(DEVICE(obj), efuse_ctrl_regs_info,
409
+
943
+ ARRAY_SIZE(efuse_ctrl_regs_info),
410
+ timer_init_ns(&s->conv_timer, QEMU_CLOCK_VIRTUAL,
944
+ s->regs_info, s->regs,
411
+ npcm7xx_adc_convert_done, s);
945
+ &efuse_ctrl_ops,
412
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_adc_ops, s,
946
+ XLNX_VERSAL_EFUSE_CTRL_ERR_DEBUG,
413
+ TYPE_NPCM7XX_ADC, 4 * KiB);
947
+ R_MAX * 4);
414
+ sysbus_init_mmio(sbd, &s->iomem);
948
+
415
+ s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL);
949
+ sysbus_init_mmio(sbd, &reg_array->mem);
416
+
950
+ sysbus_init_irq(sbd, &s->irq_efuse_imr);
417
+ for (i = 0; i < NPCM7XX_ADC_NUM_INPUTS; ++i) {
951
+}
418
+ object_property_add_uint32_ptr(obj, "adci[*]",
952
+
419
+ &s->adci[i], OBJ_PROP_FLAG_WRITE);
953
+static const VMStateDescription vmstate_efuse_ctrl = {
420
+ }
954
+ .name = TYPE_XLNX_VERSAL_EFUSE_CTRL,
421
+ object_property_add_uint32_ptr(obj, "vref",
955
+ .version_id = 1,
422
+ &s->vref, OBJ_PROP_FLAG_WRITE);
956
+ .minimum_version_id = 1,
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,
957
+ .fields = (VMStateField[]) {
430
+ .fields = (VMStateField[]) {
958
+ VMSTATE_UINT32_ARRAY(regs, XlnxVersalEFuseCtrl, R_MAX),
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),
959
+ VMSTATE_END_OF_LIST(),
440
+ VMSTATE_END_OF_LIST(),
960
+ }
441
+ },
961
+};
442
+};
962
+
443
+
963
+static Property efuse_ctrl_props[] = {
444
+static Property npcm7xx_timer_properties[] = {
964
+ DEFINE_PROP_LINK("efuse",
445
+ DEFINE_PROP_UINT32("iref", NPCM7xxADCState, iref, NPCM7XX_ADC_DEFAULT_IREF),
965
+ XlnxVersalEFuseCtrl, efuse,
966
+ TYPE_XLNX_EFUSE, XlnxEFuse *),
967
+ DEFINE_PROP_ARRAY("pg0-lock",
968
+ XlnxVersalEFuseCtrl, extra_pg0_lock_n16,
969
+ extra_pg0_lock_spec, qdev_prop_uint16, uint16_t),
970
+
971
+ DEFINE_PROP_END_OF_LIST(),
446
+ DEFINE_PROP_END_OF_LIST(),
972
+};
447
+};
973
+
448
+
974
+static void efuse_ctrl_class_init(ObjectClass *klass, void *data)
449
+static void npcm7xx_adc_class_init(ObjectClass *klass, void *data)
975
+{
450
+{
451
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
976
+ DeviceClass *dc = DEVICE_CLASS(klass);
452
+ DeviceClass *dc = DEVICE_CLASS(klass);
977
+
453
+
978
+ dc->reset = efuse_ctrl_reset;
454
+ dc->desc = "NPCM7xx ADC Module";
979
+ dc->realize = efuse_ctrl_realize;
455
+ dc->vmsd = &vmstate_npcm7xx_adc;
980
+ dc->vmsd = &vmstate_efuse_ctrl;
456
+ rc->phases.enter = npcm7xx_adc_enter_reset;
981
+ device_class_set_props(dc, efuse_ctrl_props);
457
+ rc->phases.hold = npcm7xx_adc_hold_reset;
982
+}
458
+
983
+
459
+ device_class_set_props(dc, npcm7xx_timer_properties);
984
+static const TypeInfo efuse_ctrl_info = {
460
+}
985
+ .name = TYPE_XLNX_VERSAL_EFUSE_CTRL,
461
+
986
+ .parent = TYPE_SYS_BUS_DEVICE,
462
+static const TypeInfo npcm7xx_adc_info = {
987
+ .instance_size = sizeof(XlnxVersalEFuseCtrl),
463
+ .name = TYPE_NPCM7XX_ADC,
988
+ .class_init = efuse_ctrl_class_init,
464
+ .parent = TYPE_SYS_BUS_DEVICE,
989
+ .instance_init = efuse_ctrl_init,
465
+ .instance_size = sizeof(NPCM7xxADCState),
466
+ .class_init = npcm7xx_adc_class_init,
467
+ .instance_init = npcm7xx_adc_init,
990
+};
468
+};
991
+
469
+
992
+static void efuse_ctrl_register_types(void)
470
+static void npcm7xx_adc_register_types(void)
993
+{
471
+{
994
+ type_register_static(&efuse_ctrl_info);
472
+ type_register_static(&npcm7xx_adc_info);
995
+}
473
+}
996
+
474
+
997
+type_init(efuse_ctrl_register_types)
475
+type_init(npcm7xx_adc_register_types);
998
+
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 @@
999
+/*
559
+/*
1000
+ * Retrieve a row, with unreadable bits returned as 0.
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.
1001
+ */
573
+ */
1002
+uint32_t xlnx_versal_efuse_read_row(XlnxEFuse *efuse,
574
+
1003
+ uint32_t bit, bool *denied)
575
+#include "qemu/osdep.h"
1004
+{
576
+#include "qemu/bitops.h"
1005
+ bool dummy;
577
+#include "qemu/timer.h"
1006
+
578
+#include "libqos/libqtest.h"
1007
+ if (!denied) {
579
+#include "qapi/qmp/qdict.h"
1008
+ denied = &dummy;
580
+
1009
+ }
581
+#define REF_HZ (25000000)
1010
+
582
+
1011
+ if (bit >= EFUSE_RD_BLOCKED_START && bit <= EFUSE_RD_BLOCKED_END) {
583
+#define CON_OFFSET 0x0
1012
+ *denied = true;
584
+#define DATA_OFFSET 0x4
1013
+ return 0;
585
+
1014
+ }
586
+#define NUM_INPUTS 8
1015
+
587
+#define DEFAULT_IREF 2000000
1016
+ *denied = false;
588
+#define CONV_CYCLES 20
1017
+ return xlnx_efuse_get_row(efuse, bit);
589
+#define RESET_CYCLES 10
1018
+}
590
+#define R0_INPUT 500000
1019
diff --git a/hw/nvram/Kconfig b/hw/nvram/Kconfig
591
+#define R1_INPUT 1500000
592
+#define MAX_RESULT 1023
593
+
594
+#define DEFAULT_CLKDIV 5
595
+
596
+#define FUSE_ARRAY_BA 0xf018a000
597
+#define FCTL_OFFSET 0x14
598
+#define FST_OFFSET 0x0
599
+#define FADDR_OFFSET 0x4
600
+#define FDATA_OFFSET 0x8
601
+#define ADC_CALIB_ADDR 24
602
+#define FUSE_READ 0x2
603
+
604
+/* Register field definitions. */
605
+#define CON_MUX(rv) ((rv) << 24)
606
+#define CON_INT_EN BIT(21)
607
+#define CON_REFSEL BIT(19)
608
+#define CON_INT BIT(18)
609
+#define CON_EN BIT(17)
610
+#define CON_RST BIT(16)
611
+#define CON_CONV BIT(14)
612
+#define CON_DIV(rv) extract32(rv, 1, 8)
613
+
614
+#define FST_RDST BIT(1)
615
+#define FDATA_MASK 0xff
616
+
617
+#define MAX_ERROR 10000
618
+#define MIN_CALIB_INPUT 100000
619
+#define MAX_CALIB_INPUT 1800000
620
+
621
+static const uint32_t input_list[] = {
622
+ 100000,
623
+ 500000,
624
+ 1000000,
625
+ 1500000,
626
+ 1800000,
627
+ 2000000,
628
+};
629
+
630
+static const uint32_t vref_list[] = {
631
+ 2000000,
632
+ 2200000,
633
+ 2500000,
634
+};
635
+
636
+static const uint32_t iref_list[] = {
637
+ 1800000,
638
+ 1900000,
639
+ 2000000,
640
+ 2100000,
641
+ 2200000,
642
+};
643
+
644
+static const uint32_t div_list[] = {0, 1, 3, 7, 15};
645
+
646
+typedef struct ADC {
647
+ int irq;
648
+ uint64_t base_addr;
649
+} ADC;
650
+
651
+ADC adc = {
652
+ .irq = 0,
653
+ .base_addr = 0xf000c000
654
+};
655
+
656
+static uint32_t adc_read_con(QTestState *qts, const ADC *adc)
657
+{
658
+ return qtest_readl(qts, adc->base_addr + CON_OFFSET);
659
+}
660
+
661
+static void adc_write_con(QTestState *qts, const ADC *adc, uint32_t value)
662
+{
663
+ qtest_writel(qts, adc->base_addr + CON_OFFSET, value);
664
+}
665
+
666
+static uint32_t adc_read_data(QTestState *qts, const ADC *adc)
667
+{
668
+ return qtest_readl(qts, adc->base_addr + DATA_OFFSET);
669
+}
670
+
671
+static uint32_t adc_calibrate(uint32_t measured, uint32_t *rv)
672
+{
673
+ return R0_INPUT + (R1_INPUT - R0_INPUT) * (int32_t)(measured - rv[0])
674
+ / (int32_t)(rv[1] - rv[0]);
675
+}
676
+
677
+static void adc_qom_set(QTestState *qts, const ADC *adc,
678
+ const char *name, uint32_t value)
679
+{
680
+ QDict *response;
681
+ const char *path = "/machine/soc/adc";
682
+
683
+ g_test_message("Setting properties %s of %s with value %u",
684
+ name, path, value);
685
+ response = qtest_qmp(qts, "{ 'execute': 'qom-set',"
686
+ " 'arguments': { 'path': %s, 'property': %s, 'value': %u}}",
687
+ path, name, value);
688
+ /* The qom set message returns successfully. */
689
+ g_assert_true(qdict_haskey(response, "return"));
690
+}
691
+
692
+static void adc_write_input(QTestState *qts, const ADC *adc,
693
+ uint32_t index, uint32_t value)
694
+{
695
+ char name[100];
696
+
697
+ sprintf(name, "adci[%u]", index);
698
+ adc_qom_set(qts, adc, name, value);
699
+}
700
+
701
+static void adc_write_vref(QTestState *qts, const ADC *adc, uint32_t value)
702
+{
703
+ adc_qom_set(qts, adc, "vref", value);
704
+}
705
+
706
+static uint32_t adc_calculate_output(uint32_t input, uint32_t ref)
707
+{
708
+ uint32_t output;
709
+
710
+ g_assert_cmpuint(input, <=, ref);
711
+ output = (input * (MAX_RESULT + 1)) / ref;
712
+ if (output > MAX_RESULT) {
713
+ output = MAX_RESULT;
714
+ }
715
+
716
+ return output;
717
+}
718
+
719
+static uint32_t adc_prescaler(QTestState *qts, const ADC *adc)
720
+{
721
+ uint32_t div = extract32(adc_read_con(qts, adc), 1, 8);
722
+
723
+ return 2 * (div + 1);
724
+}
725
+
726
+static int64_t adc_calculate_steps(uint32_t cycles, uint32_t prescale,
727
+ uint32_t clkdiv)
728
+{
729
+ return (NANOSECONDS_PER_SECOND / (REF_HZ >> clkdiv)) * cycles * prescale;
730
+}
731
+
732
+static void adc_wait_conv_finished(QTestState *qts, const ADC *adc,
733
+ uint32_t clkdiv)
734
+{
735
+ uint32_t prescaler = adc_prescaler(qts, adc);
736
+
737
+ /*
738
+ * ADC should takes roughly 20 cycles to convert one sample. So we assert it
739
+ * should take 10~30 cycles here.
740
+ */
741
+ qtest_clock_step(qts, adc_calculate_steps(CONV_CYCLES / 2, prescaler,
742
+ clkdiv));
743
+ /* ADC is still converting. */
744
+ g_assert_true(adc_read_con(qts, adc) & CON_CONV);
745
+ qtest_clock_step(qts, adc_calculate_steps(CONV_CYCLES, prescaler, clkdiv));
746
+ /* ADC has finished conversion. */
747
+ g_assert_false(adc_read_con(qts, adc) & CON_CONV);
748
+}
749
+
750
+/* Check ADC can be reset to default value. */
751
+static void test_init(gconstpointer adc_p)
752
+{
753
+ const ADC *adc = adc_p;
754
+
755
+ QTestState *qts = qtest_init("-machine quanta-gsj");
756
+ adc_write_con(qts, adc, CON_REFSEL | CON_INT);
757
+ g_assert_cmphex(adc_read_con(qts, adc), ==, CON_REFSEL);
758
+ qtest_quit(qts);
759
+}
760
+
761
+/* Check ADC can convert from an internal reference. */
762
+static void test_convert_internal(gconstpointer adc_p)
763
+{
764
+ const ADC *adc = adc_p;
765
+ uint32_t index, input, output, expected_output;
766
+ QTestState *qts = qtest_init("-machine quanta-gsj");
767
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
768
+
769
+ for (index = 0; index < NUM_INPUTS; ++index) {
770
+ for (size_t i = 0; i < ARRAY_SIZE(input_list); ++i) {
771
+ input = input_list[i];
772
+ expected_output = adc_calculate_output(input, DEFAULT_IREF);
773
+
774
+ adc_write_input(qts, adc, index, input);
775
+ adc_write_con(qts, adc, CON_MUX(index) | CON_REFSEL | CON_INT |
776
+ CON_EN | CON_CONV);
777
+ adc_wait_conv_finished(qts, adc, DEFAULT_CLKDIV);
778
+ g_assert_cmphex(adc_read_con(qts, adc), ==, CON_MUX(index) |
779
+ CON_REFSEL | CON_EN);
780
+ g_assert_false(qtest_get_irq(qts, adc->irq));
781
+ output = adc_read_data(qts, adc);
782
+ g_assert_cmpuint(output, ==, expected_output);
783
+ }
784
+ }
785
+
786
+ qtest_quit(qts);
787
+}
788
+
789
+/* Check ADC can convert from an external reference. */
790
+static void test_convert_external(gconstpointer adc_p)
791
+{
792
+ const ADC *adc = adc_p;
793
+ uint32_t index, input, vref, output, expected_output;
794
+ QTestState *qts = qtest_init("-machine quanta-gsj");
795
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
796
+
797
+ for (index = 0; index < NUM_INPUTS; ++index) {
798
+ for (size_t i = 0; i < ARRAY_SIZE(input_list); ++i) {
799
+ for (size_t j = 0; j < ARRAY_SIZE(vref_list); ++j) {
800
+ input = input_list[i];
801
+ vref = vref_list[j];
802
+ expected_output = adc_calculate_output(input, vref);
803
+
804
+ adc_write_input(qts, adc, index, input);
805
+ adc_write_vref(qts, adc, vref);
806
+ adc_write_con(qts, adc, CON_MUX(index) | CON_INT | CON_EN |
807
+ CON_CONV);
808
+ adc_wait_conv_finished(qts, adc, DEFAULT_CLKDIV);
809
+ g_assert_cmphex(adc_read_con(qts, adc), ==,
810
+ CON_MUX(index) | CON_EN);
811
+ g_assert_false(qtest_get_irq(qts, adc->irq));
812
+ output = adc_read_data(qts, adc);
813
+ g_assert_cmpuint(output, ==, expected_output);
814
+ }
815
+ }
816
+ }
817
+
818
+ qtest_quit(qts);
819
+}
820
+
821
+/* Check ADC interrupt files if and only if CON_INT_EN is set. */
822
+static void test_interrupt(gconstpointer adc_p)
823
+{
824
+ const ADC *adc = adc_p;
825
+ uint32_t index, input, output, expected_output;
826
+ QTestState *qts = qtest_init("-machine quanta-gsj");
827
+
828
+ index = 1;
829
+ input = input_list[1];
830
+ expected_output = adc_calculate_output(input, DEFAULT_IREF);
831
+
832
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
833
+ adc_write_input(qts, adc, index, input);
834
+ g_assert_false(qtest_get_irq(qts, adc->irq));
835
+ adc_write_con(qts, adc, CON_MUX(index) | CON_INT_EN | CON_REFSEL | CON_INT
836
+ | CON_EN | CON_CONV);
837
+ adc_wait_conv_finished(qts, adc, DEFAULT_CLKDIV);
838
+ g_assert_cmphex(adc_read_con(qts, adc), ==, CON_MUX(index) | CON_INT_EN
839
+ | CON_REFSEL | CON_INT | CON_EN);
840
+ g_assert_true(qtest_get_irq(qts, adc->irq));
841
+ output = adc_read_data(qts, adc);
842
+ g_assert_cmpuint(output, ==, expected_output);
843
+
844
+ qtest_quit(qts);
845
+}
846
+
847
+/* Check ADC is reset after setting ADC_RST for 10 ADC cycles. */
848
+static void test_reset(gconstpointer adc_p)
849
+{
850
+ const ADC *adc = adc_p;
851
+ QTestState *qts = qtest_init("-machine quanta-gsj");
852
+
853
+ for (size_t i = 0; i < ARRAY_SIZE(div_list); ++i) {
854
+ uint32_t div = div_list[i];
855
+
856
+ adc_write_con(qts, adc, CON_INT | CON_EN | CON_RST | CON_DIV(div));
857
+ qtest_clock_step(qts, adc_calculate_steps(RESET_CYCLES,
858
+ adc_prescaler(qts, adc), DEFAULT_CLKDIV));
859
+ g_assert_false(adc_read_con(qts, adc) & CON_EN);
860
+ }
861
+ qtest_quit(qts);
862
+}
863
+
864
+/* Check ADC Calibration works as desired. */
865
+static void test_calibrate(gconstpointer adc_p)
866
+{
867
+ int i, j;
868
+ const ADC *adc = adc_p;
869
+
870
+ for (j = 0; j < ARRAY_SIZE(iref_list); ++j) {
871
+ uint32_t iref = iref_list[j];
872
+ uint32_t expected_rv[] = {
873
+ adc_calculate_output(R0_INPUT, iref),
874
+ adc_calculate_output(R1_INPUT, iref),
875
+ };
876
+ char buf[100];
877
+ QTestState *qts;
878
+
879
+ sprintf(buf, "-machine quanta-gsj -global npcm7xx-adc.iref=%u", iref);
880
+ qts = qtest_init(buf);
881
+
882
+ /* Check the converted value is correct using the calibration value. */
883
+ for (i = 0; i < ARRAY_SIZE(input_list); ++i) {
884
+ uint32_t input;
885
+ uint32_t output;
886
+ uint32_t expected_output;
887
+ uint32_t calibrated_voltage;
888
+ uint32_t index = 0;
889
+
890
+ input = input_list[i];
891
+ /* Calibration only works for input range 0.1V ~ 1.8V. */
892
+ if (input < MIN_CALIB_INPUT || input > MAX_CALIB_INPUT) {
893
+ continue;
894
+ }
895
+ expected_output = adc_calculate_output(input, iref);
896
+
897
+ adc_write_input(qts, adc, index, input);
898
+ adc_write_con(qts, adc, CON_MUX(index) | CON_REFSEL | CON_INT |
899
+ CON_EN | CON_CONV);
900
+ adc_wait_conv_finished(qts, adc, DEFAULT_CLKDIV);
901
+ g_assert_cmphex(adc_read_con(qts, adc), ==,
902
+ CON_REFSEL | CON_MUX(index) | CON_EN);
903
+ output = adc_read_data(qts, adc);
904
+ g_assert_cmpuint(output, ==, expected_output);
905
+
906
+ calibrated_voltage = adc_calibrate(output, expected_rv);
907
+ g_assert_cmpuint(calibrated_voltage, >, input - MAX_ERROR);
908
+ g_assert_cmpuint(calibrated_voltage, <, input + MAX_ERROR);
909
+ }
910
+
911
+ qtest_quit(qts);
912
+ }
913
+}
914
+
915
+static void adc_add_test(const char *name, const ADC* wd,
916
+ GTestDataFunc fn)
917
+{
918
+ g_autofree char *full_name = g_strdup_printf("npcm7xx_adc/%s", name);
919
+ qtest_add_data_func(full_name, wd, fn);
920
+}
921
+#define add_test(name, td) adc_add_test(#name, td, test_##name)
922
+
923
+int main(int argc, char **argv)
924
+{
925
+ g_test_init(&argc, &argv, NULL);
926
+
927
+ add_test(init, &adc);
928
+ add_test(convert_internal, &adc);
929
+ add_test(convert_external, &adc);
930
+ add_test(interrupt, &adc);
931
+ add_test(reset, &adc);
932
+ add_test(calibrate, &adc);
933
+
934
+ return g_test_run();
935
+}
936
diff --git a/hw/adc/meson.build b/hw/adc/meson.build
1020
index XXXXXXX..XXXXXXX 100644
937
index XXXXXXX..XXXXXXX 100644
1021
--- a/hw/nvram/Kconfig
938
--- a/hw/adc/meson.build
1022
+++ b/hw/nvram/Kconfig
939
+++ b/hw/adc/meson.build
1023
@@ -XXX,XX +XXX,XX @@ config XLNX_EFUSE_CRC
940
@@ -1 +1,2 @@
1024
config XLNX_EFUSE
941
softmmu_ss.add(when: 'CONFIG_STM32F2XX_ADC', if_true: files('stm32f2xx_adc.c'))
1025
bool
942
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_adc.c'))
1026
select XLNX_EFUSE_CRC
943
diff --git a/hw/adc/trace-events b/hw/adc/trace-events
1027
+
944
new file mode 100644
1028
+config XLNX_EFUSE_VERSAL
945
index XXXXXXX..XXXXXXX
1029
+ bool
946
--- /dev/null
1030
+ select XLNX_EFUSE
947
+++ b/hw/adc/trace-events
1031
diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build
948
@@ -XXX,XX +XXX,XX @@
949
+# See docs/devel/tracing.txt for syntax documentation.
950
+
951
+# npcm7xx_adc.c
952
+npcm7xx_adc_read(const char *id, uint64_t offset, uint32_t value) " %s offset: 0x%04" PRIx64 " value 0x%04" PRIx32
953
+npcm7xx_adc_write(const char *id, uint64_t offset, uint32_t value) "%s offset: 0x%04" PRIx64 " value 0x%04" PRIx32
954
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
1032
index XXXXXXX..XXXXXXX 100644
955
index XXXXXXX..XXXXXXX 100644
1033
--- a/hw/nvram/meson.build
956
--- a/tests/qtest/meson.build
1034
+++ b/hw/nvram/meson.build
957
+++ b/tests/qtest/meson.build
1035
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_otp.c'))
958
@@ -XXX,XX +XXX,XX @@ qtests_sparc64 = \
1036
softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_nvm.c'))
959
['prom-env-test', 'boot-serial-test']
1037
softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_CRC', if_true: files('xlnx-efuse-crc.c'))
960
1038
softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE', if_true: files('xlnx-efuse.c'))
961
qtests_npcm7xx = \
1039
+softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_VERSAL', if_true: files(
962
- ['npcm7xx_gpio-test',
1040
+ 'xlnx-versal-efuse-cache.c',
963
+ ['npcm7xx_adc-test',
1041
+ 'xlnx-versal-efuse-ctrl.c'))
964
+ 'npcm7xx_gpio-test',
1042
965
'npcm7xx_rng-test',
1043
specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_nvram.c'))
966
'npcm7xx_timer-test',
967
'npcm7xx_watchdog_timer-test']
1044
--
968
--
1045
2.20.1
969
2.20.1
1046
970
1047
971
diff view generated by jsdifflib
1
From: Tong Ho <tong.ho@xilinx.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
This introduces the QOM for Xilinx eFuse, an one-time
3
The PWM module is part of NPCM7XX module. Each NPCM7XX module has two
4
field-programmable storage bit array.
4
identical PWM modules. Each module contains 4 PWM entries. Each PWM has
5
two outputs: frequency and duty_cycle. Both are computed using inputs
6
from software side.
5
7
6
The actual mmio interface to the array varies by device
8
This module does not model detail pulse signals since it is expensive.
7
families and will be provided in different change-sets.
9
It also does not model interrupts and watchdogs that are dependant on
10
the detail models. The interfaces for these are left in the module so
11
that anyone in need for these functionalities can implement on their
12
own.
8
13
9
Co-authored-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
14
The user can read the duty cycle and frequency using qom-get command.
10
Co-authored-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
11
15
12
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
16
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
13
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
17
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
14
Signed-off-by: Tong Ho <tong.ho@xilinx.com>
18
Signed-off-by: Hao Wu <wuhaotsh@google.com>
15
Message-id: 20210917052400.1249094-2-tong.ho@xilinx.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/nvram/xlnx-efuse.h | 132 ++++++++++++++++
23
docs/system/arm/nuvoton.rst | 2 +-
20
hw/nvram/xlnx-efuse-crc.c | 119 +++++++++++++++
24
include/hw/arm/npcm7xx.h | 2 +
21
hw/nvram/xlnx-efuse.c | 280 ++++++++++++++++++++++++++++++++++
25
include/hw/misc/npcm7xx_pwm.h | 105 +++++++
22
hw/nvram/Kconfig | 7 +
26
hw/arm/npcm7xx.c | 26 +-
23
hw/nvram/meson.build | 2 +
27
hw/misc/npcm7xx_pwm.c | 550 ++++++++++++++++++++++++++++++++++
24
5 files changed, 540 insertions(+)
28
hw/misc/meson.build | 1 +
25
create mode 100644 include/hw/nvram/xlnx-efuse.h
29
hw/misc/trace-events | 6 +
26
create mode 100644 hw/nvram/xlnx-efuse-crc.c
30
7 files changed, 689 insertions(+), 3 deletions(-)
27
create mode 100644 hw/nvram/xlnx-efuse.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/nvram/xlnx-efuse.h b/include/hw/nvram/xlnx-efuse.h
34
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
35
index XXXXXXX..XXXXXXX 100644
36
--- a/docs/system/arm/nuvoton.rst
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
58
@@ -XXX,XX +XXX,XX @@
59
#include "hw/mem/npcm7xx_mc.h"
60
#include "hw/misc/npcm7xx_clk.h"
61
#include "hw/misc/npcm7xx_gcr.h"
62
+#include "hw/misc/npcm7xx_pwm.h"
63
#include "hw/misc/npcm7xx_rng.h"
64
#include "hw/nvram/npcm7xx_otp.h"
65
#include "hw/timer/npcm7xx_timer.h"
66
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
67
NPCM7xxCLKState clk;
68
NPCM7xxTimerCtrlState tim[3];
69
NPCM7xxADCState adc;
70
+ NPCM7xxPWMState pwm[2];
71
NPCM7xxOTPState key_storage;
72
NPCM7xxOTPState fuse_array;
73
NPCM7xxMCState mc;
74
diff --git a/include/hw/misc/npcm7xx_pwm.h b/include/hw/misc/npcm7xx_pwm.h
30
new file mode 100644
75
new file mode 100644
31
index XXXXXXX..XXXXXXX
76
index XXXXXXX..XXXXXXX
32
--- /dev/null
77
--- /dev/null
33
+++ b/include/hw/nvram/xlnx-efuse.h
78
+++ b/include/hw/misc/npcm7xx_pwm.h
34
@@ -XXX,XX +XXX,XX @@
79
@@ -XXX,XX +XXX,XX @@
35
+/*
80
+/*
36
+ * QEMU model of the Xilinx eFuse core
81
+ * Nuvoton NPCM7xx PWM Module
37
+ *
82
+ *
38
+ * Copyright (c) 2015 Xilinx Inc.
83
+ * Copyright 2020 Google LLC
39
+ *
84
+ *
40
+ * Written by Edgar E. Iglesias <edgari@xilinx.com>
85
+ * This program is free software; you can redistribute it and/or modify it
86
+ * under the terms of the GNU General Public License as published by the
87
+ * Free Software Foundation; either version 2 of the License, or
88
+ * (at your option) any later version.
41
+ *
89
+ *
42
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
90
+ * This program is distributed in the hope that it will be useful, but WITHOUT
43
+ * of this software and associated documentation files (the "Software"), to deal
91
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
44
+ * in the Software without restriction, including without limitation the rights
92
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
45
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
93
+ * for more details.
46
+ * copies of the Software, and to permit persons to whom the Software is
47
+ * furnished to do so, subject to the following conditions:
48
+ *
49
+ * The above copyright notice and this permission notice shall be included in
50
+ * all copies or substantial portions of the Software.
51
+ *
52
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
53
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
54
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
55
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
56
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
57
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
58
+ * THE SOFTWARE.
59
+ */
94
+ */
60
+
95
+#ifndef NPCM7XX_PWM_H
61
+#ifndef XLNX_EFUSE_H
96
+#define NPCM7XX_PWM_H
62
+#define XLNX_EFUSE_H
97
+
63
+
98
+#include "hw/clock.h"
64
+#include "sysemu/block-backend.h"
99
+#include "hw/sysbus.h"
65
+#include "hw/qdev-core.h"
100
+#include "hw/irq.h"
66
+
101
+
67
+#define TYPE_XLNX_EFUSE "xlnx,efuse"
102
+/* Each PWM module holds 4 PWM channels. */
68
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxEFuse, XLNX_EFUSE);
103
+#define NPCM7XX_PWM_PER_MODULE 4
69
+
104
+
70
+struct XlnxEFuse {
105
+/*
71
+ DeviceState parent_obj;
106
+ * Number of registers in one pwm module. Don't change this without increasing
72
+ BlockBackend *blk;
107
+ * the version_id in vmstate.
73
+ bool blk_ro;
108
+ */
74
+ uint32_t *fuse32;
109
+#define NPCM7XX_PWM_NR_REGS (0x54 / sizeof(uint32_t))
75
+
110
+
76
+ DeviceState *dev;
111
+/*
77
+
112
+ * The maximum duty values. Each duty unit represents 1/NPCM7XX_PWM_MAX_DUTY
78
+ bool init_tbits;
113
+ * cycles. For example, if NPCM7XX_PWM_MAX_DUTY=1,000,000 and a PWM has a duty
79
+
114
+ * value of 100,000 the duty cycle for that PWM is 10%.
80
+ uint8_t efuse_nr;
115
+ */
81
+ uint32_t efuse_size;
116
+#define NPCM7XX_PWM_MAX_DUTY 1000000
82
+
117
+
83
+ uint32_t *ro_bits;
118
+typedef struct NPCM7xxPWMState NPCM7xxPWMState;
84
+ uint32_t ro_bits_cnt;
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;
85
+};
178
+};
86
+
179
+
87
+/**
180
+#define TYPE_NPCM7XX_PWM "npcm7xx-pwm"
88
+ * xlnx_efuse_calc_crc:
181
+#define NPCM7XX_PWM(obj) \
89
+ * @data: an array of 32-bit words for which the CRC should be computed
182
+ OBJECT_CHECK(NPCM7xxPWMState, (obj), TYPE_NPCM7XX_PWM)
90
+ * @u32_cnt: the array size in number of 32-bit words
183
+
91
+ * @zpads: the number of 32-bit zeros prepended to @data before computation
184
+#endif /* NPCM7XX_PWM_H */
92
+ *
185
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
93
+ * This function is used to compute the CRC for an array of 32-bit words,
186
index XXXXXXX..XXXXXXX 100644
94
+ * using a Xilinx-specific data padding.
187
--- a/hw/arm/npcm7xx.c
95
+ *
188
+++ b/hw/arm/npcm7xx.c
96
+ * Returns: the computed 32-bit CRC
189
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
97
+ */
190
NPCM7XX_WDG2_IRQ, /* Timer Module 2 Watchdog */
98
+uint32_t xlnx_efuse_calc_crc(const uint32_t *data, unsigned u32_cnt,
191
NPCM7XX_EHCI_IRQ = 61,
99
+ unsigned zpads);
192
NPCM7XX_OHCI_IRQ = 62,
100
+
193
+ NPCM7XX_PWM0_IRQ = 93, /* PWM module 0 */
101
+/**
194
+ NPCM7XX_PWM1_IRQ, /* PWM module 1 */
102
+ * xlnx_efuse_get_bit:
195
NPCM7XX_GPIO0_IRQ = 116,
103
+ * @s: the efuse object
196
NPCM7XX_GPIO1_IRQ,
104
+ * @bit: the efuse bit-address to read the data
197
NPCM7XX_GPIO2_IRQ,
105
+ *
198
@@ -XXX,XX +XXX,XX @@ static const hwaddr npcm7xx_fiu3_flash_addr[] = {
106
+ * Returns: the bit, 0 or 1, at @bit of object @s
199
0xb8000000, /* CS3 */
107
+ */
200
};
108
+bool xlnx_efuse_get_bit(XlnxEFuse *s, unsigned int bit);
201
109
+
202
+/* Register base address for each PWM Module */
110
+/**
203
+static const hwaddr npcm7xx_pwm_addr[] = {
111
+ * xlnx_efuse_set_bit:
204
+ 0xf0103000,
112
+ * @s: the efuse object
205
+ 0xf0104000,
113
+ * @bit: the efuse bit-address to be written a value of 1
206
+};
114
+ *
207
+
115
+ * Returns: true on success, false on failure
208
static const struct {
116
+ */
209
hwaddr regs_addr;
117
+bool xlnx_efuse_set_bit(XlnxEFuse *s, unsigned int bit);
210
uint32_t unconnected_pins;
118
+
211
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
119
+/**
212
object_initialize_child(obj, npcm7xx_fiu[i].name, &s->fiu[i],
120
+ * xlnx_efuse_k256_check:
213
TYPE_NPCM7XX_FIU);
121
+ * @s: the efuse object
214
}
122
+ * @crc: the 32-bit CRC to be compared with
215
+
123
+ * @start: the efuse bit-address (which must be multiple of 32) of the
216
+ for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
124
+ * start of a 256-bit array
217
+ object_initialize_child(obj, "pwm[*]", &s->pwm[i], TYPE_NPCM7XX_PWM);
125
+ *
218
+ }
126
+ * This function computes the CRC of a 256-bit array starting at @start
219
}
127
+ * then compares to the given @crc
220
128
+ *
221
static void npcm7xx_realize(DeviceState *dev, Error **errp)
129
+ * Returns: true of @crc == computed, false otherwise
222
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
130
+ */
223
sysbus_connect_irq(SYS_BUS_DEVICE(&s->ohci), 0,
131
+bool xlnx_efuse_k256_check(XlnxEFuse *s, uint32_t crc, unsigned start);
224
npcm7xx_irq(s, NPCM7XX_OHCI_IRQ));
132
+
225
133
+/**
226
+ /* PWM Modules. Cannot fail. */
134
+ * xlnx_efuse_tbits_check:
227
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_pwm_addr) != ARRAY_SIZE(s->pwm));
135
+ * @s: the efuse object
228
+ for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
136
+ *
229
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->pwm[i]);
137
+ * This function inspects a number of efuse bits at specific addresses
230
+
138
+ * to see if they match a validation pattern. Each pattern is a group
231
+ qdev_connect_clock_in(DEVICE(&s->pwm[i]), "clock", qdev_get_clock_out(
139
+ * of 4 bits, and there are 3 groups.
232
+ DEVICE(&s->clk), "apb3-clock"));
140
+ *
233
+ sysbus_realize(sbd, &error_abort);
141
+ * Returns: a 3-bit mask, where a bit of '1' means the corresponding
234
+ sysbus_mmio_map(sbd, 0, npcm7xx_pwm_addr[i]);
142
+ * group has a valid pattern.
235
+ sysbus_connect_irq(sbd, i, npcm7xx_irq(s, NPCM7XX_PWM0_IRQ + i));
143
+ */
236
+ }
144
+uint32_t xlnx_efuse_tbits_check(XlnxEFuse *s);
237
+
145
+
238
/*
146
+/**
239
* Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
147
+ * xlnx_efuse_get_row:
240
* specified, but this is a programming error.
148
+ * @s: the efuse object
241
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
149
+ * @bit: the efuse bit address for which a 32-bit value is read
242
create_unimplemented_device("npcm7xx.peci", 0xf0100000, 4 * KiB);
150
+ *
243
create_unimplemented_device("npcm7xx.siox[1]", 0xf0101000, 4 * KiB);
151
+ * Returns: the entire 32 bits of the efuse, starting at a bit
244
create_unimplemented_device("npcm7xx.siox[2]", 0xf0102000, 4 * KiB);
152
+ * address that is multiple of 32 and contains the bit at @bit
245
- create_unimplemented_device("npcm7xx.pwm[0]", 0xf0103000, 4 * KiB);
153
+ */
246
- create_unimplemented_device("npcm7xx.pwm[1]", 0xf0104000, 4 * KiB);
154
+static inline uint32_t xlnx_efuse_get_row(XlnxEFuse *s, unsigned int bit)
247
create_unimplemented_device("npcm7xx.mft[0]", 0xf0180000, 4 * KiB);
155
+{
248
create_unimplemented_device("npcm7xx.mft[1]", 0xf0181000, 4 * KiB);
156
+ if (!(s->fuse32)) {
249
create_unimplemented_device("npcm7xx.mft[2]", 0xf0182000, 4 * KiB);
157
+ return 0;
250
diff --git a/hw/misc/npcm7xx_pwm.c b/hw/misc/npcm7xx_pwm.c
158
+ } else {
159
+ unsigned int row_idx = bit / 32;
160
+
161
+ assert(row_idx < (s->efuse_size * s->efuse_nr / 32));
162
+ return s->fuse32[row_idx];
163
+ }
164
+}
165
+
166
+#endif
167
diff --git a/hw/nvram/xlnx-efuse-crc.c b/hw/nvram/xlnx-efuse-crc.c
168
new file mode 100644
251
new file mode 100644
169
index XXXXXXX..XXXXXXX
252
index XXXXXXX..XXXXXXX
170
--- /dev/null
253
--- /dev/null
171
+++ b/hw/nvram/xlnx-efuse-crc.c
254
+++ b/hw/misc/npcm7xx_pwm.c
172
@@ -XXX,XX +XXX,XX @@
255
@@ -XXX,XX +XXX,XX @@
173
+/*
256
+/*
174
+ * Xilinx eFuse/bbram CRC calculator
257
+ * Nuvoton NPCM7xx PWM Module
175
+ *
258
+ *
176
+ * Copyright (c) 2021 Xilinx Inc.
259
+ * Copyright 2020 Google LLC
177
+ *
260
+ *
178
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
261
+ * This program is free software; you can redistribute it and/or modify it
179
+ * of this software and associated documentation files (the "Software"), to deal
262
+ * under the terms of the GNU General Public License as published by the
180
+ * in the Software without restriction, including without limitation the rights
263
+ * Free Software Foundation; either version 2 of the License, or
181
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
264
+ * (at your option) any later version.
182
+ * copies of the Software, and to permit persons to whom the Software is
183
+ * furnished to do so, subject to the following conditions:
184
+ *
265
+ *
185
+ * The above copyright notice and this permission notice shall be included in
266
+ * This program is distributed in the hope that it will be useful, but WITHOUT
186
+ * all copies or substantial portions of the Software.
267
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
187
+ *
268
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
188
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
269
+ * for more details.
189
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
190
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
191
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
192
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
193
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
194
+ * THE SOFTWARE.
195
+ */
270
+ */
271
+
196
+#include "qemu/osdep.h"
272
+#include "qemu/osdep.h"
197
+#include "hw/nvram/xlnx-efuse.h"
273
+#include "hw/irq.h"
198
+
274
+#include "hw/qdev-clock.h"
199
+static uint32_t xlnx_efuse_u37_crc(uint32_t prev_crc, uint32_t data,
275
+#include "hw/qdev-properties.h"
200
+ uint32_t addr)
276
+#include "hw/misc/npcm7xx_pwm.h"
201
+{
277
+#include "hw/registerfields.h"
202
+ /* A table for 7-bit slicing */
278
+#include "migration/vmstate.h"
203
+ static const uint32_t crc_tab[128] = {
279
+#include "qemu/bitops.h"
204
+ 0x00000000, 0xe13b70f7, 0xc79a971f, 0x26a1e7e8,
205
+ 0x8ad958cf, 0x6be22838, 0x4d43cfd0, 0xac78bf27,
206
+ 0x105ec76f, 0xf165b798, 0xd7c45070, 0x36ff2087,
207
+ 0x9a879fa0, 0x7bbcef57, 0x5d1d08bf, 0xbc267848,
208
+ 0x20bd8ede, 0xc186fe29, 0xe72719c1, 0x061c6936,
209
+ 0xaa64d611, 0x4b5fa6e6, 0x6dfe410e, 0x8cc531f9,
210
+ 0x30e349b1, 0xd1d83946, 0xf779deae, 0x1642ae59,
211
+ 0xba3a117e, 0x5b016189, 0x7da08661, 0x9c9bf696,
212
+ 0x417b1dbc, 0xa0406d4b, 0x86e18aa3, 0x67dafa54,
213
+ 0xcba24573, 0x2a993584, 0x0c38d26c, 0xed03a29b,
214
+ 0x5125dad3, 0xb01eaa24, 0x96bf4dcc, 0x77843d3b,
215
+ 0xdbfc821c, 0x3ac7f2eb, 0x1c661503, 0xfd5d65f4,
216
+ 0x61c69362, 0x80fde395, 0xa65c047d, 0x4767748a,
217
+ 0xeb1fcbad, 0x0a24bb5a, 0x2c855cb2, 0xcdbe2c45,
218
+ 0x7198540d, 0x90a324fa, 0xb602c312, 0x5739b3e5,
219
+ 0xfb410cc2, 0x1a7a7c35, 0x3cdb9bdd, 0xdde0eb2a,
220
+ 0x82f63b78, 0x63cd4b8f, 0x456cac67, 0xa457dc90,
221
+ 0x082f63b7, 0xe9141340, 0xcfb5f4a8, 0x2e8e845f,
222
+ 0x92a8fc17, 0x73938ce0, 0x55326b08, 0xb4091bff,
223
+ 0x1871a4d8, 0xf94ad42f, 0xdfeb33c7, 0x3ed04330,
224
+ 0xa24bb5a6, 0x4370c551, 0x65d122b9, 0x84ea524e,
225
+ 0x2892ed69, 0xc9a99d9e, 0xef087a76, 0x0e330a81,
226
+ 0xb21572c9, 0x532e023e, 0x758fe5d6, 0x94b49521,
227
+ 0x38cc2a06, 0xd9f75af1, 0xff56bd19, 0x1e6dcdee,
228
+ 0xc38d26c4, 0x22b65633, 0x0417b1db, 0xe52cc12c,
229
+ 0x49547e0b, 0xa86f0efc, 0x8ecee914, 0x6ff599e3,
230
+ 0xd3d3e1ab, 0x32e8915c, 0x144976b4, 0xf5720643,
231
+ 0x590ab964, 0xb831c993, 0x9e902e7b, 0x7fab5e8c,
232
+ 0xe330a81a, 0x020bd8ed, 0x24aa3f05, 0xc5914ff2,
233
+ 0x69e9f0d5, 0x88d28022, 0xae7367ca, 0x4f48173d,
234
+ 0xf36e6f75, 0x12551f82, 0x34f4f86a, 0xd5cf889d,
235
+ 0x79b737ba, 0x988c474d, 0xbe2da0a5, 0x5f16d052
236
+ };
237
+
238
+ /*
239
+ * eFuse calculation is shown here:
240
+ * https://github.com/Xilinx/embeddedsw/blob/release-2019.2/lib/sw_services/xilskey/src/xilskey_utils.c#L1496
241
+ *
242
+ * Each u32 word is appended a 5-bit value, for a total of 37 bits; see:
243
+ * https://github.com/Xilinx/embeddedsw/blob/release-2019.2/lib/sw_services/xilskey/src/xilskey_utils.c#L1356
244
+ */
245
+ uint32_t crc = prev_crc;
246
+ const unsigned rshf = 7;
247
+ const uint32_t im = (1 << rshf) - 1;
248
+ const uint32_t rm = (1 << (32 - rshf)) - 1;
249
+ const uint32_t i2 = (1 << 2) - 1;
250
+ const uint32_t r2 = (1 << 30) - 1;
251
+
252
+ unsigned j;
253
+ uint32_t i, r;
254
+ uint64_t w;
255
+
256
+ w = (uint64_t)(addr) << 32;
257
+ w |= data;
258
+
259
+ /* Feed 35 bits, in 5 rounds, each a slice of 7 bits */
260
+ for (j = 0; j < 5; j++) {
261
+ r = rm & (crc >> rshf);
262
+ i = im & (crc ^ w);
263
+ crc = crc_tab[i] ^ r;
264
+
265
+ w >>= rshf;
266
+ }
267
+
268
+ /* Feed the remaining 2 bits */
269
+ r = r2 & (crc >> 2);
270
+ i = i2 & (crc ^ w);
271
+ crc = crc_tab[i << (rshf - 2)] ^ r;
272
+
273
+ return crc;
274
+}
275
+
276
+uint32_t xlnx_efuse_calc_crc(const uint32_t *data, unsigned u32_cnt,
277
+ unsigned zpads)
278
+{
279
+ uint32_t crc = 0;
280
+ unsigned index;
281
+
282
+ for (index = zpads; index; index--) {
283
+ crc = xlnx_efuse_u37_crc(crc, 0, (index + u32_cnt));
284
+ }
285
+
286
+ for (index = u32_cnt; index; index--) {
287
+ crc = xlnx_efuse_u37_crc(crc, data[index - 1], index);
288
+ }
289
+
290
+ return crc;
291
+}
292
diff --git a/hw/nvram/xlnx-efuse.c b/hw/nvram/xlnx-efuse.c
293
new file mode 100644
294
index XXXXXXX..XXXXXXX
295
--- /dev/null
296
+++ b/hw/nvram/xlnx-efuse.c
297
@@ -XXX,XX +XXX,XX @@
298
+/*
299
+ * QEMU model of the EFUSE eFuse
300
+ *
301
+ * Copyright (c) 2015 Xilinx Inc.
302
+ *
303
+ * Written by Edgar E. Iglesias <edgari@xilinx.com>
304
+ *
305
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
306
+ * of this software and associated documentation files (the "Software"), to deal
307
+ * in the Software without restriction, including without limitation the rights
308
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
309
+ * copies of the Software, and to permit persons to whom the Software is
310
+ * furnished to do so, subject to the following conditions:
311
+ *
312
+ * The above copyright notice and this permission notice shall be included in
313
+ * all copies or substantial portions of the Software.
314
+ *
315
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
316
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
317
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
318
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
319
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
320
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
321
+ * THE SOFTWARE.
322
+ */
323
+
324
+#include "qemu/osdep.h"
325
+#include "hw/nvram/xlnx-efuse.h"
326
+
327
+#include "qemu/error-report.h"
280
+#include "qemu/error-report.h"
328
+#include "qemu/log.h"
281
+#include "qemu/log.h"
329
+#include "qapi/error.h"
282
+#include "qemu/module.h"
330
+#include "sysemu/blockdev.h"
283
+#include "qemu/units.h"
331
+#include "hw/qdev-properties.h"
284
+#include "trace.h"
332
+#include "hw/qdev-properties-system.h"
285
+
333
+
286
+REG32(NPCM7XX_PWM_PPR, 0x00);
334
+#define TBIT0_OFFSET 28
287
+REG32(NPCM7XX_PWM_CSR, 0x04);
335
+#define TBIT1_OFFSET 29
288
+REG32(NPCM7XX_PWM_PCR, 0x08);
336
+#define TBIT2_OFFSET 30
289
+REG32(NPCM7XX_PWM_CNR0, 0x0c);
337
+#define TBIT3_OFFSET 31
290
+REG32(NPCM7XX_PWM_CMR0, 0x10);
338
+#define TBITS_PATTERN (0x0AU << TBIT0_OFFSET)
291
+REG32(NPCM7XX_PWM_PDR0, 0x14);
339
+#define TBITS_MASK (0x0FU << TBIT0_OFFSET)
292
+REG32(NPCM7XX_PWM_CNR1, 0x18);
340
+
293
+REG32(NPCM7XX_PWM_CMR1, 0x1c);
341
+bool xlnx_efuse_get_bit(XlnxEFuse *s, unsigned int bit)
294
+REG32(NPCM7XX_PWM_PDR1, 0x20);
342
+{
295
+REG32(NPCM7XX_PWM_CNR2, 0x24);
343
+ bool b = s->fuse32[bit / 32] & (1 << (bit % 32));
296
+REG32(NPCM7XX_PWM_CMR2, 0x28);
344
+ return b;
297
+REG32(NPCM7XX_PWM_PDR2, 0x2c);
345
+}
298
+REG32(NPCM7XX_PWM_CNR3, 0x30);
346
+
299
+REG32(NPCM7XX_PWM_CMR3, 0x34);
347
+static int efuse_bytes(XlnxEFuse *s)
300
+REG32(NPCM7XX_PWM_PDR3, 0x38);
348
+{
301
+REG32(NPCM7XX_PWM_PIER, 0x3c);
349
+ return ROUND_UP((s->efuse_nr * s->efuse_size) / 8, 4);
302
+REG32(NPCM7XX_PWM_PIIR, 0x40);
350
+}
303
+REG32(NPCM7XX_PWM_PWDR0, 0x44);
351
+
304
+REG32(NPCM7XX_PWM_PWDR1, 0x48);
352
+static int efuse_bdrv_read(XlnxEFuse *s, Error **errp)
305
+REG32(NPCM7XX_PWM_PWDR2, 0x4c);
353
+{
306
+REG32(NPCM7XX_PWM_PWDR3, 0x50);
354
+ uint32_t *ram = s->fuse32;
307
+
355
+ int nr = efuse_bytes(s);
308
+/* Register field definitions. */
356
+
309
+#define NPCM7XX_PPR(rv, index) extract32((rv), npcm7xx_ppr_base[index], 8)
357
+ if (!s->blk) {
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) {
358
+ return 0;
330
+ return 0;
359
+ }
331
+ }
360
+
332
+
361
+ s->blk_ro = !blk_supports_write_perm(s->blk);
333
+ csr = NPCM7XX_CSR(p->module->csr, p->index);
362
+ if (!s->blk_ro) {
334
+ ppr = NPCM7XX_PPR(p->module->ppr, p->index);
363
+ int rc;
335
+ freq = clock_get_hz(p->module->clock);
364
+
336
+ freq /= ppr + 1;
365
+ rc = blk_set_perm(s->blk,
337
+ /* csr can only be 0~4 */
366
+ (BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE),
338
+ if (csr > 4) {
367
+ BLK_PERM_ALL, NULL);
339
+ qemu_log_mask(LOG_GUEST_ERROR,
368
+ if (rc) {
340
+ "%s: invalid csr value %u\n",
369
+ s->blk_ro = true;
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);
370
+ }
363
+ }
371
+ }
364
+ } else {
372
+ if (s->blk_ro) {
365
+ duty = 0;
373
+ warn_report("%s: Skip saving updates to read-only eFUSE backstore.",
366
+ }
374
+ blk_name(s->blk));
367
+
375
+ }
368
+ if (p->inverted) {
376
+
369
+ duty = NPCM7XX_PWM_MAX_DUTY - duty;
377
+ if (blk_pread(s->blk, 0, ram, nr) < 0) {
370
+ }
378
+ error_setg(errp, "%s: Failed to read %u bytes from eFUSE backstore.",
371
+
379
+ blk_name(s->blk), nr);
372
+ return duty;
380
+ return -1;
373
+}
381
+ }
374
+
382
+
375
+static void npcm7xx_pwm_update_freq(NPCM7xxPWM *p)
383
+ /* Convert from little-endian backstore for each 32-bit row */
376
+{
384
+ nr /= 4;
377
+ uint32_t freq = npcm7xx_pwm_calculate_freq(p);
385
+ while (nr--) {
378
+
386
+ ram[nr] = le32_to_cpu(ram[nr]);
379
+ if (freq != p->freq) {
387
+ }
380
+ trace_npcm7xx_pwm_update_freq(DEVICE(p->module)->canonical_path,
388
+
381
+ p->index, p->freq, freq);
389
+ return 0;
382
+ p->freq = freq;
390
+}
383
+ }
391
+
384
+}
392
+static void efuse_bdrv_sync(XlnxEFuse *s, unsigned int bit)
385
+
393
+{
386
+static void npcm7xx_pwm_update_duty(NPCM7xxPWM *p)
394
+ unsigned int row_offset;
387
+{
395
+ uint32_t le32;
388
+ uint32_t duty = npcm7xx_pwm_calculate_duty(p);
396
+
389
+
397
+ if (!s->blk || s->blk_ro) {
390
+ if (duty != p->duty) {
398
+ return; /* Silent on read-only backend to avoid message flood */
391
+ trace_npcm7xx_pwm_update_duty(DEVICE(p->module)->canonical_path,
399
+ }
392
+ p->index, p->duty, duty);
400
+
393
+ p->duty = duty;
401
+ /* Backstore is always in little-endian */
394
+ }
402
+ le32 = cpu_to_le32(xlnx_efuse_get_row(s, bit));
395
+}
403
+
396
+
404
+ row_offset = (bit / 32) * 4;
397
+static void npcm7xx_pwm_update_output(NPCM7xxPWM *p)
405
+ if (blk_pwrite(s->blk, row_offset, &le32, 4, 0) < 0) {
398
+{
406
+ error_report("%s: Failed to write offset %u of eFUSE backstore.",
399
+ npcm7xx_pwm_update_freq(p);
407
+ blk_name(s->blk), row_offset);
400
+ npcm7xx_pwm_update_duty(p);
408
+ }
401
+}
409
+}
402
+
410
+
403
+static void npcm7xx_pwm_write_ppr(NPCM7xxPWMState *s, uint32_t new_ppr)
411
+static int efuse_ro_bits_cmp(const void *a, const void *b)
404
+{
412
+{
405
+ int i;
413
+ uint32_t i = *(const uint32_t *)a;
406
+ uint32_t old_ppr = s->ppr;
414
+ uint32_t j = *(const uint32_t *)b;
407
+
415
+
408
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_ppr_base) != NPCM7XX_PWM_PER_MODULE);
416
+ return (i > j) - (i < j);
409
+ s->ppr = new_ppr;
417
+}
410
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
418
+
411
+ if (NPCM7XX_PPR(old_ppr, i) != NPCM7XX_PPR(new_ppr, i)) {
419
+static void efuse_ro_bits_sort(XlnxEFuse *s)
412
+ npcm7xx_pwm_update_freq(&s->pwm[i]);
420
+{
413
+ }
421
+ uint32_t *ary = s->ro_bits;
414
+ }
422
+ const uint32_t cnt = s->ro_bits_cnt;
415
+}
423
+
416
+
424
+ if (ary && cnt > 1) {
417
+static void npcm7xx_pwm_write_csr(NPCM7xxPWMState *s, uint32_t new_csr)
425
+ qsort(ary, cnt, sizeof(ary[0]), efuse_ro_bits_cmp);
418
+{
426
+ }
419
+ int i;
427
+}
420
+ uint32_t old_csr = s->csr;
428
+
421
+
429
+static bool efuse_ro_bits_find(XlnxEFuse *s, uint32_t k)
422
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_csr_base) != NPCM7XX_PWM_PER_MODULE);
430
+{
423
+ s->csr = new_csr;
431
+ const uint32_t *ary = s->ro_bits;
424
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
432
+ const uint32_t cnt = s->ro_bits_cnt;
425
+ if (NPCM7XX_CSR(old_csr, i) != NPCM7XX_CSR(new_csr, i)) {
433
+
426
+ npcm7xx_pwm_update_freq(&s->pwm[i]);
434
+ if (!ary || !cnt) {
427
+ }
435
+ return false;
428
+ }
436
+ }
429
+}
437
+
430
+
438
+ return bsearch(&k, ary, cnt, sizeof(ary[0]), efuse_ro_bits_cmp) != NULL;
431
+static void npcm7xx_pwm_write_pcr(NPCM7xxPWMState *s, uint32_t new_pcr)
439
+}
432
+{
440
+
433
+ int i;
441
+bool xlnx_efuse_set_bit(XlnxEFuse *s, unsigned int bit)
434
+ bool inverted;
442
+{
435
+ uint32_t pcr;
443
+ if (efuse_ro_bits_find(s, bit)) {
436
+ NPCM7xxPWM *p;
444
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: WARN: "
437
+
445
+ "Ignored setting of readonly efuse bit<%u,%u>!\n",
438
+ s->pcr = new_pcr;
446
+ object_get_canonical_path(OBJECT(s)),
439
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_ch_base) != NPCM7XX_PWM_PER_MODULE);
447
+ (bit / 32), (bit % 32));
440
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
448
+ return false;
441
+ p = &s->pwm[i];
449
+ }
442
+ pcr = NPCM7XX_CH(new_pcr, i);
450
+
443
+ inverted = pcr & NPCM7XX_CH_INV;
451
+ s->fuse32[bit / 32] |= 1 << (bit % 32);
452
+ efuse_bdrv_sync(s, bit);
453
+ return true;
454
+}
455
+
456
+bool xlnx_efuse_k256_check(XlnxEFuse *s, uint32_t crc, unsigned start)
457
+{
458
+ uint32_t calc;
459
+
460
+ /* A key always occupies multiple of whole rows */
461
+ assert((start % 32) == 0);
462
+
463
+ calc = xlnx_efuse_calc_crc(&s->fuse32[start / 32], (256 / 32), 0);
464
+ return calc == crc;
465
+}
466
+
467
+uint32_t xlnx_efuse_tbits_check(XlnxEFuse *s)
468
+{
469
+ int nr;
470
+ uint32_t check = 0;
471
+
472
+ for (nr = s->efuse_nr; nr-- > 0; ) {
473
+ int efuse_start_row_num = (s->efuse_size * nr) / 32;
474
+ uint32_t data = s->fuse32[efuse_start_row_num];
475
+
444
+
476
+ /*
445
+ /*
477
+ * If the option is on, auto-init blank T-bits.
446
+ * We only run a PWM channel with toggle mode. Single-shot mode does not
478
+ * (non-blank will still be reported as '0' in the check, e.g.,
447
+ * generate frequency and duty-cycle values.
479
+ * for error-injection tests)
480
+ */
448
+ */
481
+ if ((data & TBITS_MASK) == 0 && s->init_tbits) {
449
+ if ((pcr & NPCM7XX_CH_EN) && (pcr & NPCM7XX_CH_MOD)) {
482
+ data |= TBITS_PATTERN;
450
+ if (p->running) {
483
+
451
+ /* Re-run this PWM channel if inverted changed. */
484
+ s->fuse32[efuse_start_row_num] = data;
452
+ if (p->inverted ^ inverted) {
485
+ efuse_bdrv_sync(s, (efuse_start_row_num * 32 + TBIT0_OFFSET));
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);
486
+ }
467
+ }
487
+
468
+ }
488
+ check = (check << 1) | ((data & TBITS_MASK) == TBITS_PATTERN);
469
+
489
+ }
470
+}
490
+
471
+
491
+ return check;
472
+static hwaddr npcm7xx_cnr_index(hwaddr offset)
492
+}
473
+{
493
+
474
+ switch (offset) {
494
+static void efuse_realize(DeviceState *dev, Error **errp)
475
+ case A_NPCM7XX_PWM_CNR0:
495
+{
476
+ return 0;
496
+ XlnxEFuse *s = XLNX_EFUSE(dev);
477
+ case A_NPCM7XX_PWM_CNR1:
497
+
478
+ return 1;
498
+ /* Sort readonly-list for bsearch lookup */
479
+ case A_NPCM7XX_PWM_CNR2:
499
+ efuse_ro_bits_sort(s);
480
+ return 2;
500
+
481
+ case A_NPCM7XX_PWM_CNR3:
501
+ if ((s->efuse_size % 32) != 0) {
482
+ return 3;
502
+ error_setg(errp,
483
+ default:
503
+ "%s.efuse-size: %u: property value not multiple of 32.",
484
+ g_assert_not_reached();
504
+ object_get_canonical_path(OBJECT(dev)), s->efuse_size);
485
+ }
505
+ return;
486
+}
506
+ }
487
+
507
+
488
+static hwaddr npcm7xx_cmr_index(hwaddr offset)
508
+ s->fuse32 = g_malloc0(efuse_bytes(s));
489
+{
509
+ if (efuse_bdrv_read(s, errp)) {
490
+ switch (offset) {
510
+ g_free(s->fuse32);
491
+ case A_NPCM7XX_PWM_CMR0:
511
+ }
492
+ return 0;
512
+}
493
+ case A_NPCM7XX_PWM_CMR1:
513
+
494
+ return 1;
514
+static void efuse_prop_set_drive(Object *obj, Visitor *v, const char *name,
495
+ case A_NPCM7XX_PWM_CMR2:
515
+ void *opaque, Error **errp)
496
+ return 2;
516
+{
497
+ case A_NPCM7XX_PWM_CMR3:
517
+ DeviceState *dev = DEVICE(obj);
498
+ return 3;
518
+
499
+ default:
519
+ qdev_prop_drive.set(obj, v, name, opaque, errp);
500
+ g_assert_not_reached();
520
+
501
+ }
521
+ /* Fill initial data if backend is attached after realized */
502
+}
522
+ if (dev->realized) {
503
+
523
+ efuse_bdrv_read(XLNX_EFUSE(obj), errp);
504
+static hwaddr npcm7xx_pdr_index(hwaddr offset)
524
+ }
505
+{
525
+}
506
+ switch (offset) {
526
+
507
+ case A_NPCM7XX_PWM_PDR0:
527
+static void efuse_prop_get_drive(Object *obj, Visitor *v, const char *name,
508
+ return 0;
528
+ void *opaque, Error **errp)
509
+ case A_NPCM7XX_PWM_PDR1:
529
+{
510
+ return 1;
530
+ qdev_prop_drive.get(obj, v, name, opaque, errp);
511
+ case A_NPCM7XX_PWM_PDR2:
531
+}
512
+ return 2;
532
+
513
+ case A_NPCM7XX_PWM_PDR3:
533
+static void efuse_prop_release_drive(Object *obj, const char *name,
514
+ return 3;
534
+ void *opaque)
515
+ default:
535
+{
516
+ g_assert_not_reached();
536
+ qdev_prop_drive.release(obj, name, opaque);
517
+ }
537
+}
518
+}
538
+
519
+
539
+static const PropertyInfo efuse_prop_drive = {
520
+static hwaddr npcm7xx_pwdr_index(hwaddr offset)
540
+ .name = "str",
521
+{
541
+ .description = "Node name or ID of a block device to use as eFUSE backend",
522
+ switch (offset) {
542
+ .realized_set_allowed = true,
523
+ case A_NPCM7XX_PWM_PWDR0:
543
+ .get = efuse_prop_get_drive,
524
+ return 0;
544
+ .set = efuse_prop_set_drive,
525
+ case A_NPCM7XX_PWM_PWDR1:
545
+ .release = efuse_prop_release_drive,
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
+ },
546
+};
687
+};
547
+
688
+
548
+static Property efuse_properties[] = {
689
+static void npcm7xx_pwm_enter_reset(Object *obj, ResetType type)
549
+ DEFINE_PROP("drive", XlnxEFuse, blk, efuse_prop_drive, BlockBackend *),
690
+{
550
+ DEFINE_PROP_UINT8("efuse-nr", XlnxEFuse, efuse_nr, 3),
691
+ NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
551
+ DEFINE_PROP_UINT32("efuse-size", XlnxEFuse, efuse_size, 64 * 32),
692
+ int i;
552
+ DEFINE_PROP_BOOL("init-factory-tbits", XlnxEFuse, init_tbits, true),
693
+
553
+ DEFINE_PROP_ARRAY("read-only", XlnxEFuse, ro_bits_cnt, ro_bits,
694
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
554
+ qdev_prop_uint32, uint32_t),
695
+ NPCM7xxPWM *p = &s->pwm[i];
555
+ DEFINE_PROP_END_OF_LIST(),
696
+
697
+ p->cnr = 0x00000000;
698
+ p->cmr = 0x00000000;
699
+ p->pdr = 0x00000000;
700
+ p->pwdr = 0x00000000;
701
+ }
702
+
703
+ s->ppr = 0x00000000;
704
+ s->csr = 0x00000000;
705
+ s->pcr = 0x00000000;
706
+ s->pier = 0x00000000;
707
+ s->piir = 0x00000000;
708
+}
709
+
710
+static void npcm7xx_pwm_hold_reset(Object *obj)
711
+{
712
+ NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
713
+ int i;
714
+
715
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
716
+ qemu_irq_lower(s->pwm[i].irq);
717
+ }
718
+}
719
+
720
+static void npcm7xx_pwm_init(Object *obj)
721
+{
722
+ NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
723
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
724
+ int i;
725
+
726
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
727
+ NPCM7xxPWM *p = &s->pwm[i];
728
+ p->module = s;
729
+ p->index = i;
730
+ sysbus_init_irq(sbd, &p->irq);
731
+ }
732
+
733
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_pwm_ops, s,
734
+ TYPE_NPCM7XX_PWM, 4 * KiB);
735
+ sysbus_init_mmio(sbd, &s->iomem);
736
+ s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL);
737
+
738
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
739
+ object_property_add_uint32_ptr(obj, "freq[*]",
740
+ &s->pwm[i].freq, OBJ_PROP_FLAG_READ);
741
+ object_property_add_uint32_ptr(obj, "duty[*]",
742
+ &s->pwm[i].duty, OBJ_PROP_FLAG_READ);
743
+ }
744
+}
745
+
746
+static const VMStateDescription vmstate_npcm7xx_pwm = {
747
+ .name = "npcm7xx-pwm",
748
+ .version_id = 0,
749
+ .minimum_version_id = 0,
750
+ .fields = (VMStateField[]) {
751
+ VMSTATE_BOOL(running, NPCM7xxPWM),
752
+ VMSTATE_BOOL(inverted, NPCM7xxPWM),
753
+ VMSTATE_UINT8(index, NPCM7xxPWM),
754
+ VMSTATE_UINT32(cnr, NPCM7xxPWM),
755
+ VMSTATE_UINT32(cmr, NPCM7xxPWM),
756
+ VMSTATE_UINT32(pdr, NPCM7xxPWM),
757
+ VMSTATE_UINT32(pwdr, NPCM7xxPWM),
758
+ VMSTATE_UINT32(freq, NPCM7xxPWM),
759
+ VMSTATE_UINT32(duty, NPCM7xxPWM),
760
+ VMSTATE_END_OF_LIST(),
761
+ },
556
+};
762
+};
557
+
763
+
558
+static void efuse_class_init(ObjectClass *klass, void *data)
764
+static const VMStateDescription vmstate_npcm7xx_pwm_module = {
559
+{
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);
560
+ DeviceClass *dc = DEVICE_CLASS(klass);
785
+ DeviceClass *dc = DEVICE_CLASS(klass);
561
+
786
+
562
+ dc->realize = efuse_realize;
787
+ dc->desc = "NPCM7xx PWM Controller";
563
+ device_class_set_props(dc, efuse_properties);
788
+ dc->vmsd = &vmstate_npcm7xx_pwm_module;
564
+}
789
+ rc->phases.enter = npcm7xx_pwm_enter_reset;
565
+
790
+ rc->phases.hold = npcm7xx_pwm_hold_reset;
566
+static const TypeInfo efuse_info = {
791
+}
567
+ .name = TYPE_XLNX_EFUSE,
792
+
568
+ .parent = TYPE_DEVICE,
793
+static const TypeInfo npcm7xx_pwm_info = {
569
+ .instance_size = sizeof(XlnxEFuse),
794
+ .name = TYPE_NPCM7XX_PWM,
570
+ .class_init = efuse_class_init,
795
+ .parent = TYPE_SYS_BUS_DEVICE,
796
+ .instance_size = sizeof(NPCM7xxPWMState),
797
+ .class_init = npcm7xx_pwm_class_init,
798
+ .instance_init = npcm7xx_pwm_init,
571
+};
799
+};
572
+
800
+
573
+static void efuse_register_types(void)
801
+static void npcm7xx_pwm_register_type(void)
574
+{
802
+{
575
+ type_register_static(&efuse_info);
803
+ type_register_static(&npcm7xx_pwm_info);
576
+}
804
+}
577
+type_init(efuse_register_types)
805
+type_init(npcm7xx_pwm_register_type);
578
diff --git a/hw/nvram/Kconfig b/hw/nvram/Kconfig
806
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
579
index XXXXXXX..XXXXXXX 100644
807
index XXXXXXX..XXXXXXX 100644
580
--- a/hw/nvram/Kconfig
808
--- a/hw/misc/meson.build
581
+++ b/hw/nvram/Kconfig
809
+++ b/hw/misc/meson.build
582
@@ -XXX,XX +XXX,XX @@ config NMC93XX_EEPROM
810
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c'))
583
811
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
584
config CHRP_NVRAM
812
'npcm7xx_clk.c',
585
bool
813
'npcm7xx_gcr.c',
586
+
814
+ 'npcm7xx_pwm.c',
587
+config XLNX_EFUSE_CRC
815
'npcm7xx_rng.c',
588
+ bool
816
))
589
+
817
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files(
590
+config XLNX_EFUSE
818
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
591
+ bool
592
+ select XLNX_EFUSE_CRC
593
diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build
594
index XXXXXXX..XXXXXXX 100644
819
index XXXXXXX..XXXXXXX 100644
595
--- a/hw/nvram/meson.build
820
--- a/hw/misc/trace-events
596
+++ b/hw/nvram/meson.build
821
+++ b/hw/misc/trace-events
597
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_AT24C', if_true: files('eeprom_at24c.c'))
822
@@ -XXX,XX +XXX,XX @@ npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " valu
598
softmmu_ss.add(when: 'CONFIG_MAC_NVRAM', if_true: files('mac_nvram.c'))
823
npcm7xx_rng_read(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
599
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_otp.c'))
824
npcm7xx_rng_write(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
600
softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_nvm.c'))
825
601
+softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_CRC', if_true: files('xlnx-efuse-crc.c'))
826
+# npcm7xx_pwm.c
602
+softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE', if_true: files('xlnx-efuse.c'))
827
+npcm7xx_pwm_read(const char *id, uint64_t offset, uint32_t value) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
603
828
+npcm7xx_pwm_write(const char *id, uint64_t offset, uint32_t value) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
604
specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_nvram.c'))
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"
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"
605
--
835
--
606
2.20.1
836
2.20.1
607
837
608
838
diff view generated by jsdifflib
1
From: Tong Ho <tong.ho@xilinx.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
This device is present in Versal and ZynqMP product
3
We add a qtest for the PWM in the previous patch. It proves it works as
4
families to store a 256-bit encryption key.
4
expected.
5
5
6
Co-authored-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
6
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
7
Co-authored-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
7
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
8
8
Signed-off-by: Hao Wu <wuhaotsh@google.com>
9
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
10
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
11
Signed-off-by: Tong Ho <tong.ho@xilinx.com>
12
Message-id: 20210917052400.1249094-5-tong.ho@xilinx.com
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20210108190945.949196-6-wuhaotsh@google.com
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
12
---
16
include/hw/nvram/xlnx-bbram.h | 54 ++++
13
tests/qtest/npcm7xx_pwm-test.c | 490 +++++++++++++++++++++++++++++++++
17
hw/nvram/xlnx-bbram.c | 545 ++++++++++++++++++++++++++++++++++
14
tests/qtest/meson.build | 1 +
18
hw/nvram/Kconfig | 4 +
15
2 files changed, 491 insertions(+)
19
hw/nvram/meson.build | 1 +
16
create mode 100644 tests/qtest/npcm7xx_pwm-test.c
20
4 files changed, 604 insertions(+)
21
create mode 100644 include/hw/nvram/xlnx-bbram.h
22
create mode 100644 hw/nvram/xlnx-bbram.c
23
17
24
diff --git a/include/hw/nvram/xlnx-bbram.h b/include/hw/nvram/xlnx-bbram.h
18
diff --git a/tests/qtest/npcm7xx_pwm-test.c b/tests/qtest/npcm7xx_pwm-test.c
25
new file mode 100644
19
new file mode 100644
26
index XXXXXXX..XXXXXXX
20
index XXXXXXX..XXXXXXX
27
--- /dev/null
21
--- /dev/null
28
+++ b/include/hw/nvram/xlnx-bbram.h
22
+++ b/tests/qtest/npcm7xx_pwm-test.c
29
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@
30
+/*
24
+/*
31
+ * QEMU model of the Xilinx BBRAM Battery Backed RAM
25
+ * QTests for Nuvoton NPCM7xx PWM Modules.
32
+ *
26
+ *
33
+ * Copyright (c) 2015-2021 Xilinx Inc.
27
+ * Copyright 2020 Google LLC
34
+ *
28
+ *
35
+ * Written by Edgar E. Iglesias <edgari@xilinx.com>
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.
36
+ *
33
+ *
37
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
34
+ * This program is distributed in the hope that it will be useful, but WITHOUT
38
+ * of this software and associated documentation files (the "Software"), to deal
35
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
39
+ * in the Software without restriction, including without limitation the rights
36
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
40
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
37
+ * for more details.
41
+ * copies of the Software, and to permit persons to whom the Software is
42
+ * furnished to do so, subject to the following conditions:
43
+ *
44
+ * The above copyright notice and this permission notice shall be included in
45
+ * all copies or substantial portions of the Software.
46
+ *
47
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
48
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
49
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
50
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
51
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
52
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
53
+ * THE SOFTWARE.
54
+ */
38
+ */
55
+#ifndef XLNX_BBRAM_H
39
+
56
+#define XLNX_BBRAM_H
40
+#include "qemu/osdep.h"
57
+
41
+#include "qemu/bitops.h"
58
+#include "sysemu/block-backend.h"
42
+#include "libqos/libqtest.h"
59
+#include "hw/qdev-core.h"
43
+#include "qapi/qmp/qdict.h"
60
+#include "hw/irq.h"
44
+#include "qapi/qmp/qnum.h"
61
+#include "hw/sysbus.h"
45
+
62
+#include "hw/register.h"
46
+#define REF_HZ 25000000
63
+
47
+
64
+#define RMAX_XLNX_BBRAM ((0x4c / 4) + 1)
48
+/* Register field definitions. */
65
+
49
+#define CH_EN BIT(0)
66
+#define TYPE_XLNX_BBRAM "xlnx,bbram-ctrl"
50
+#define CH_INV BIT(2)
67
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxBBRam, XLNX_BBRAM);
51
+#define CH_MOD BIT(3)
68
+
52
+
69
+struct XlnxBBRam {
53
+/* Registers shared between all PWMs in a module */
70
+ SysBusDevice parent_obj;
54
+#define PPR 0x00
71
+ qemu_irq irq_bbram;
55
+#define CSR 0x04
72
+
56
+#define PCR 0x08
73
+ BlockBackend *blk;
57
+#define PIER 0x3c
74
+
58
+#define PIIR 0x40
75
+ uint32_t crc_zpads;
59
+
76
+ bool bbram8_wo;
60
+/* CLK module related */
77
+ bool blk_ro;
61
+#define CLK_BA 0xf0801000
78
+
62
+#define CLKSEL 0x04
79
+ uint32_t regs[RMAX_XLNX_BBRAM];
63
+#define CLKDIV1 0x08
80
+ RegisterInfo regs_info[RMAX_XLNX_BBRAM];
64
+#define CLKDIV2 0x2c
65
+#define PLLCON0 0x0c
66
+#define PLLCON1 0x10
67
+#define PLL_INDV(rv) extract32((rv), 0, 6)
68
+#define PLL_FBDV(rv) extract32((rv), 16, 12)
69
+#define PLL_OTDV1(rv) extract32((rv), 8, 3)
70
+#define PLL_OTDV2(rv) extract32((rv), 13, 3)
71
+#define APB3CKDIV(rv) extract32((rv), 28, 2)
72
+#define CLK2CKDIV(rv) extract32((rv), 0, 1)
73
+#define CLK4CKDIV(rv) extract32((rv), 26, 2)
74
+#define CPUCKSEL(rv) extract32((rv), 0, 2)
75
+
76
+#define MAX_DUTY 1000000
77
+
78
+typedef struct PWMModule {
79
+ int irq;
80
+ uint64_t base_addr;
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
+ }
81
+};
104
+};
82
+
105
+
83
+#endif
106
+static const PWM pwm_list[] = {
84
diff --git a/hw/nvram/xlnx-bbram.c b/hw/nvram/xlnx-bbram.c
107
+ {
85
new file mode 100644
108
+ .cnr_offset = 0x0c,
86
index XXXXXXX..XXXXXXX
109
+ .cmr_offset = 0x10,
87
--- /dev/null
110
+ .pdr_offset = 0x14,
88
+++ b/hw/nvram/xlnx-bbram.c
111
+ .pwdr_offset = 0x44,
89
@@ -XXX,XX +XXX,XX @@
112
+ },
90
+/*
113
+ {
91
+ * QEMU model of the Xilinx BBRAM Battery Backed RAM
114
+ .cnr_offset = 0x18,
92
+ *
115
+ .cmr_offset = 0x1c,
93
+ * Copyright (c) 2014-2021 Xilinx Inc.
116
+ .pdr_offset = 0x20,
94
+ *
117
+ .pwdr_offset = 0x48,
95
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
118
+ },
96
+ * of this software and associated documentation files (the "Software"), to deal
119
+ {
97
+ * in the Software without restriction, including without limitation the rights
120
+ .cnr_offset = 0x24,
98
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
121
+ .cmr_offset = 0x28,
99
+ * copies of the Software, and to permit persons to whom the Software is
122
+ .pdr_offset = 0x2c,
100
+ * furnished to do so, subject to the following conditions:
123
+ .pwdr_offset = 0x4c,
101
+ *
124
+ },
102
+ * The above copyright notice and this permission notice shall be included in
125
+ {
103
+ * all copies or substantial portions of the Software.
126
+ .cnr_offset = 0x30,
104
+ *
127
+ .cmr_offset = 0x34,
105
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
128
+ .pdr_offset = 0x38,
106
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
129
+ .pwdr_offset = 0x50,
107
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
108
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
109
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
110
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
111
+ * THE SOFTWARE.
112
+ */
113
+
114
+#include "qemu/osdep.h"
115
+#include "hw/nvram/xlnx-bbram.h"
116
+
117
+#include "qemu/error-report.h"
118
+#include "qemu/log.h"
119
+#include "qapi/error.h"
120
+#include "sysemu/blockdev.h"
121
+#include "migration/vmstate.h"
122
+#include "hw/qdev-properties.h"
123
+#include "hw/qdev-properties-system.h"
124
+#include "hw/nvram/xlnx-efuse.h"
125
+
126
+#ifndef XLNX_BBRAM_ERR_DEBUG
127
+#define XLNX_BBRAM_ERR_DEBUG 0
128
+#endif
129
+
130
+REG32(BBRAM_STATUS, 0x0)
131
+ FIELD(BBRAM_STATUS, AES_CRC_PASS, 9, 1)
132
+ FIELD(BBRAM_STATUS, AES_CRC_DONE, 8, 1)
133
+ FIELD(BBRAM_STATUS, BBRAM_ZEROIZED, 4, 1)
134
+ FIELD(BBRAM_STATUS, PGM_MODE, 0, 1)
135
+REG32(BBRAM_CTRL, 0x4)
136
+ FIELD(BBRAM_CTRL, ZEROIZE, 0, 1)
137
+REG32(PGM_MODE, 0x8)
138
+REG32(BBRAM_AES_CRC, 0xc)
139
+REG32(BBRAM_0, 0x10)
140
+REG32(BBRAM_1, 0x14)
141
+REG32(BBRAM_2, 0x18)
142
+REG32(BBRAM_3, 0x1c)
143
+REG32(BBRAM_4, 0x20)
144
+REG32(BBRAM_5, 0x24)
145
+REG32(BBRAM_6, 0x28)
146
+REG32(BBRAM_7, 0x2c)
147
+REG32(BBRAM_8, 0x30)
148
+REG32(BBRAM_SLVERR, 0x34)
149
+ FIELD(BBRAM_SLVERR, ENABLE, 0, 1)
150
+REG32(BBRAM_ISR, 0x38)
151
+ FIELD(BBRAM_ISR, APB_SLVERR, 0, 1)
152
+REG32(BBRAM_IMR, 0x3c)
153
+ FIELD(BBRAM_IMR, APB_SLVERR, 0, 1)
154
+REG32(BBRAM_IER, 0x40)
155
+ FIELD(BBRAM_IER, APB_SLVERR, 0, 1)
156
+REG32(BBRAM_IDR, 0x44)
157
+ FIELD(BBRAM_IDR, APB_SLVERR, 0, 1)
158
+REG32(BBRAM_MSW_LOCK, 0x4c)
159
+ FIELD(BBRAM_MSW_LOCK, VAL, 0, 1)
160
+
161
+#define R_MAX (R_BBRAM_MSW_LOCK + 1)
162
+
163
+#define RAM_MAX (A_BBRAM_8 + 4 - A_BBRAM_0)
164
+
165
+#define BBRAM_PGM_MAGIC 0x757bdf0d
166
+
167
+QEMU_BUILD_BUG_ON(R_MAX != ARRAY_SIZE(((XlnxBBRam *)0)->regs));
168
+
169
+static bool bbram_msw_locked(XlnxBBRam *s)
170
+{
171
+ return ARRAY_FIELD_EX32(s->regs, BBRAM_MSW_LOCK, VAL) != 0;
172
+}
173
+
174
+static bool bbram_pgm_enabled(XlnxBBRam *s)
175
+{
176
+ return ARRAY_FIELD_EX32(s->regs, BBRAM_STATUS, PGM_MODE) != 0;
177
+}
178
+
179
+static void bbram_bdrv_error(XlnxBBRam *s, int rc, gchar *detail)
180
+{
181
+ Error *errp;
182
+
183
+ error_setg_errno(&errp, -rc, "%s: BBRAM backstore %s failed.",
184
+ blk_name(s->blk), detail);
185
+ error_report("%s", error_get_pretty(errp));
186
+ error_free(errp);
187
+
188
+ g_free(detail);
189
+}
190
+
191
+static void bbram_bdrv_read(XlnxBBRam *s, Error **errp)
192
+{
193
+ uint32_t *ram = &s->regs[R_BBRAM_0];
194
+ int nr = RAM_MAX;
195
+
196
+ if (!s->blk) {
197
+ return;
198
+ }
199
+
200
+ s->blk_ro = !blk_supports_write_perm(s->blk);
201
+ if (!s->blk_ro) {
202
+ int rc;
203
+
204
+ rc = blk_set_perm(s->blk,
205
+ (BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE),
206
+ BLK_PERM_ALL, NULL);
207
+ if (rc) {
208
+ s->blk_ro = true;
209
+ }
210
+ }
211
+ if (s->blk_ro) {
212
+ warn_report("%s: Skip saving updates to read-only BBRAM backstore.",
213
+ blk_name(s->blk));
214
+ }
215
+
216
+ if (blk_pread(s->blk, 0, ram, nr) < 0) {
217
+ error_setg(errp,
218
+ "%s: Failed to read %u bytes from BBRAM backstore.",
219
+ blk_name(s->blk), nr);
220
+ return;
221
+ }
222
+
223
+ /* Convert from little-endian backstore for each 32-bit word */
224
+ nr /= 4;
225
+ while (nr--) {
226
+ ram[nr] = le32_to_cpu(ram[nr]);
227
+ }
228
+}
229
+
230
+static void bbram_bdrv_sync(XlnxBBRam *s, uint64_t hwaddr)
231
+{
232
+ uint32_t le32;
233
+ unsigned offset;
234
+ int rc;
235
+
236
+ assert(A_BBRAM_0 <= hwaddr && hwaddr <= A_BBRAM_8);
237
+
238
+ /* Backstore is always in little-endian */
239
+ le32 = cpu_to_le32(s->regs[hwaddr / 4]);
240
+
241
+ /* Update zeroized flag */
242
+ if (le32 && (hwaddr != A_BBRAM_8 || s->bbram8_wo)) {
243
+ ARRAY_FIELD_DP32(s->regs, BBRAM_STATUS, BBRAM_ZEROIZED, 0);
244
+ }
245
+
246
+ if (!s->blk || s->blk_ro) {
247
+ return;
248
+ }
249
+
250
+ offset = hwaddr - A_BBRAM_0;
251
+ rc = blk_pwrite(s->blk, offset, &le32, 4, 0);
252
+ if (rc < 0) {
253
+ bbram_bdrv_error(s, rc, g_strdup_printf("write to offset %u", offset));
254
+ }
255
+}
256
+
257
+static void bbram_bdrv_zero(XlnxBBRam *s)
258
+{
259
+ int rc;
260
+
261
+ ARRAY_FIELD_DP32(s->regs, BBRAM_STATUS, BBRAM_ZEROIZED, 1);
262
+
263
+ if (!s->blk || s->blk_ro) {
264
+ return;
265
+ }
266
+
267
+ rc = blk_make_zero(s->blk, 0);
268
+ if (rc < 0) {
269
+ bbram_bdrv_error(s, rc, g_strdup("zeroizing"));
270
+ }
271
+
272
+ /* Restore bbram8 if it is non-zero */
273
+ if (s->regs[R_BBRAM_8]) {
274
+ bbram_bdrv_sync(s, A_BBRAM_8);
275
+ }
276
+}
277
+
278
+static void bbram_zeroize(XlnxBBRam *s)
279
+{
280
+ int nr = RAM_MAX - (s->bbram8_wo ? 0 : 4); /* only wo bbram8 is cleared */
281
+
282
+ memset(&s->regs[R_BBRAM_0], 0, nr);
283
+ bbram_bdrv_zero(s);
284
+}
285
+
286
+static void bbram_update_irq(XlnxBBRam *s)
287
+{
288
+ bool pending = s->regs[R_BBRAM_ISR] & ~s->regs[R_BBRAM_IMR];
289
+
290
+ qemu_set_irq(s->irq_bbram, pending);
291
+}
292
+
293
+static void bbram_ctrl_postw(RegisterInfo *reg, uint64_t val64)
294
+{
295
+ XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
296
+ uint32_t val = val64;
297
+
298
+ if (val & R_BBRAM_CTRL_ZEROIZE_MASK) {
299
+ bbram_zeroize(s);
300
+ /* The bit is self clearing */
301
+ s->regs[R_BBRAM_CTRL] &= ~R_BBRAM_CTRL_ZEROIZE_MASK;
302
+ }
303
+}
304
+
305
+static void bbram_pgm_mode_postw(RegisterInfo *reg, uint64_t val64)
306
+{
307
+ XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
308
+ uint32_t val = val64;
309
+
310
+ if (val == BBRAM_PGM_MAGIC) {
311
+ bbram_zeroize(s);
312
+
313
+ /* The status bit is cleared only by POR */
314
+ ARRAY_FIELD_DP32(s->regs, BBRAM_STATUS, PGM_MODE, 1);
315
+ }
316
+}
317
+
318
+static void bbram_aes_crc_postw(RegisterInfo *reg, uint64_t val64)
319
+{
320
+ XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
321
+ uint32_t calc_crc;
322
+
323
+ if (!bbram_pgm_enabled(s)) {
324
+ /* We are not in programming mode, don't do anything */
325
+ return;
326
+ }
327
+
328
+ /* Perform the AES integrity check */
329
+ s->regs[R_BBRAM_STATUS] |= R_BBRAM_STATUS_AES_CRC_DONE_MASK;
330
+
331
+ /*
332
+ * Set check status.
333
+ *
334
+ * ZynqMP BBRAM check has a zero-u32 prepended; see:
335
+ * https://github.com/Xilinx/embeddedsw/blob/release-2019.2/lib/sw_services/xilskey/src/xilskey_bbramps_zynqmp.c#L311
336
+ */
337
+ calc_crc = xlnx_efuse_calc_crc(&s->regs[R_BBRAM_0],
338
+ (R_BBRAM_8 - R_BBRAM_0), s->crc_zpads);
339
+
340
+ ARRAY_FIELD_DP32(s->regs, BBRAM_STATUS, AES_CRC_PASS,
341
+ (s->regs[R_BBRAM_AES_CRC] == calc_crc));
342
+}
343
+
344
+static uint64_t bbram_key_prew(RegisterInfo *reg, uint64_t val64)
345
+{
346
+ XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
347
+ uint32_t original_data = *(uint32_t *) reg->data;
348
+
349
+ if (bbram_pgm_enabled(s)) {
350
+ return val64;
351
+ } else {
352
+ /* We are not in programming mode, don't do anything */
353
+ qemu_log_mask(LOG_GUEST_ERROR,
354
+ "Not in programming mode, dropping the write\n");
355
+ return original_data;
356
+ }
357
+}
358
+
359
+static void bbram_key_postw(RegisterInfo *reg, uint64_t val64)
360
+{
361
+ XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
362
+
363
+ bbram_bdrv_sync(s, reg->access->addr);
364
+}
365
+
366
+static uint64_t bbram_wo_postr(RegisterInfo *reg, uint64_t val)
367
+{
368
+ return 0;
369
+}
370
+
371
+static uint64_t bbram_r8_postr(RegisterInfo *reg, uint64_t val)
372
+{
373
+ XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
374
+
375
+ return s->bbram8_wo ? bbram_wo_postr(reg, val) : val;
376
+}
377
+
378
+static bool bbram_r8_readonly(XlnxBBRam *s)
379
+{
380
+ return !bbram_pgm_enabled(s) || bbram_msw_locked(s);
381
+}
382
+
383
+static uint64_t bbram_r8_prew(RegisterInfo *reg, uint64_t val64)
384
+{
385
+ XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
386
+
387
+ if (bbram_r8_readonly(s)) {
388
+ val64 = *(uint32_t *)reg->data;
389
+ }
390
+
391
+ return val64;
392
+}
393
+
394
+static void bbram_r8_postw(RegisterInfo *reg, uint64_t val64)
395
+{
396
+ XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
397
+
398
+ if (!bbram_r8_readonly(s)) {
399
+ bbram_bdrv_sync(s, A_BBRAM_8);
400
+ }
401
+}
402
+
403
+static uint64_t bbram_msw_lock_prew(RegisterInfo *reg, uint64_t val64)
404
+{
405
+ XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
406
+
407
+ /* Never lock if bbram8 is wo; and, only POR can clear the lock */
408
+ if (s->bbram8_wo) {
409
+ val64 = 0;
410
+ } else {
411
+ val64 |= s->regs[R_BBRAM_MSW_LOCK];
412
+ }
413
+
414
+ return val64;
415
+}
416
+
417
+static void bbram_isr_postw(RegisterInfo *reg, uint64_t val64)
418
+{
419
+ XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
420
+
421
+ bbram_update_irq(s);
422
+}
423
+
424
+static uint64_t bbram_ier_prew(RegisterInfo *reg, uint64_t val64)
425
+{
426
+ XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
427
+ uint32_t val = val64;
428
+
429
+ s->regs[R_BBRAM_IMR] &= ~val;
430
+ bbram_update_irq(s);
431
+ return 0;
432
+}
433
+
434
+static uint64_t bbram_idr_prew(RegisterInfo *reg, uint64_t val64)
435
+{
436
+ XlnxBBRam *s = XLNX_BBRAM(reg->opaque);
437
+ uint32_t val = val64;
438
+
439
+ s->regs[R_BBRAM_IMR] |= val;
440
+ bbram_update_irq(s);
441
+ return 0;
442
+}
443
+
444
+static RegisterAccessInfo bbram_ctrl_regs_info[] = {
445
+ { .name = "BBRAM_STATUS", .addr = A_BBRAM_STATUS,
446
+ .rsvd = 0xee,
447
+ .ro = 0x3ff,
448
+ },{ .name = "BBRAM_CTRL", .addr = A_BBRAM_CTRL,
449
+ .post_write = bbram_ctrl_postw,
450
+ },{ .name = "PGM_MODE", .addr = A_PGM_MODE,
451
+ .post_write = bbram_pgm_mode_postw,
452
+ },{ .name = "BBRAM_AES_CRC", .addr = A_BBRAM_AES_CRC,
453
+ .post_write = bbram_aes_crc_postw,
454
+ .post_read = bbram_wo_postr,
455
+ },{ .name = "BBRAM_0", .addr = A_BBRAM_0,
456
+ .pre_write = bbram_key_prew,
457
+ .post_write = bbram_key_postw,
458
+ .post_read = bbram_wo_postr,
459
+ },{ .name = "BBRAM_1", .addr = A_BBRAM_1,
460
+ .pre_write = bbram_key_prew,
461
+ .post_write = bbram_key_postw,
462
+ .post_read = bbram_wo_postr,
463
+ },{ .name = "BBRAM_2", .addr = A_BBRAM_2,
464
+ .pre_write = bbram_key_prew,
465
+ .post_write = bbram_key_postw,
466
+ .post_read = bbram_wo_postr,
467
+ },{ .name = "BBRAM_3", .addr = A_BBRAM_3,
468
+ .pre_write = bbram_key_prew,
469
+ .post_write = bbram_key_postw,
470
+ .post_read = bbram_wo_postr,
471
+ },{ .name = "BBRAM_4", .addr = A_BBRAM_4,
472
+ .pre_write = bbram_key_prew,
473
+ .post_write = bbram_key_postw,
474
+ .post_read = bbram_wo_postr,
475
+ },{ .name = "BBRAM_5", .addr = A_BBRAM_5,
476
+ .pre_write = bbram_key_prew,
477
+ .post_write = bbram_key_postw,
478
+ .post_read = bbram_wo_postr,
479
+ },{ .name = "BBRAM_6", .addr = A_BBRAM_6,
480
+ .pre_write = bbram_key_prew,
481
+ .post_write = bbram_key_postw,
482
+ .post_read = bbram_wo_postr,
483
+ },{ .name = "BBRAM_7", .addr = A_BBRAM_7,
484
+ .pre_write = bbram_key_prew,
485
+ .post_write = bbram_key_postw,
486
+ .post_read = bbram_wo_postr,
487
+ },{ .name = "BBRAM_8", .addr = A_BBRAM_8,
488
+ .pre_write = bbram_r8_prew,
489
+ .post_write = bbram_r8_postw,
490
+ .post_read = bbram_r8_postr,
491
+ },{ .name = "BBRAM_SLVERR", .addr = A_BBRAM_SLVERR,
492
+ .rsvd = ~1,
493
+ },{ .name = "BBRAM_ISR", .addr = A_BBRAM_ISR,
494
+ .w1c = 0x1,
495
+ .post_write = bbram_isr_postw,
496
+ },{ .name = "BBRAM_IMR", .addr = A_BBRAM_IMR,
497
+ .ro = 0x1,
498
+ },{ .name = "BBRAM_IER", .addr = A_BBRAM_IER,
499
+ .pre_write = bbram_ier_prew,
500
+ },{ .name = "BBRAM_IDR", .addr = A_BBRAM_IDR,
501
+ .pre_write = bbram_idr_prew,
502
+ },{ .name = "BBRAM_MSW_LOCK", .addr = A_BBRAM_MSW_LOCK,
503
+ .pre_write = bbram_msw_lock_prew,
504
+ .ro = ~R_BBRAM_MSW_LOCK_VAL_MASK,
505
+ }
506
+};
507
+
508
+static void bbram_ctrl_reset(DeviceState *dev)
509
+{
510
+ XlnxBBRam *s = XLNX_BBRAM(dev);
511
+ unsigned int i;
512
+
513
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
514
+ if (i < R_BBRAM_0 || i > R_BBRAM_8) {
515
+ register_reset(&s->regs_info[i]);
516
+ }
517
+ }
518
+
519
+ bbram_update_irq(s);
520
+}
521
+
522
+static const MemoryRegionOps bbram_ctrl_ops = {
523
+ .read = register_read_memory,
524
+ .write = register_write_memory,
525
+ .endianness = DEVICE_LITTLE_ENDIAN,
526
+ .valid = {
527
+ .min_access_size = 4,
528
+ .max_access_size = 4,
529
+ },
130
+ },
530
+};
131
+};
531
+
132
+
532
+static void bbram_ctrl_realize(DeviceState *dev, Error **errp)
133
+static const int ppr_base[] = { 0, 0, 8, 8 };
533
+{
134
+static const int csr_base[] = { 0, 4, 8, 12 };
534
+ XlnxBBRam *s = XLNX_BBRAM(dev);
135
+static const int pcr_base[] = { 0, 8, 12, 16 };
535
+
136
+
536
+ if (s->crc_zpads) {
137
+static const uint32_t ppr_list[] = {
537
+ s->bbram8_wo = true;
138
+ 0,
538
+ }
139
+ 1,
539
+
140
+ 10,
540
+ bbram_bdrv_read(s, errp);
141
+ 100,
541
+}
142
+ 255, /* Max possible value. */
542
+
543
+static void bbram_ctrl_init(Object *obj)
544
+{
545
+ XlnxBBRam *s = XLNX_BBRAM(obj);
546
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
547
+ RegisterInfoArray *reg_array;
548
+
549
+ reg_array =
550
+ register_init_block32(DEVICE(obj), bbram_ctrl_regs_info,
551
+ ARRAY_SIZE(bbram_ctrl_regs_info),
552
+ s->regs_info, s->regs,
553
+ &bbram_ctrl_ops,
554
+ XLNX_BBRAM_ERR_DEBUG,
555
+ R_MAX * 4);
556
+
557
+ sysbus_init_mmio(sbd, &reg_array->mem);
558
+ sysbus_init_irq(sbd, &s->irq_bbram);
559
+}
560
+
561
+static void bbram_prop_set_drive(Object *obj, Visitor *v, const char *name,
562
+ void *opaque, Error **errp)
563
+{
564
+ DeviceState *dev = DEVICE(obj);
565
+
566
+ qdev_prop_drive.set(obj, v, name, opaque, errp);
567
+
568
+ /* Fill initial data if backend is attached after realized */
569
+ if (dev->realized) {
570
+ bbram_bdrv_read(XLNX_BBRAM(obj), errp);
571
+ }
572
+}
573
+
574
+static void bbram_prop_get_drive(Object *obj, Visitor *v, const char *name,
575
+ void *opaque, Error **errp)
576
+{
577
+ qdev_prop_drive.get(obj, v, name, opaque, errp);
578
+}
579
+
580
+static void bbram_prop_release_drive(Object *obj, const char *name,
581
+ void *opaque)
582
+{
583
+ qdev_prop_drive.release(obj, name, opaque);
584
+}
585
+
586
+static const PropertyInfo bbram_prop_drive = {
587
+ .name = "str",
588
+ .description = "Node name or ID of a block device to use as BBRAM backend",
589
+ .realized_set_allowed = true,
590
+ .get = bbram_prop_get_drive,
591
+ .set = bbram_prop_set_drive,
592
+ .release = bbram_prop_release_drive,
593
+};
143
+};
594
+
144
+
595
+static const VMStateDescription vmstate_bbram_ctrl = {
145
+static const uint32_t csr_list[] = {
596
+ .name = TYPE_XLNX_BBRAM,
146
+ 0,
597
+ .version_id = 1,
147
+ 1,
598
+ .minimum_version_id = 1,
148
+ 2,
599
+ .fields = (VMStateField[]) {
149
+ 3,
600
+ VMSTATE_UINT32_ARRAY(regs, XlnxBBRam, R_MAX),
150
+ 4, /* Max possible value. */
601
+ VMSTATE_END_OF_LIST(),
602
+ }
603
+};
151
+};
604
+
152
+
605
+static Property bbram_ctrl_props[] = {
153
+static const uint32_t cnr_list[] = {
606
+ DEFINE_PROP("drive", XlnxBBRam, blk, bbram_prop_drive, BlockBackend *),
154
+ 0,
607
+ DEFINE_PROP_UINT32("crc-zpads", XlnxBBRam, crc_zpads, 1),
155
+ 1,
608
+ DEFINE_PROP_END_OF_LIST(),
156
+ 50,
157
+ 100,
158
+ 150,
159
+ 200,
160
+ 1000,
161
+ 10000,
162
+ 65535, /* Max possible value. */
609
+};
163
+};
610
+
164
+
611
+static void bbram_ctrl_class_init(ObjectClass *klass, void *data)
165
+static const uint32_t cmr_list[] = {
612
+{
166
+ 0,
613
+ DeviceClass *dc = DEVICE_CLASS(klass);
167
+ 1,
614
+
168
+ 10,
615
+ dc->reset = bbram_ctrl_reset;
169
+ 50,
616
+ dc->realize = bbram_ctrl_realize;
170
+ 100,
617
+ dc->vmsd = &vmstate_bbram_ctrl;
171
+ 150,
618
+ device_class_set_props(dc, bbram_ctrl_props);
172
+ 200,
619
+}
173
+ 1000,
620
+
174
+ 10000,
621
+static const TypeInfo bbram_ctrl_info = {
175
+ 65535, /* Max possible value. */
622
+ .name = TYPE_XLNX_BBRAM,
623
+ .parent = TYPE_SYS_BUS_DEVICE,
624
+ .instance_size = sizeof(XlnxBBRam),
625
+ .class_init = bbram_ctrl_class_init,
626
+ .instance_init = bbram_ctrl_init,
627
+};
176
+};
628
+
177
+
629
+static void bbram_ctrl_register_types(void)
178
+/* Returns the index of the PWM module. */
630
+{
179
+static int pwm_module_index(const PWMModule *module)
631
+ type_register_static(&bbram_ctrl_info);
180
+{
632
+}
181
+ ptrdiff_t diff = module - pwm_module_list;
633
+
182
+
634
+type_init(bbram_ctrl_register_types)
183
+ g_assert_true(diff >= 0 && diff < ARRAY_SIZE(pwm_module_list));
635
diff --git a/hw/nvram/Kconfig b/hw/nvram/Kconfig
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)
492
+
493
+int main(int argc, char **argv)
494
+{
495
+ TestData test_data_list[ARRAY_SIZE(pwm_module_list) * ARRAY_SIZE(pwm_list)];
496
+
497
+ g_test_init(&argc, &argv, NULL);
498
+
499
+ for (int i = 0; i < ARRAY_SIZE(pwm_module_list); ++i) {
500
+ for (int j = 0; j < ARRAY_SIZE(pwm_list); ++j) {
501
+ TestData *td = &test_data_list[i * ARRAY_SIZE(pwm_list) + j];
502
+
503
+ td->module = &pwm_module_list[i];
504
+ td->pwm = &pwm_list[j];
505
+
506
+ add_test(init, td);
507
+ add_test(oneshot, td);
508
+ add_test(toggle, td);
509
+ }
510
+ }
511
+
512
+ return g_test_run();
513
+}
514
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
636
index XXXXXXX..XXXXXXX 100644
515
index XXXXXXX..XXXXXXX 100644
637
--- a/hw/nvram/Kconfig
516
--- a/tests/qtest/meson.build
638
+++ b/hw/nvram/Kconfig
517
+++ b/tests/qtest/meson.build
639
@@ -XXX,XX +XXX,XX @@ config XLNX_EFUSE_VERSAL
518
@@ -XXX,XX +XXX,XX @@ qtests_sparc64 = \
640
config XLNX_EFUSE_ZYNQMP
519
qtests_npcm7xx = \
641
bool
520
['npcm7xx_adc-test',
642
select XLNX_EFUSE
521
'npcm7xx_gpio-test',
643
+
522
+ 'npcm7xx_pwm-test',
644
+config XLNX_BBRAM
523
'npcm7xx_rng-test',
645
+ bool
524
'npcm7xx_timer-test',
646
+ select XLNX_EFUSE_CRC
525
'npcm7xx_watchdog_timer-test']
647
diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build
648
index XXXXXXX..XXXXXXX 100644
649
--- a/hw/nvram/meson.build
650
+++ b/hw/nvram/meson.build
651
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_VERSAL', if_true: files(
652
'xlnx-versal-efuse-ctrl.c'))
653
softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_ZYNQMP', if_true: files(
654
'xlnx-zynqmp-efuse.c'))
655
+softmmu_ss.add(when: 'CONFIG_XLNX_BBRAM', if_true: files('xlnx-bbram.c'))
656
657
specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_nvram.c'))
658
--
526
--
659
2.20.1
527
2.20.1
660
528
661
529
diff view generated by jsdifflib
Deleted patch
1
The aarch64-linux QEMU usermode binaries can never run 32-bit
2
code, so they do not need to include the GDB XML for it.
3
(arm_cpu_register_gdb_regs_for_features() will not use these
4
XML files if the CPU has ARM_FEATURE_AARCH64, so we will not
5
advertise to gdb that we have them.)
6
1
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210921162901.17508-2-peter.maydell@linaro.org
10
---
11
configs/targets/aarch64-linux-user.mak | 2 +-
12
configs/targets/aarch64_be-linux-user.mak | 2 +-
13
2 files changed, 2 insertions(+), 2 deletions(-)
14
15
diff --git a/configs/targets/aarch64-linux-user.mak b/configs/targets/aarch64-linux-user.mak
16
index XXXXXXX..XXXXXXX 100644
17
--- a/configs/targets/aarch64-linux-user.mak
18
+++ b/configs/targets/aarch64-linux-user.mak
19
@@ -XXX,XX +XXX,XX @@
20
TARGET_ARCH=aarch64
21
TARGET_BASE_ARCH=arm
22
-TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
23
+TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml
24
TARGET_HAS_BFLT=y
25
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
26
diff --git a/configs/targets/aarch64_be-linux-user.mak b/configs/targets/aarch64_be-linux-user.mak
27
index XXXXXXX..XXXXXXX 100644
28
--- a/configs/targets/aarch64_be-linux-user.mak
29
+++ b/configs/targets/aarch64_be-linux-user.mak
30
@@ -XXX,XX +XXX,XX @@
31
TARGET_ARCH=aarch64
32
TARGET_BASE_ARCH=arm
33
TARGET_WORDS_BIGENDIAN=y
34
-TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
35
+TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml
36
TARGET_HAS_BFLT=y
37
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
38
--
39
2.20.1
40
41
diff view generated by jsdifflib
1
The function scsi_bus_new() creates a new SCSI bus; callers can
1
From: Hao Wu <wuhaotsh@google.com>
2
either pass in a name argument to specify the name of the new bus, or
3
they can pass in NULL to allow the bus to be given an automatically
4
generated unique name. Almost all callers want to use the
5
autogenerated name; the only exception is the virtio-scsi device.
6
2
7
Taking a name argument that should almost always be NULL is an
3
A device shouldn't access its parent object which is QOM internal.
8
easy-to-misuse API design -- it encourages callers to think perhaps
4
Instead it should use type cast for this purporse. This patch fixes this
9
they should pass in some standard name like "scsi" or "scsi-bus". We
5
issue for all NPCM7XX Devices.
10
don't do this anywhere for SCSI, but we do (incorrectly) do it for
11
other bus types such as i2c.
12
6
13
The function name also implies that it will return a newly allocated
7
Signed-off-by: Hao Wu <wuhaotsh@google.com>
14
object, when it in fact does in-place allocation. We more commonly
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
name such functions foo_init(), with foo_new() being the
9
Message-id: 20210108190945.949196-7-wuhaotsh@google.com
16
allocate-and-return variant.
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
hw/arm/npcm7xx_boards.c | 2 +-
13
hw/mem/npcm7xx_mc.c | 2 +-
14
hw/misc/npcm7xx_clk.c | 2 +-
15
hw/misc/npcm7xx_gcr.c | 2 +-
16
hw/misc/npcm7xx_rng.c | 2 +-
17
hw/nvram/npcm7xx_otp.c | 2 +-
18
hw/ssi/npcm7xx_fiu.c | 2 +-
19
7 files changed, 7 insertions(+), 7 deletions(-)
17
20
18
Replace all the scsi_bus_new() callsites with either:
21
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
19
* scsi_bus_init() for the usual case where the caller wants
20
an autogenerated bus name
21
* scsi_bus_init_named() for the rare case where the caller
22
needs to specify the bus name
23
24
and document that for the _named() version it's then the caller's
25
responsibility to think about uniqueness of bus names.
26
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
29
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
30
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
31
Message-id: 20210923121153.23754-2-peter.maydell@linaro.org
32
---
33
include/hw/scsi/scsi.h | 30 ++++++++++++++++++++++++++++--
34
hw/scsi/esp-pci.c | 2 +-
35
hw/scsi/esp.c | 2 +-
36
hw/scsi/lsi53c895a.c | 2 +-
37
hw/scsi/megasas.c | 3 +--
38
hw/scsi/mptsas.c | 2 +-
39
hw/scsi/scsi-bus.c | 4 ++--
40
hw/scsi/spapr_vscsi.c | 3 +--
41
hw/scsi/virtio-scsi.c | 4 ++--
42
hw/scsi/vmw_pvscsi.c | 3 +--
43
hw/usb/dev-storage-bot.c | 3 +--
44
hw/usb/dev-storage-classic.c | 4 ++--
45
hw/usb/dev-uas.c | 3 +--
46
13 files changed, 43 insertions(+), 22 deletions(-)
47
48
diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
49
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
50
--- a/include/hw/scsi/scsi.h
23
--- a/hw/arm/npcm7xx_boards.c
51
+++ b/include/hw/scsi/scsi.h
24
+++ b/hw/arm/npcm7xx_boards.c
52
@@ -XXX,XX +XXX,XX @@ struct SCSIBus {
25
@@ -XXX,XX +XXX,XX @@ static NPCM7xxState *npcm7xx_create_soc(MachineState *machine,
53
const SCSIBusInfo *info;
26
uint32_t hw_straps)
54
};
55
56
-void scsi_bus_new(SCSIBus *bus, size_t bus_size, DeviceState *host,
57
- const SCSIBusInfo *info, const char *bus_name);
58
+/**
59
+ * scsi_bus_init_named: Initialize a SCSI bus with the specified name
60
+ * @bus: SCSIBus object to initialize
61
+ * @bus_size: size of @bus object
62
+ * @host: Device which owns the bus (generally the SCSI controller)
63
+ * @info: structure defining callbacks etc for the controller
64
+ * @bus_name: Name to use for this bus
65
+ *
66
+ * This in-place initializes @bus as a new SCSI bus with a name
67
+ * provided by the caller. It is the caller's responsibility to make
68
+ * sure that name does not clash with the name of any other bus in the
69
+ * system. Unless you need the new bus to have a specific name, you
70
+ * should use scsi_bus_new() instead.
71
+ */
72
+void scsi_bus_init_named(SCSIBus *bus, size_t bus_size, DeviceState *host,
73
+ const SCSIBusInfo *info, const char *bus_name);
74
+
75
+/**
76
+ * scsi_bus_init: Initialize a SCSI bus
77
+ *
78
+ * This in-place-initializes @bus as a new SCSI bus and gives it
79
+ * an automatically generated unique name.
80
+ */
81
+static inline void scsi_bus_init(SCSIBus *bus, size_t bus_size,
82
+ DeviceState *host, const SCSIBusInfo *info)
83
+{
84
+ scsi_bus_init_named(bus, bus_size, host, info, NULL);
85
+}
86
87
static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
88
{
27
{
89
diff --git a/hw/scsi/esp-pci.c b/hw/scsi/esp-pci.c
28
NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_GET_CLASS(machine);
29
- MachineClass *mc = &nmc->parent;
30
+ MachineClass *mc = MACHINE_CLASS(nmc);
31
Object *obj;
32
33
if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
34
diff --git a/hw/mem/npcm7xx_mc.c b/hw/mem/npcm7xx_mc.c
90
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
91
--- a/hw/scsi/esp-pci.c
36
--- a/hw/mem/npcm7xx_mc.c
92
+++ b/hw/scsi/esp-pci.c
37
+++ b/hw/mem/npcm7xx_mc.c
93
@@ -XXX,XX +XXX,XX @@ static void esp_pci_scsi_realize(PCIDevice *dev, Error **errp)
38
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_mc_realize(DeviceState *dev, Error **errp)
94
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->io);
39
95
s->irq = pci_allocate_irq(dev);
40
memory_region_init_io(&s->mmio, OBJECT(s), &npcm7xx_mc_ops, s, "regs",
96
41
NPCM7XX_MC_REGS_SIZE);
97
- scsi_bus_new(&s->bus, sizeof(s->bus), d, &esp_pci_scsi_info, NULL);
42
- sysbus_init_mmio(&s->parent, &s->mmio);
98
+ scsi_bus_init(&s->bus, sizeof(s->bus), d, &esp_pci_scsi_info);
43
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio);
99
}
44
}
100
45
101
static void esp_pci_scsi_exit(PCIDevice *d)
46
static void npcm7xx_mc_class_init(ObjectClass *klass, void *data)
102
diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
47
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
103
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
104
--- a/hw/scsi/esp.c
49
--- a/hw/misc/npcm7xx_clk.c
105
+++ b/hw/scsi/esp.c
50
+++ b/hw/misc/npcm7xx_clk.c
106
@@ -XXX,XX +XXX,XX @@ static void sysbus_esp_realize(DeviceState *dev, Error **errp)
51
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_init(Object *obj)
107
52
108
qdev_init_gpio_in(dev, sysbus_esp_gpio_demux, 2);
53
memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s,
109
54
TYPE_NPCM7XX_CLK, 4 * KiB);
110
- scsi_bus_new(&s->bus, sizeof(s->bus), dev, &esp_scsi_info, NULL);
55
- sysbus_init_mmio(&s->parent, &s->iomem);
111
+ scsi_bus_init(&s->bus, sizeof(s->bus), dev, &esp_scsi_info);
56
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
112
}
57
}
113
58
114
static void sysbus_esp_hard_reset(DeviceState *dev)
59
static int npcm7xx_clk_post_load(void *opaque, int version_id)
115
diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c
60
diff --git a/hw/misc/npcm7xx_gcr.c b/hw/misc/npcm7xx_gcr.c
116
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
117
--- a/hw/scsi/lsi53c895a.c
62
--- a/hw/misc/npcm7xx_gcr.c
118
+++ b/hw/scsi/lsi53c895a.c
63
+++ b/hw/misc/npcm7xx_gcr.c
119
@@ -XXX,XX +XXX,XX @@ static void lsi_scsi_realize(PCIDevice *dev, Error **errp)
64
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_gcr_init(Object *obj)
120
pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ram_io);
65
121
QTAILQ_INIT(&s->queue);
66
memory_region_init_io(&s->iomem, obj, &npcm7xx_gcr_ops, s,
122
67
TYPE_NPCM7XX_GCR, 4 * KiB);
123
- scsi_bus_new(&s->bus, sizeof(s->bus), d, &lsi_scsi_info, NULL);
68
- sysbus_init_mmio(&s->parent, &s->iomem);
124
+ scsi_bus_init(&s->bus, sizeof(s->bus), d, &lsi_scsi_info);
69
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
125
}
70
}
126
71
127
static void lsi_scsi_exit(PCIDevice *dev)
72
static const VMStateDescription vmstate_npcm7xx_gcr = {
128
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
73
diff --git a/hw/misc/npcm7xx_rng.c b/hw/misc/npcm7xx_rng.c
129
index XXXXXXX..XXXXXXX 100644
74
index XXXXXXX..XXXXXXX 100644
130
--- a/hw/scsi/megasas.c
75
--- a/hw/misc/npcm7xx_rng.c
131
+++ b/hw/scsi/megasas.c
76
+++ b/hw/misc/npcm7xx_rng.c
132
@@ -XXX,XX +XXX,XX @@ static void megasas_scsi_realize(PCIDevice *dev, Error **errp)
77
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_rng_init(Object *obj)
133
s->frames[i].state = s;
78
134
}
79
memory_region_init_io(&s->iomem, obj, &npcm7xx_rng_ops, s, "regs",
135
80
NPCM7XX_RNG_REGS_SIZE);
136
- scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev),
81
- sysbus_init_mmio(&s->parent, &s->iomem);
137
- &megasas_scsi_info, NULL);
82
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
138
+ scsi_bus_init(&s->bus, sizeof(s->bus), DEVICE(dev), &megasas_scsi_info);
139
}
83
}
140
84
141
static Property megasas_properties_gen1[] = {
85
static const VMStateDescription vmstate_npcm7xx_rng = {
142
diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c
86
diff --git a/hw/nvram/npcm7xx_otp.c b/hw/nvram/npcm7xx_otp.c
143
index XXXXXXX..XXXXXXX 100644
87
index XXXXXXX..XXXXXXX 100644
144
--- a/hw/scsi/mptsas.c
88
--- a/hw/nvram/npcm7xx_otp.c
145
+++ b/hw/scsi/mptsas.c
89
+++ b/hw/nvram/npcm7xx_otp.c
146
@@ -XXX,XX +XXX,XX @@ static void mptsas_scsi_realize(PCIDevice *dev, Error **errp)
90
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_otp_realize(DeviceState *dev, Error **errp)
147
91
{
148
s->request_bh = qemu_bh_new(mptsas_fetch_requests, s);
92
NPCM7xxOTPClass *oc = NPCM7XX_OTP_GET_CLASS(dev);
149
93
NPCM7xxOTPState *s = NPCM7XX_OTP(dev);
150
- scsi_bus_new(&s->bus, sizeof(s->bus), &dev->qdev, &mptsas_scsi_info, NULL);
94
- SysBusDevice *sbd = &s->parent;
151
+ scsi_bus_init(&s->bus, sizeof(s->bus), &dev->qdev, &mptsas_scsi_info);
95
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
152
}
96
153
97
memset(s->array, 0, sizeof(s->array));
154
static void mptsas_scsi_uninit(PCIDevice *dev)
98
155
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
99
diff --git a/hw/ssi/npcm7xx_fiu.c b/hw/ssi/npcm7xx_fiu.c
156
index XXXXXXX..XXXXXXX 100644
100
index XXXXXXX..XXXXXXX 100644
157
--- a/hw/scsi/scsi-bus.c
101
--- a/hw/ssi/npcm7xx_fiu.c
158
+++ b/hw/scsi/scsi-bus.c
102
+++ b/hw/ssi/npcm7xx_fiu.c
159
@@ -XXX,XX +XXX,XX @@ void scsi_device_unit_attention_reported(SCSIDevice *s)
103
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_fiu_hold_reset(Object *obj)
160
}
104
static void npcm7xx_fiu_realize(DeviceState *dev, Error **errp)
161
162
/* Create a scsi bus, and attach devices to it. */
163
-void scsi_bus_new(SCSIBus *bus, size_t bus_size, DeviceState *host,
164
- const SCSIBusInfo *info, const char *bus_name)
165
+void scsi_bus_init_named(SCSIBus *bus, size_t bus_size, DeviceState *host,
166
+ const SCSIBusInfo *info, const char *bus_name)
167
{
105
{
168
qbus_create_inplace(bus, bus_size, TYPE_SCSI_BUS, host, bus_name);
106
NPCM7xxFIUState *s = NPCM7XX_FIU(dev);
169
bus->busnr = next_scsi_bus++;
107
- SysBusDevice *sbd = &s->parent;
170
diff --git a/hw/scsi/spapr_vscsi.c b/hw/scsi/spapr_vscsi.c
108
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
171
index XXXXXXX..XXXXXXX 100644
109
int i;
172
--- a/hw/scsi/spapr_vscsi.c
110
173
+++ b/hw/scsi/spapr_vscsi.c
111
if (s->cs_count <= 0) {
174
@@ -XXX,XX +XXX,XX @@ static void spapr_vscsi_realize(SpaprVioDevice *dev, Error **errp)
175
176
dev->crq.SendFunc = vscsi_do_crq;
177
178
- scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev),
179
- &vscsi_scsi_info, NULL);
180
+ scsi_bus_init(&s->bus, sizeof(s->bus), DEVICE(dev), &vscsi_scsi_info);
181
182
/* ibmvscsi SCSI bus does not allow hotplug. */
183
qbus_set_hotplug_handler(BUS(&s->bus), NULL);
184
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
185
index XXXXXXX..XXXXXXX 100644
186
--- a/hw/scsi/virtio-scsi.c
187
+++ b/hw/scsi/virtio-scsi.c
188
@@ -XXX,XX +XXX,XX @@ static void virtio_scsi_device_realize(DeviceState *dev, Error **errp)
189
return;
190
}
191
192
- scsi_bus_new(&s->bus, sizeof(s->bus), dev,
193
- &virtio_scsi_scsi_info, vdev->bus_name);
194
+ scsi_bus_init_named(&s->bus, sizeof(s->bus), dev,
195
+ &virtio_scsi_scsi_info, vdev->bus_name);
196
/* override default SCSI bus hotplug-handler, with virtio-scsi's one */
197
qbus_set_hotplug_handler(BUS(&s->bus), OBJECT(dev));
198
199
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
200
index XXXXXXX..XXXXXXX 100644
201
--- a/hw/scsi/vmw_pvscsi.c
202
+++ b/hw/scsi/vmw_pvscsi.c
203
@@ -XXX,XX +XXX,XX @@ pvscsi_realizefn(PCIDevice *pci_dev, Error **errp)
204
205
s->completion_worker = qemu_bh_new(pvscsi_process_completion_queue, s);
206
207
- scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(pci_dev),
208
- &pvscsi_scsi_info, NULL);
209
+ scsi_bus_init(&s->bus, sizeof(s->bus), DEVICE(pci_dev), &pvscsi_scsi_info);
210
/* override default SCSI bus hotplug-handler, with pvscsi's one */
211
qbus_set_hotplug_handler(BUS(&s->bus), OBJECT(s));
212
pvscsi_reset_state(s);
213
diff --git a/hw/usb/dev-storage-bot.c b/hw/usb/dev-storage-bot.c
214
index XXXXXXX..XXXXXXX 100644
215
--- a/hw/usb/dev-storage-bot.c
216
+++ b/hw/usb/dev-storage-bot.c
217
@@ -XXX,XX +XXX,XX @@ static void usb_msd_bot_realize(USBDevice *dev, Error **errp)
218
s->dev.auto_attach = 0;
219
}
220
221
- scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev),
222
- &usb_msd_scsi_info_bot, NULL);
223
+ scsi_bus_init(&s->bus, sizeof(s->bus), DEVICE(dev), &usb_msd_scsi_info_bot);
224
usb_msd_handle_reset(dev);
225
}
226
227
diff --git a/hw/usb/dev-storage-classic.c b/hw/usb/dev-storage-classic.c
228
index XXXXXXX..XXXXXXX 100644
229
--- a/hw/usb/dev-storage-classic.c
230
+++ b/hw/usb/dev-storage-classic.c
231
@@ -XXX,XX +XXX,XX @@ static void usb_msd_storage_realize(USBDevice *dev, Error **errp)
232
usb_desc_create_serial(dev);
233
usb_desc_init(dev);
234
dev->flags |= (1 << USB_DEV_FLAG_IS_SCSI_STORAGE);
235
- scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev),
236
- &usb_msd_scsi_info_storage, NULL);
237
+ scsi_bus_init(&s->bus, sizeof(s->bus), DEVICE(dev),
238
+ &usb_msd_scsi_info_storage);
239
scsi_dev = scsi_bus_legacy_add_drive(&s->bus, blk, 0, !!s->removable,
240
s->conf.bootindex, s->conf.share_rw,
241
s->conf.rerror, s->conf.werror,
242
diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c
243
index XXXXXXX..XXXXXXX 100644
244
--- a/hw/usb/dev-uas.c
245
+++ b/hw/usb/dev-uas.c
246
@@ -XXX,XX +XXX,XX @@ static void usb_uas_realize(USBDevice *dev, Error **errp)
247
uas->status_bh = qemu_bh_new(usb_uas_send_status_bh, uas);
248
249
dev->flags |= (1 << USB_DEV_FLAG_IS_SCSI_STORAGE);
250
- scsi_bus_new(&uas->bus, sizeof(uas->bus), DEVICE(dev),
251
- &usb_uas_scsi_info, NULL);
252
+ scsi_bus_init(&uas->bus, sizeof(uas->bus), DEVICE(dev), &usb_uas_scsi_info);
253
}
254
255
static const VMStateDescription vmstate_usb_uas = {
256
--
112
--
257
2.20.1
113
2.20.1
258
114
259
115
diff view generated by jsdifflib
1
From: Xuzhou Cheng <xuzhou.cheng@windriver.com>
1
From: Roman Bolshakov <r.bolshakov@yadro.com>
2
2
3
The Linux spi-imx driver does not work on QEMU. The reason is that the
3
ui/cocoa.m:1188:44: warning: 'openFile:' is deprecated: first deprecated in macOS 11.0 - Use -[NSWorkspace openURL:] instead.
4
state of m25p80 loops in STATE_READING_DATA state after receiving
4
[-Wdeprecated-declarations]
5
RDSR command, the new command is ignored. Before sending a new command,
5
if ([[NSWorkspace sharedWorkspace] openFile: full_file_path] == YES) {
6
CS line should be pulled high to make the state of m25p80 back to IDLE.
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
^
7
11
8
Currently the SPI flash CS line is connected to the SPI controller, but
12
Signed-off-by: Roman Bolshakov <r.bolshakov@yadro.com>
9
on the real board, it's connected to GPIO3_19. This matches the ecspi1
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
device node in the board dts.
14
Message-id: 20210102150718.47618-1-r.bolshakov@yadro.com
11
12
ecspi1 node in imx6qdl-sabrelite.dtsi:
13
&ecspi1 {
14
cs-gpios = <&gpio3 19 GPIO_ACTIVE_LOW>;
15
pinctrl-names = "default";
16
pinctrl-0 = <&pinctrl_ecspi1>;
17
status = "okay";
18
19
flash: m25p80@0 {
20
compatible = "sst,sst25vf016b", "jedec,spi-nor";
21
spi-max-frequency = <20000000>;
22
reg = <0>;
23
};
24
};
25
26
Should connect the SSI_GPIO_CS to GPIO3_19 when adding a spi-nor to
27
spi1 on sabrelite machine.
28
29
Verified this patch on Linux v5.14.
30
31
Logs:
32
# echo "01234567899876543210" > test
33
# mtd_debug erase /dev/mtd0 0x0 0x1000
34
Erased 4096 bytes from address 0x00000000 in flash
35
# mtd_debug write /dev/mtdblock0 0x0 20 test
36
Copied 20 bytes from test to address 0x00000000 in flash
37
# mtd_debug read /dev/mtdblock0 0x0 20 test_out
38
Copied 20 bytes from address 0x00000000 in flash to test_out
39
# cat test_out
40
01234567899876543210#
41
42
Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
43
Reported-by: Guenter Roeck <linux@roeck-us.net>
44
Reviewed-by: Bin Meng <bin.meng@windriver.com>
45
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
46
Message-id: 20210927142825.491-1-xchengl.cn@gmail.com
47
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
48
---
16
---
49
hw/arm/sabrelite.c | 2 +-
17
ui/cocoa.m | 5 ++++-
50
1 file changed, 1 insertion(+), 1 deletion(-)
18
1 file changed, 4 insertions(+), 1 deletion(-)
51
19
52
diff --git a/hw/arm/sabrelite.c b/hw/arm/sabrelite.c
20
diff --git a/ui/cocoa.m b/ui/cocoa.m
53
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
54
--- a/hw/arm/sabrelite.c
22
--- a/ui/cocoa.m
55
+++ b/hw/arm/sabrelite.c
23
+++ b/ui/cocoa.m
56
@@ -XXX,XX +XXX,XX @@ static void sabrelite_init(MachineState *machine)
24
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
57
qdev_realize_and_unref(flash_dev, BUS(spi_bus), &error_fatal);
25
/* Where to look for local files */
58
26
NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"docs/"};
59
cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0);
27
NSString *full_file_path;
60
- sysbus_connect_irq(SYS_BUS_DEVICE(spi_dev), 1, cs_line);
28
+ NSURL *full_file_url;
61
+ qdev_connect_gpio_out(DEVICE(&s->gpio[2]), 19, cs_line);
29
62
}
30
/* iterate thru the possible paths until the file is found */
31
int index;
32
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
33
full_file_path = [full_file_path stringByDeletingLastPathComponent];
34
full_file_path = [NSString stringWithFormat: @"%@/%@%@", full_file_path,
35
path_array[index], filename];
36
- if ([[NSWorkspace sharedWorkspace] openFile: full_file_path] == YES) {
37
+ full_file_url = [NSURL fileURLWithPath: full_file_path
38
+ isDirectory: false];
39
+ if ([[NSWorkspace sharedWorkspace] openURL: full_file_url] == YES) {
40
return;
63
}
41
}
64
}
42
}
65
--
43
--
66
2.20.1
44
2.20.1
67
45
68
46
diff view generated by jsdifflib