1
Arm queue; some of the simpler stuff, things other have reviewed (thanks!), etc.
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
5
thanks
3
-- PMM
6
-- PMM
4
7
5
The following changes since commit 5d2f557b47dfbf8f23277a5bdd8473d4607c681a:
8
The following changes since commit b3f846c59d8405bb87c551187721fc92ff2f1b92:
6
9
7
Merge remote-tracking branch 'remotes/kraxel/tags/vga-20200605-pull-request' into staging (2020-06-05 13:53:05 +0100)
10
Merge remote-tracking branch 'remotes/huth-gitlab/tags/pull-request-2021-01-11v2' into staging (2021-01-11 15:15:35 +0000)
8
11
9
are available in the Git repository at:
12
are available in the Git repository at:
10
13
11
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200605
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210112
12
15
13
for you to fetch changes up to 2c35a39eda0b16c2ed85c94cec204bf5efb97812:
16
for you to fetch changes up to 19d131395ccaf503db21dadd8257e6dc9fc1d7de:
14
17
15
target/arm: Convert Neon one-register-and-immediate insns to decodetree (2020-06-05 17:23:10 +0100)
18
ui/cocoa: Fix openFile: deprecation on Big Sur (2021-01-12 11:38:37 +0000)
16
19
17
----------------------------------------------------------------
20
----------------------------------------------------------------
18
target-arm queue:
21
target-arm queue:
19
hw/ssi/imx_spi: Handle tx burst lengths other than 8 correctly
22
* arm: Support emulation of ARMv8.4-TTST extension
20
hw/input/pxa2xx_keypad: Replace hw_error() by qemu_log_mask()
23
* arm: Update cpu.h ID register field definitions
21
hw/arm/pxa2xx: Replace printf() call by qemu_log_mask()
24
* arm: Fix breakage of XScale instruction emulation
22
target/arm: Convert crypto insns to gvec
25
* hw/net/lan9118: Fix RX Status FIFO PEEK value
23
hw/adc/stm32f2xx_adc: Correct memory region size and access size
26
* npcm7xx: Add ADC and PWM emulation
24
tests/acceptance: Add a boot test for the xlnx-versal-virt machine
27
* ui/cocoa: Make "open docs" help menu entry work again when binary
25
docs/system: Document Aspeed boards
28
is run from the build tree
26
raspi: Add model of the USB controller
29
* ui/cocoa: Fix openFile: deprecation on Big Sur
27
target/arm: Convert 2-reg-and-shift and 1-reg-imm Neon insns to decodetree
30
* docs: Add qemu-storage-daemon(1) manpage to meson.build
31
* docs: Build and install all the docs in a single manual
28
32
29
----------------------------------------------------------------
33
----------------------------------------------------------------
30
Cédric Le Goater (1):
34
Hao Wu (6):
31
docs/system: Document Aspeed boards
35
hw/misc: Add clock converter in NPCM7XX CLK module
36
hw/timer: Refactor NPCM7XX Timer to use CLK clock
37
hw/adc: Add an ADC module for NPCM7XX
38
hw/misc: Add a PWM module for NPCM7XX
39
hw/misc: Add QTest for NPCM7XX PWM Module
40
hw/*: Use type casting for SysBusDevice in NPCM7XX
32
41
33
Eden Mikitas (2):
42
Leif Lindholm (6):
34
hw/ssi/imx_spi: changed while statement to prevent underflow
43
target/arm: fix typo in cpu.h ID_AA64PFR1 field name
35
hw/ssi/imx_spi: Removed unnecessary cast of rx data received from slave
44
target/arm: make ARMCPU.clidr 64-bit
45
target/arm: make ARMCPU.ctr 64-bit
46
target/arm: add descriptions of CLIDR_EL1, CCSIDR_EL1, CTR_EL0 to cpu.h
47
target/arm: add aarch64 ID register fields to cpu.h
48
target/arm: add aarch32 ID register fields to cpu.h
36
49
37
Paul Zimmerman (7):
50
Peter Maydell (5):
38
raspi: add BCM2835 SOC MPHI emulation
51
docs: Add qemu-storage-daemon(1) manpage to meson.build
39
dwc-hsotg (dwc2) USB host controller register definitions
52
docs: Build and install all the docs in a single manual
40
dwc-hsotg (dwc2) USB host controller state definitions
53
target/arm: Don't decode insns in the XScale/iWMMXt space as cp insns
41
dwc-hsotg (dwc2) USB host controller emulation
54
hw/net/lan9118: Fix RX Status FIFO PEEK value
42
usb: add short-packet handling to usb-storage driver
55
hw/net/lan9118: Add symbolic constants for register offsets
43
wire in the dwc-hsotg (dwc2) USB host controller emulation
44
raspi2 acceptance test: add test for dwc-hsotg (dwc2) USB host
45
56
46
Peter Maydell (9):
57
Roman Bolshakov (2):
47
target/arm: Convert Neon VSHL and VSLI 2-reg-shift insn to decodetree
58
ui/cocoa: Update path to docs in build tree
48
target/arm: Convert Neon VSHR 2-reg-shift insns to decodetree
59
ui/cocoa: Fix openFile: deprecation on Big Sur
49
target/arm: Convert Neon VSRA, VSRI, VRSHR, VRSRA 2-reg-shift insns to decodetree
50
target/arm: Convert VQSHLU, VQSHL 2-reg-shift insns to decodetree
51
target/arm: Convert Neon narrowing shifts with op==8 to decodetree
52
target/arm: Convert Neon narrowing shifts with op==9 to decodetree
53
target/arm: Convert Neon VSHLL, VMOVL to decodetree
54
target/arm: Convert VCVT fixed-point ops to decodetree
55
target/arm: Convert Neon one-register-and-immediate insns to decodetree
56
60
57
Philippe Mathieu-Daudé (3):
61
Rémi Denis-Courmont (2):
58
hw/input/pxa2xx_keypad: Replace hw_error() by qemu_log_mask()
62
target/arm: ARMv8.4-TTST extension
59
hw/arm/pxa2xx: Replace printf() call by qemu_log_mask()
63
target/arm: enable Small Translation tables in max CPU
60
hw/adc/stm32f2xx_adc: Correct memory region size and access size
61
64
62
Richard Henderson (6):
65
docs/conf.py | 46 ++-
63
target/arm: Convert aes and sm4 to gvec helpers
66
docs/devel/conf.py | 15 -
64
target/arm: Convert rax1 to gvec helpers
67
docs/index.html.in | 17 -
65
target/arm: Convert sha512 and sm3 to gvec helpers
68
docs/interop/conf.py | 28 --
66
target/arm: Convert sha1 and sha256 to gvec helpers
69
docs/meson.build | 65 ++--
67
target/arm: Split helper_crypto_sha1_3reg
70
docs/specs/conf.py | 16 -
68
target/arm: Split helper_crypto_sm3tt
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
69
122
70
Thomas Huth (1):
71
tests/acceptance: Add a boot test for the xlnx-versal-virt machine
72
73
docs/system/arm/aspeed.rst | 85 ++
74
docs/system/target-arm.rst | 1 +
75
hw/usb/hcd-dwc2.h | 190 +++++
76
include/hw/arm/bcm2835_peripherals.h | 5 +-
77
include/hw/misc/bcm2835_mphi.h | 44 +
78
include/hw/usb/dwc2-regs.h | 899 ++++++++++++++++++++
79
target/arm/helper.h | 45 +-
80
target/arm/translate-a64.h | 3 +
81
target/arm/vec_internal.h | 33 +
82
target/arm/neon-dp.decode | 214 ++++-
83
hw/adc/stm32f2xx_adc.c | 4 +-
84
hw/arm/bcm2835_peripherals.c | 38 +-
85
hw/arm/pxa2xx.c | 66 +-
86
hw/input/pxa2xx_keypad.c | 10 +-
87
hw/misc/bcm2835_mphi.c | 191 +++++
88
hw/ssi/imx_spi.c | 4 +-
89
hw/usb/dev-storage.c | 15 +-
90
hw/usb/hcd-dwc2.c | 1417 ++++++++++++++++++++++++++++++++
91
target/arm/crypto_helper.c | 267 ++++--
92
target/arm/translate-a64.c | 198 ++---
93
target/arm/translate-neon.inc.c | 796 ++++++++++++++----
94
target/arm/translate.c | 539 +-----------
95
target/arm/vec_helper.c | 12 +-
96
hw/misc/Makefile.objs | 1 +
97
hw/usb/Kconfig | 5 +
98
hw/usb/Makefile.objs | 1 +
99
hw/usb/trace-events | 50 ++
100
tests/acceptance/boot_linux_console.py | 35 +-
101
28 files changed, 4258 insertions(+), 910 deletions(-)
102
create mode 100644 docs/system/arm/aspeed.rst
103
create mode 100644 hw/usb/hcd-dwc2.h
104
create mode 100644 include/hw/misc/bcm2835_mphi.h
105
create mode 100644 include/hw/usb/dwc2-regs.h
106
create mode 100644 target/arm/vec_internal.h
107
create mode 100644 hw/misc/bcm2835_mphi.c
108
create mode 100644 hw/usb/hcd-dwc2.c
109
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
2
2
3
Rather than passing an opcode to a helper, fully decode the
3
This adds for the Small Translation tables extension in AArch64 state.
4
operation at translate time. Use clear_tail_16 to zap the
5
balance of the SVE register with the AdvSIMD write.
6
4
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
8
Message-id: 20200514212831.31248-6-richard.henderson@linaro.org
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
8
---
12
target/arm/helper.h | 5 +-
9
target/arm/cpu.h | 5 +++++
13
target/arm/neon-dp.decode | 6 +-
10
target/arm/helper.c | 15 +++++++++++++--
14
target/arm/crypto_helper.c | 99 +++++++++++++++++++++------------
11
2 files changed, 18 insertions(+), 2 deletions(-)
15
target/arm/translate-a64.c | 29 ++++------
16
target/arm/translate-neon.inc.c | 46 ++++-----------
17
5 files changed, 93 insertions(+), 92 deletions(-)
18
12
19
diff --git a/target/arm/helper.h b/target/arm/helper.h
13
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/helper.h
15
--- a/target/arm/cpu.h
22
+++ b/target/arm/helper.h
16
+++ b/target/arm/cpu.h
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(neon_qzip32, TCG_CALL_NO_RWG, void, ptr, ptr)
17
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_uao(const ARMISARegisters *id)
24
DEF_HELPER_FLAGS_4(crypto_aese, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
18
return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0;
25
DEF_HELPER_FLAGS_3(crypto_aesmc, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
26
27
-DEF_HELPER_FLAGS_4(crypto_sha1_3reg, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
28
+DEF_HELPER_FLAGS_4(crypto_sha1su0, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
29
+DEF_HELPER_FLAGS_4(crypto_sha1c, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
30
+DEF_HELPER_FLAGS_4(crypto_sha1p, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
31
+DEF_HELPER_FLAGS_4(crypto_sha1m, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
32
DEF_HELPER_FLAGS_3(crypto_sha1h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
33
DEF_HELPER_FLAGS_3(crypto_sha1su1, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
34
35
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/neon-dp.decode
38
+++ b/target/arm/neon-dp.decode
39
@@ -XXX,XX +XXX,XX @@ VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same
40
@3same_crypto .... .... .... .... .... .... .... .... \
41
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp size=0 q=1
42
43
-SHA1_3s 1111 001 0 0 . optype:2 .... .... 1100 . 1 . 0 .... \
44
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
45
+SHA1C_3s 1111 001 0 0 . 00 .... .... 1100 . 1 . 0 .... @3same_crypto
46
+SHA1P_3s 1111 001 0 0 . 01 .... .... 1100 . 1 . 0 .... @3same_crypto
47
+SHA1M_3s 1111 001 0 0 . 10 .... .... 1100 . 1 . 0 .... @3same_crypto
48
+SHA1SU0_3s 1111 001 0 0 . 11 .... .... 1100 . 1 . 0 .... @3same_crypto
49
SHA256H_3s 1111 001 1 0 . 00 .... .... 1100 . 1 . 0 .... @3same_crypto
50
SHA256H2_3s 1111 001 1 0 . 01 .... .... 1100 . 1 . 0 .... @3same_crypto
51
SHA256SU1_3s 1111 001 1 0 . 10 .... .... 1100 . 1 . 0 .... @3same_crypto
52
diff --git a/target/arm/crypto_helper.c b/target/arm/crypto_helper.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/crypto_helper.c
55
+++ b/target/arm/crypto_helper.c
56
@@ -XXX,XX +XXX,XX @@ union CRYPTO_STATE {
57
};
58
59
#ifdef HOST_WORDS_BIGENDIAN
60
-#define CR_ST_BYTE(state, i) (state.bytes[(15 - (i)) ^ 8])
61
-#define CR_ST_WORD(state, i) (state.words[(3 - (i)) ^ 2])
62
+#define CR_ST_BYTE(state, i) ((state).bytes[(15 - (i)) ^ 8])
63
+#define CR_ST_WORD(state, i) ((state).words[(3 - (i)) ^ 2])
64
#else
65
-#define CR_ST_BYTE(state, i) (state.bytes[i])
66
-#define CR_ST_WORD(state, i) (state.words[i])
67
+#define CR_ST_BYTE(state, i) ((state).bytes[i])
68
+#define CR_ST_WORD(state, i) ((state).words[i])
69
#endif
70
71
/*
72
@@ -XXX,XX +XXX,XX @@ static uint32_t maj(uint32_t x, uint32_t y, uint32_t z)
73
return (x & y) | ((x | y) & z);
74
}
19
}
75
20
76
-void HELPER(crypto_sha1_3reg)(void *vd, void *vn, void *vm, uint32_t op)
21
+static inline bool isar_feature_aa64_st(const ARMISARegisters *id)
77
+void HELPER(crypto_sha1su0)(void *vd, void *vn, void *vm, uint32_t desc)
78
+{
22
+{
79
+ uint64_t *d = vd, *n = vn, *m = vm;
23
+ return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, ST) != 0;
80
+ uint64_t d0, d1;
81
+
82
+ d0 = d[1] ^ d[0] ^ m[0];
83
+ d1 = n[0] ^ d[1] ^ m[1];
84
+ d[0] = d0;
85
+ d[1] = d1;
86
+
87
+ clear_tail_16(vd, desc);
88
+}
24
+}
89
+
25
+
90
+static inline void crypto_sha1_3reg(uint64_t *rd, uint64_t *rn,
26
static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
91
+ uint64_t *rm, uint32_t desc,
92
+ uint32_t (*fn)(union CRYPTO_STATE *d))
93
{
27
{
94
- uint64_t *rd = vd;
28
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;
95
- uint64_t *rn = vn;
29
diff --git a/target/arm/helper.c b/target/arm/helper.c
96
- uint64_t *rm = vm;
30
index XXXXXXX..XXXXXXX 100644
97
union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
31
--- a/target/arm/helper.c
98
union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
32
+++ b/target/arm/helper.c
99
union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
33
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
100
+ int i;
34
{
101
35
uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
102
- if (op == 3) { /* sha1su0 */
36
bool epd, hpd, using16k, using64k;
103
- d.l[0] ^= d.l[1] ^ m.l[0];
37
- int select, tsz, tbi;
104
- d.l[1] ^= n.l[0] ^ m.l[1];
38
+ int select, tsz, tbi, max_tsz;
105
- } else {
39
106
- int i;
40
if (!regime_has_2_ranges(mmu_idx)) {
107
+ for (i = 0; i < 4; i++) {
41
select = 0;
108
+ uint32_t t = fn(&d);
42
@@ -XXX,XX +XXX,XX @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
109
43
hpd = extract64(tcr, 42, 1);
110
- for (i = 0; i < 4; i++) {
44
}
111
- uint32_t t;
112
+ t += rol32(CR_ST_WORD(d, 0), 5) + CR_ST_WORD(n, 0)
113
+ + CR_ST_WORD(m, i);
114
115
- switch (op) {
116
- case 0: /* sha1c */
117
- t = cho(CR_ST_WORD(d, 1), CR_ST_WORD(d, 2), CR_ST_WORD(d, 3));
118
- break;
119
- case 1: /* sha1p */
120
- t = par(CR_ST_WORD(d, 1), CR_ST_WORD(d, 2), CR_ST_WORD(d, 3));
121
- break;
122
- case 2: /* sha1m */
123
- t = maj(CR_ST_WORD(d, 1), CR_ST_WORD(d, 2), CR_ST_WORD(d, 3));
124
- break;
125
- default:
126
- g_assert_not_reached();
127
- }
128
- t += rol32(CR_ST_WORD(d, 0), 5) + CR_ST_WORD(n, 0)
129
- + CR_ST_WORD(m, i);
130
-
131
- CR_ST_WORD(n, 0) = CR_ST_WORD(d, 3);
132
- CR_ST_WORD(d, 3) = CR_ST_WORD(d, 2);
133
- CR_ST_WORD(d, 2) = ror32(CR_ST_WORD(d, 1), 2);
134
- CR_ST_WORD(d, 1) = CR_ST_WORD(d, 0);
135
- CR_ST_WORD(d, 0) = t;
136
- }
137
+ CR_ST_WORD(n, 0) = CR_ST_WORD(d, 3);
138
+ CR_ST_WORD(d, 3) = CR_ST_WORD(d, 2);
139
+ CR_ST_WORD(d, 2) = ror32(CR_ST_WORD(d, 1), 2);
140
+ CR_ST_WORD(d, 1) = CR_ST_WORD(d, 0);
141
+ CR_ST_WORD(d, 0) = t;
142
}
45
}
143
rd[0] = d.l[0];
46
- tsz = MIN(tsz, 39); /* TODO: ARMv8.4-TTST */
144
rd[1] = d.l[1];
145
+
47
+
146
+ clear_tail_16(rd, desc);
48
+ if (cpu_isar_feature(aa64_st, env_archcpu(env))) {
147
+}
49
+ max_tsz = 48 - using64k;
50
+ } else {
51
+ max_tsz = 39;
52
+ }
148
+
53
+
149
+static uint32_t do_sha1c(union CRYPTO_STATE *d)
54
+ tsz = MIN(tsz, max_tsz);
150
+{
55
tsz = MAX(tsz, 16); /* TODO: ARMv8.2-LVA */
151
+ return cho(CR_ST_WORD(*d, 1), CR_ST_WORD(*d, 2), CR_ST_WORD(*d, 3));
56
152
+}
57
/* Present TBI as a composite with TBID. */
58
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
59
if (!aarch64 || stride == 9) {
60
/* AArch32 or 4KB pages */
61
startlevel = 2 - sl0;
153
+
62
+
154
+void HELPER(crypto_sha1c)(void *vd, void *vn, void *vm, uint32_t desc)
63
+ if (cpu_isar_feature(aa64_st, cpu)) {
155
+{
64
+ startlevel &= 3;
156
+ crypto_sha1_3reg(vd, vn, vm, desc, do_sha1c);
65
+ }
157
+}
66
} else {
158
+
67
/* 16KB or 64KB pages */
159
+static uint32_t do_sha1p(union CRYPTO_STATE *d)
68
startlevel = 3 - sl0;
160
+{
161
+ return par(CR_ST_WORD(*d, 1), CR_ST_WORD(*d, 2), CR_ST_WORD(*d, 3));
162
+}
163
+
164
+void HELPER(crypto_sha1p)(void *vd, void *vn, void *vm, uint32_t desc)
165
+{
166
+ crypto_sha1_3reg(vd, vn, vm, desc, do_sha1p);
167
+}
168
+
169
+static uint32_t do_sha1m(union CRYPTO_STATE *d)
170
+{
171
+ return maj(CR_ST_WORD(*d, 1), CR_ST_WORD(*d, 2), CR_ST_WORD(*d, 3));
172
+}
173
+
174
+void HELPER(crypto_sha1m)(void *vd, void *vn, void *vm, uint32_t desc)
175
+{
176
+ crypto_sha1_3reg(vd, vn, vm, desc, do_sha1m);
177
}
178
179
void HELPER(crypto_sha1h)(void *vd, void *vm, uint32_t desc)
180
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
181
index XXXXXXX..XXXXXXX 100644
182
--- a/target/arm/translate-a64.c
183
+++ b/target/arm/translate-a64.c
184
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
185
186
switch (opcode) {
187
case 0: /* SHA1C */
188
+ genfn = gen_helper_crypto_sha1c;
189
+ feature = dc_isar_feature(aa64_sha1, s);
190
+ break;
191
case 1: /* SHA1P */
192
+ genfn = gen_helper_crypto_sha1p;
193
+ feature = dc_isar_feature(aa64_sha1, s);
194
+ break;
195
case 2: /* SHA1M */
196
+ genfn = gen_helper_crypto_sha1m;
197
+ feature = dc_isar_feature(aa64_sha1, s);
198
+ break;
199
case 3: /* SHA1SU0 */
200
- genfn = NULL;
201
+ genfn = gen_helper_crypto_sha1su0;
202
feature = dc_isar_feature(aa64_sha1, s);
203
break;
204
case 4: /* SHA256H */
205
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
206
if (!fp_access_check(s)) {
207
return;
208
}
209
-
210
- if (genfn) {
211
- gen_gvec_op3_ool(s, true, rd, rn, rm, 0, genfn);
212
- } else {
213
- TCGv_i32 tcg_opcode = tcg_const_i32(opcode);
214
- TCGv_ptr tcg_rd_ptr = vec_full_reg_ptr(s, rd);
215
- TCGv_ptr tcg_rn_ptr = vec_full_reg_ptr(s, rn);
216
- TCGv_ptr tcg_rm_ptr = vec_full_reg_ptr(s, rm);
217
-
218
- gen_helper_crypto_sha1_3reg(tcg_rd_ptr, tcg_rn_ptr,
219
- tcg_rm_ptr, tcg_opcode);
220
-
221
- tcg_temp_free_i32(tcg_opcode);
222
- tcg_temp_free_ptr(tcg_rd_ptr);
223
- tcg_temp_free_ptr(tcg_rn_ptr);
224
- tcg_temp_free_ptr(tcg_rm_ptr);
225
- }
226
+ gen_gvec_op3_ool(s, true, rd, rn, rm, 0, genfn);
227
}
228
229
/* Crypto two-reg SHA
230
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
231
index XXXXXXX..XXXXXXX 100644
232
--- a/target/arm/translate-neon.inc.c
233
+++ b/target/arm/translate-neon.inc.c
234
@@ -XXX,XX +XXX,XX @@ static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a)
235
DO_VQRDMLAH(VQRDMLAH, gen_gvec_sqrdmlah_qc)
236
DO_VQRDMLAH(VQRDMLSH, gen_gvec_sqrdmlsh_qc)
237
238
-static bool trans_SHA1_3s(DisasContext *s, arg_SHA1_3s *a)
239
-{
240
- TCGv_ptr ptr1, ptr2, ptr3;
241
- TCGv_i32 tmp;
242
-
243
- if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
244
- !dc_isar_feature(aa32_sha1, s)) {
245
- return false;
246
+#define DO_SHA1(NAME, FUNC) \
247
+ WRAP_OOL_FN(gen_##NAME##_3s, FUNC) \
248
+ static bool trans_##NAME##_3s(DisasContext *s, arg_3same *a) \
249
+ { \
250
+ if (!dc_isar_feature(aa32_sha1, s)) { \
251
+ return false; \
252
+ } \
253
+ return do_3same(s, a, gen_##NAME##_3s); \
254
}
255
256
- /* UNDEF accesses to D16-D31 if they don't exist. */
257
- if (!dc_isar_feature(aa32_simd_r32, s) &&
258
- ((a->vd | a->vn | a->vm) & 0x10)) {
259
- return false;
260
- }
261
-
262
- if ((a->vn | a->vm | a->vd) & 1) {
263
- return false;
264
- }
265
-
266
- if (!vfp_access_check(s)) {
267
- return true;
268
- }
269
-
270
- ptr1 = vfp_reg_ptr(true, a->vd);
271
- ptr2 = vfp_reg_ptr(true, a->vn);
272
- ptr3 = vfp_reg_ptr(true, a->vm);
273
- tmp = tcg_const_i32(a->optype);
274
- gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp);
275
- tcg_temp_free_i32(tmp);
276
- tcg_temp_free_ptr(ptr1);
277
- tcg_temp_free_ptr(ptr2);
278
- tcg_temp_free_ptr(ptr3);
279
-
280
- return true;
281
-}
282
+DO_SHA1(SHA1C, gen_helper_crypto_sha1c)
283
+DO_SHA1(SHA1P, gen_helper_crypto_sha1p)
284
+DO_SHA1(SHA1M, gen_helper_crypto_sha1m)
285
+DO_SHA1(SHA1SU0, gen_helper_crypto_sha1su0)
286
287
#define DO_SHA2(NAME, FUNC) \
288
WRAP_OOL_FN(gen_##NAME##_3s, FUNC) \
289
--
69
--
290
2.20.1
70
2.20.1
291
71
292
72
diff view generated by jsdifflib
1
From: Paul Zimmerman <pauldzim@gmail.com>
1
From: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
2
2
3
Add a check for functional dwc-hsotg (dwc2) USB host emulation to
3
Signed-off-by: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
4
the Raspi 2 acceptance test
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
6
Signed-off-by: Paul Zimmerman <pauldzim@gmail.com>
7
Reviewed-by: Philippe Mathieu-Daude <f4bug@amsat.org>
8
Message-id: 20200520235349.21215-8-pauldzim@gmail.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
6
---
11
tests/acceptance/boot_linux_console.py | 9 +++++++--
7
target/arm/cpu64.c | 1 +
12
1 file changed, 7 insertions(+), 2 deletions(-)
8
1 file changed, 1 insertion(+)
13
9
14
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
10
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
15
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/acceptance/boot_linux_console.py
12
--- a/target/arm/cpu64.c
17
+++ b/tests/acceptance/boot_linux_console.py
13
+++ b/target/arm/cpu64.c
18
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(LinuxKernelTest):
14
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
19
15
t = cpu->isar.id_aa64mmfr2;
20
self.vm.set_console()
16
t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1);
21
kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
17
t = FIELD_DP64(t, ID_AA64MMFR2, CNP, 1); /* TTCNP */
22
- serial_kernel_cmdline[uart_id])
18
+ t = FIELD_DP64(t, ID_AA64MMFR2, ST, 1); /* TTST */
23
+ serial_kernel_cmdline[uart_id] +
19
cpu->isar.id_aa64mmfr2 = t;
24
+ ' root=/dev/mmcblk0p2 rootwait ' +
20
25
+ 'dwc_otg.fiq_fsm_enable=0')
21
/* Replicate the same data to the 32-bit id registers. */
26
self.vm.add_args('-kernel', kernel_path,
27
'-dtb', dtb_path,
28
- '-append', kernel_command_line)
29
+ '-append', kernel_command_line,
30
+ '-device', 'usb-kbd')
31
self.vm.launch()
32
console_pattern = 'Kernel command line: %s' % kernel_command_line
33
self.wait_for_console_pattern(console_pattern)
34
+ console_pattern = 'Product: QEMU USB Keyboard'
35
+ self.wait_for_console_pattern(console_pattern)
36
37
def test_arm_raspi2_uart0(self):
38
"""
39
--
22
--
40
2.20.1
23
2.20.1
41
24
42
25
diff view generated by jsdifflib
1
From: Paul Zimmerman <pauldzim@gmail.com>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
Wire the dwc-hsotg (dwc2) emulation into Qemu
3
SBSS -> SSBS
4
4
5
Signed-off-by: Paul Zimmerman <pauldzim@gmail.com>
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
6
Reviewed-by: Philippe Mathieu-Daude <f4bug@amsat.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20200520235349.21215-7-pauldzim@gmail.com
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
---
11
---
10
include/hw/arm/bcm2835_peripherals.h | 3 ++-
12
target/arm/cpu.h | 2 +-
11
hw/arm/bcm2835_peripherals.c | 21 ++++++++++++++++++++-
13
1 file changed, 1 insertion(+), 1 deletion(-)
12
2 files changed, 22 insertions(+), 2 deletions(-)
13
14
14
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/arm/bcm2835_peripherals.h
17
--- a/target/arm/cpu.h
17
+++ b/include/hw/arm/bcm2835_peripherals.h
18
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64PFR0, RAS, 28, 4)
19
#include "hw/sd/bcm2835_sdhost.h"
20
FIELD(ID_AA64PFR0, SVE, 32, 4)
20
#include "hw/gpio/bcm2835_gpio.h"
21
21
#include "hw/timer/bcm2835_systmr.h"
22
FIELD(ID_AA64PFR1, BT, 0, 4)
22
+#include "hw/usb/hcd-dwc2.h"
23
-FIELD(ID_AA64PFR1, SBSS, 4, 4)
23
#include "hw/misc/unimp.h"
24
+FIELD(ID_AA64PFR1, SSBS, 4, 4)
24
25
FIELD(ID_AA64PFR1, MTE, 8, 4)
25
#define TYPE_BCM2835_PERIPHERALS "bcm2835-peripherals"
26
FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4)
26
@@ -XXX,XX +XXX,XX @@ typedef struct BCM2835PeripheralState {
27
UnimplementedDeviceState ave0;
28
UnimplementedDeviceState bscsl;
29
UnimplementedDeviceState smi;
30
- UnimplementedDeviceState dwc2;
31
+ DWC2State dwc2;
32
UnimplementedDeviceState sdramc;
33
} BCM2835PeripheralState;
34
35
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/arm/bcm2835_peripherals.c
38
+++ b/hw/arm/bcm2835_peripherals.c
39
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
40
/* Mphi */
41
sysbus_init_child_obj(obj, "mphi", &s->mphi, sizeof(s->mphi),
42
TYPE_BCM2835_MPHI);
43
+
44
+ /* DWC2 */
45
+ sysbus_init_child_obj(obj, "dwc2", &s->dwc2, sizeof(s->dwc2),
46
+ TYPE_DWC2_USB);
47
+
48
+ object_property_add_const_link(OBJECT(&s->dwc2), "dma-mr",
49
+ OBJECT(&s->gpu_bus_mr));
50
}
51
52
static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
53
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
54
qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
55
INTERRUPT_HOSTPORT));
56
57
+ /* DWC2 */
58
+ object_property_set_bool(OBJECT(&s->dwc2), true, "realized", &err);
59
+ if (err) {
60
+ error_propagate(errp, err);
61
+ return;
62
+ }
63
+
64
+ memory_region_add_subregion(&s->peri_mr, USB_OTG_OFFSET,
65
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dwc2), 0));
66
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->dwc2), 0,
67
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
68
+ INTERRUPT_USB));
69
+
70
create_unimp(s, &s->armtmr, "bcm2835-sp804", ARMCTRL_TIMER0_1_OFFSET, 0x40);
71
create_unimp(s, &s->cprman, "bcm2835-cprman", CPRMAN_OFFSET, 0x1000);
72
create_unimp(s, &s->a2w, "bcm2835-a2w", A2W_OFFSET, 0x1000);
73
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
74
create_unimp(s, &s->otp, "bcm2835-otp", OTP_OFFSET, 0x80);
75
create_unimp(s, &s->dbus, "bcm2835-dbus", DBUS_OFFSET, 0x8000);
76
create_unimp(s, &s->ave0, "bcm2835-ave0", AVE0_OFFSET, 0x8000);
77
- create_unimp(s, &s->dwc2, "dwc-usb2", USB_OTG_OFFSET, 0x1000);
78
create_unimp(s, &s->sdramc, "bcm2835-sdramc", SDRAMC_OFFSET, 0x100);
79
}
80
27
81
--
28
--
82
2.20.1
29
2.20.1
83
30
84
31
diff view generated by jsdifflib
1
From: Eden Mikitas <e.mikitas@gmail.com>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
The while statement in question only checked if tx_burst is not 0.
3
The AArch64 view of CLIDR_EL1 extends the ICB field to include also bit
4
tx_burst is a signed int, which is assigned the value put by the
4
32, as well as adding a Ttype<n> field when FEAT_MTE is implemented.
5
guest driver in ECSPI_CONREG. The burst length can be anywhere
5
Extend the clidr field to be able to hold this context.
6
between 1 and 4096, and since tx_burst is always decremented by 8
7
it could possibly underflow, causing an infinite loop.
8
6
9
Signed-off-by: Eden Mikitas <e.mikitas@gmail.com>
7
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
11
Message-id: 20210108185154.8108-3-leif@nuviainc.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
---
13
hw/ssi/imx_spi.c | 2 +-
14
target/arm/cpu.h | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
16
diff --git a/hw/ssi/imx_spi.c b/hw/ssi/imx_spi.c
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/ssi/imx_spi.c
19
--- a/target/arm/cpu.h
19
+++ b/hw/ssi/imx_spi.c
20
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ static void imx_spi_flush_txfifo(IMXSPIState *s)
21
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
21
22
uint32_t id_afr0;
22
rx = 0;
23
uint64_t id_aa64afr0;
23
24
uint64_t id_aa64afr1;
24
- while (tx_burst) {
25
- uint32_t clidr;
25
+ while (tx_burst > 0) {
26
+ uint64_t clidr;
26
uint8_t byte = tx & 0xff;
27
uint64_t mp_affinity; /* MP ID without feature bits */
27
28
/* The elements of this array are the CCSIDR values for each cache,
28
DPRINTF("writing 0x%02x\n", (uint32_t)byte);
29
* in the order L1DCache, L1ICache, L2DCache, L2ICache, etc.
29
--
30
--
30
2.20.1
31
2.20.1
31
32
32
33
diff view generated by jsdifflib
1
From: Eden Mikitas <e.mikitas@gmail.com>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
When inserting the value retrieved (rx) from the spi slave, rx is pushed to
3
When FEAT_MTE is implemented, the AArch64 view of CTR_EL0 adds the
4
rx_fifo after being cast to uint8_t. rx_fifo is a fifo32, and the rx
4
TminLine field in bits [37:32].
5
register the driver uses is also 32 bit. This zeroes the 24 most
5
Extend the ctr field to be able to hold this context.
6
significant bits of rx. This proved problematic with devices that expect to
7
use the whole 32 bits of the rx register.
8
6
9
Signed-off-by: Eden Mikitas <e.mikitas@gmail.com>
7
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Hao Wu <wuhaotsh@google.com>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
11
Message-id: 20210108185154.8108-4-leif@nuviainc.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
---
13
hw/ssi/imx_spi.c | 2 +-
14
target/arm/cpu.h | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
16
diff --git a/hw/ssi/imx_spi.c b/hw/ssi/imx_spi.c
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/ssi/imx_spi.c
19
--- a/target/arm/cpu.h
19
+++ b/hw/ssi/imx_spi.c
20
+++ b/target/arm/cpu.h
20
@@ -XXX,XX +XXX,XX @@ static void imx_spi_flush_txfifo(IMXSPIState *s)
21
@@ -XXX,XX +XXX,XX @@ struct ARMCPU {
21
if (fifo32_is_full(&s->rx_fifo)) {
22
uint64_t midr;
22
s->regs[ECSPI_STATREG] |= ECSPI_STATREG_RO;
23
uint32_t revidr;
23
} else {
24
uint32_t reset_fpsid;
24
- fifo32_push(&s->rx_fifo, (uint8_t)rx);
25
- uint32_t ctr;
25
+ fifo32_push(&s->rx_fifo, rx);
26
+ uint64_t ctr;
26
}
27
uint32_t reset_sctlr;
27
28
uint64_t pmceid0;
28
if (s->burst_length <= 0) {
29
uint64_t pmceid1;
29
--
30
--
30
2.20.1
31
2.20.1
31
32
32
33
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
hw_error() calls exit(). This a bit overkill when we can log
4
the accesses as unimplemented or guest error.
5
6
When fuzzing the devices, we don't want the whole process to
7
exit. Replace some hw_error() calls by qemu_log_mask()
8
(missed in commit 5a0001ec7e).
9
10
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 20200525114123.21317-2-f4bug@amsat.org
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
hw/input/pxa2xx_keypad.c | 10 +++++++---
16
1 file changed, 7 insertions(+), 3 deletions(-)
17
18
diff --git a/hw/input/pxa2xx_keypad.c b/hw/input/pxa2xx_keypad.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/input/pxa2xx_keypad.c
21
+++ b/hw/input/pxa2xx_keypad.c
22
@@ -XXX,XX +XXX,XX @@
23
*/
24
25
#include "qemu/osdep.h"
26
-#include "hw/hw.h"
27
+#include "qemu/log.h"
28
#include "hw/irq.h"
29
#include "migration/vmstate.h"
30
#include "hw/arm/pxa.h"
31
@@ -XXX,XX +XXX,XX @@ static uint64_t pxa2xx_keypad_read(void *opaque, hwaddr offset,
32
return s->kpkdi;
33
break;
34
default:
35
- hw_error("%s: Bad offset " REG_FMT "\n", __func__, offset);
36
+ qemu_log_mask(LOG_GUEST_ERROR,
37
+ "%s: Bad read offset 0x%"HWADDR_PRIx"\n",
38
+ __func__, offset);
39
}
40
41
return 0;
42
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_keypad_write(void *opaque, hwaddr offset,
43
break;
44
45
default:
46
- hw_error("%s: Bad offset " REG_FMT "\n", __func__, offset);
47
+ qemu_log_mask(LOG_GUEST_ERROR,
48
+ "%s: Bad write offset 0x%"HWADDR_PRIx"\n",
49
+ __func__, offset);
50
}
51
}
52
53
--
54
2.20.1
55
56
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
Replace printf() calls by qemu_log_mask(), which is disabled
4
by default. This avoid flooding the terminal when fuzzing the
5
device.
6
7
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20200525114123.21317-3-f4bug@amsat.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
hw/arm/pxa2xx.c | 66 ++++++++++++++++++++++++++++++++++++-------------
13
1 file changed, 49 insertions(+), 17 deletions(-)
14
15
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/pxa2xx.c
18
+++ b/hw/arm/pxa2xx.c
19
@@ -XXX,XX +XXX,XX @@
20
#include "sysemu/blockdev.h"
21
#include "sysemu/qtest.h"
22
#include "qemu/cutils.h"
23
+#include "qemu/log.h"
24
25
static struct {
26
hwaddr io_base;
27
@@ -XXX,XX +XXX,XX @@ static uint64_t pxa2xx_pm_read(void *opaque, hwaddr addr,
28
return s->pm_regs[addr >> 2];
29
default:
30
fail:
31
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
32
+ qemu_log_mask(LOG_GUEST_ERROR,
33
+ "%s: Bad read offset 0x%"HWADDR_PRIx"\n",
34
+ __func__, addr);
35
break;
36
}
37
return 0;
38
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_pm_write(void *opaque, hwaddr addr,
39
s->pm_regs[addr >> 2] = value;
40
break;
41
}
42
-
43
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
44
+ qemu_log_mask(LOG_GUEST_ERROR,
45
+ "%s: Bad write offset 0x%"HWADDR_PRIx"\n",
46
+ __func__, addr);
47
break;
48
}
49
}
50
@@ -XXX,XX +XXX,XX @@ static uint64_t pxa2xx_cm_read(void *opaque, hwaddr addr,
51
return s->cm_regs[CCCR >> 2] | (3 << 28);
52
53
default:
54
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
55
+ qemu_log_mask(LOG_GUEST_ERROR,
56
+ "%s: Bad read offset 0x%"HWADDR_PRIx"\n",
57
+ __func__, addr);
58
break;
59
}
60
return 0;
61
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_cm_write(void *opaque, hwaddr addr,
62
break;
63
64
default:
65
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
66
+ qemu_log_mask(LOG_GUEST_ERROR,
67
+ "%s: Bad write offset 0x%"HWADDR_PRIx"\n",
68
+ __func__, addr);
69
break;
70
}
71
}
72
@@ -XXX,XX +XXX,XX @@ static uint64_t pxa2xx_mm_read(void *opaque, hwaddr addr,
73
return s->mm_regs[addr >> 2];
74
/* fall through */
75
default:
76
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
77
+ qemu_log_mask(LOG_GUEST_ERROR,
78
+ "%s: Bad read offset 0x%"HWADDR_PRIx"\n",
79
+ __func__, addr);
80
break;
81
}
82
return 0;
83
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_mm_write(void *opaque, hwaddr addr,
84
}
85
86
default:
87
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
88
+ qemu_log_mask(LOG_GUEST_ERROR,
89
+ "%s: Bad write offset 0x%"HWADDR_PRIx"\n",
90
+ __func__, addr);
91
break;
92
}
93
}
94
@@ -XXX,XX +XXX,XX @@ static uint64_t pxa2xx_ssp_read(void *opaque, hwaddr addr,
95
case SSACD:
96
return s->ssacd;
97
default:
98
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
99
+ qemu_log_mask(LOG_GUEST_ERROR,
100
+ "%s: Bad read offset 0x%"HWADDR_PRIx"\n",
101
+ __func__, addr);
102
break;
103
}
104
return 0;
105
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_ssp_write(void *opaque, hwaddr addr,
106
break;
107
108
default:
109
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
110
+ qemu_log_mask(LOG_GUEST_ERROR,
111
+ "%s: Bad write offset 0x%"HWADDR_PRIx"\n",
112
+ __func__, addr);
113
break;
114
}
115
}
116
@@ -XXX,XX +XXX,XX @@ static uint64_t pxa2xx_rtc_read(void *opaque, hwaddr addr,
117
else
118
return s->last_swcr;
119
default:
120
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
121
+ qemu_log_mask(LOG_GUEST_ERROR,
122
+ "%s: Bad read offset 0x%"HWADDR_PRIx"\n",
123
+ __func__, addr);
124
break;
125
}
126
return 0;
127
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_rtc_write(void *opaque, hwaddr addr,
128
break;
129
130
default:
131
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
132
+ qemu_log_mask(LOG_GUEST_ERROR,
133
+ "%s: Bad write offset 0x%"HWADDR_PRIx"\n",
134
+ __func__, addr);
135
}
136
}
137
138
@@ -XXX,XX +XXX,XX @@ static uint64_t pxa2xx_i2c_read(void *opaque, hwaddr addr,
139
s->ibmr = 0;
140
return s->ibmr;
141
default:
142
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
143
+ qemu_log_mask(LOG_GUEST_ERROR,
144
+ "%s: Bad read offset 0x%"HWADDR_PRIx"\n",
145
+ __func__, addr);
146
break;
147
}
148
return 0;
149
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_i2c_write(void *opaque, hwaddr addr,
150
break;
151
152
default:
153
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
154
+ qemu_log_mask(LOG_GUEST_ERROR,
155
+ "%s: Bad write offset 0x%"HWADDR_PRIx"\n",
156
+ __func__, addr);
157
}
158
}
159
160
@@ -XXX,XX +XXX,XX @@ static uint64_t pxa2xx_i2s_read(void *opaque, hwaddr addr,
161
}
162
return 0;
163
default:
164
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
165
+ qemu_log_mask(LOG_GUEST_ERROR,
166
+ "%s: Bad read offset 0x%"HWADDR_PRIx"\n",
167
+ __func__, addr);
168
break;
169
}
170
return 0;
171
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_i2s_write(void *opaque, hwaddr addr,
172
}
173
break;
174
default:
175
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
176
+ qemu_log_mask(LOG_GUEST_ERROR,
177
+ "%s: Bad write offset 0x%"HWADDR_PRIx"\n",
178
+ __func__, addr);
179
}
180
}
181
182
@@ -XXX,XX +XXX,XX @@ static uint64_t pxa2xx_fir_read(void *opaque, hwaddr addr,
183
case ICFOR:
184
return s->rx_len;
185
default:
186
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
187
+ qemu_log_mask(LOG_GUEST_ERROR,
188
+ "%s: Bad read offset 0x%"HWADDR_PRIx"\n",
189
+ __func__, addr);
190
break;
191
}
192
return 0;
193
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_fir_write(void *opaque, hwaddr addr,
194
case ICFOR:
195
break;
196
default:
197
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
198
+ qemu_log_mask(LOG_GUEST_ERROR,
199
+ "%s: Bad write offset 0x%"HWADDR_PRIx"\n",
200
+ __func__, addr);
201
}
202
}
203
204
--
205
2.20.1
206
207
diff view generated by jsdifflib
Deleted patch
1
From: Richard Henderson <richard.henderson@linaro.org>
2
1
3
With this conversion, we will be able to use the same helpers
4
with sve. In particular, pass 3 vector parameters for the
5
3-operand operations; for advsimd the destination register
6
is also an input.
7
8
This also fixes a bug in which we failed to clear the high bits
9
of the SVE register after an AdvSIMD operation.
10
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20200514212831.31248-2-richard.henderson@linaro.org
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
target/arm/helper.h | 6 ++--
17
target/arm/vec_internal.h | 33 +++++++++++++++++
18
target/arm/crypto_helper.c | 72 +++++++++++++++++++++++++++-----------
19
target/arm/translate-a64.c | 55 ++++++++++++++++++-----------
20
target/arm/translate.c | 27 +++++++-------
21
target/arm/vec_helper.c | 12 +------
22
6 files changed, 138 insertions(+), 67 deletions(-)
23
create mode 100644 target/arm/vec_internal.h
24
25
diff --git a/target/arm/helper.h b/target/arm/helper.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/helper.h
28
+++ b/target/arm/helper.h
29
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(neon_qzip8, TCG_CALL_NO_RWG, void, ptr, ptr)
30
DEF_HELPER_FLAGS_2(neon_qzip16, TCG_CALL_NO_RWG, void, ptr, ptr)
31
DEF_HELPER_FLAGS_2(neon_qzip32, TCG_CALL_NO_RWG, void, ptr, ptr)
32
33
-DEF_HELPER_FLAGS_3(crypto_aese, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
34
+DEF_HELPER_FLAGS_4(crypto_aese, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
35
DEF_HELPER_FLAGS_3(crypto_aesmc, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
36
37
DEF_HELPER_FLAGS_4(crypto_sha1_3reg, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
38
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(crypto_sm3tt, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32, i32)
39
DEF_HELPER_FLAGS_3(crypto_sm3partw1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
40
DEF_HELPER_FLAGS_3(crypto_sm3partw2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
41
42
-DEF_HELPER_FLAGS_2(crypto_sm4e, TCG_CALL_NO_RWG, void, ptr, ptr)
43
-DEF_HELPER_FLAGS_3(crypto_sm4ekey, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
44
+DEF_HELPER_FLAGS_4(crypto_sm4e, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
45
+DEF_HELPER_FLAGS_4(crypto_sm4ekey, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
46
47
DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
48
DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
49
diff --git a/target/arm/vec_internal.h b/target/arm/vec_internal.h
50
new file mode 100644
51
index XXXXXXX..XXXXXXX
52
--- /dev/null
53
+++ b/target/arm/vec_internal.h
54
@@ -XXX,XX +XXX,XX @@
55
+/*
56
+ * ARM AdvSIMD / SVE Vector Helpers
57
+ *
58
+ * Copyright (c) 2020 Linaro
59
+ *
60
+ * This library is free software; you can redistribute it and/or
61
+ * modify it under the terms of the GNU Lesser General Public
62
+ * License as published by the Free Software Foundation; either
63
+ * version 2 of the License, or (at your option) any later version.
64
+ *
65
+ * This library is distributed in the hope that it will be useful,
66
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
67
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
68
+ * Lesser General Public License for more details.
69
+ *
70
+ * You should have received a copy of the GNU Lesser General Public
71
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
72
+ */
73
+
74
+#ifndef TARGET_ARM_VEC_INTERNALS_H
75
+#define TARGET_ARM_VEC_INTERNALS_H
76
+
77
+static inline void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz)
78
+{
79
+ uint64_t *d = vd + opr_sz;
80
+ uintptr_t i;
81
+
82
+ for (i = opr_sz; i < max_sz; i += 8) {
83
+ *d++ = 0;
84
+ }
85
+}
86
+
87
+#endif /* TARGET_ARM_VEC_INTERNALS_H */
88
diff --git a/target/arm/crypto_helper.c b/target/arm/crypto_helper.c
89
index XXXXXXX..XXXXXXX 100644
90
--- a/target/arm/crypto_helper.c
91
+++ b/target/arm/crypto_helper.c
92
@@ -XXX,XX +XXX,XX @@
93
94
#include "cpu.h"
95
#include "exec/helper-proto.h"
96
+#include "tcg/tcg-gvec-desc.h"
97
#include "crypto/aes.h"
98
+#include "vec_internal.h"
99
100
union CRYPTO_STATE {
101
uint8_t bytes[16];
102
@@ -XXX,XX +XXX,XX @@ union CRYPTO_STATE {
103
#define CR_ST_WORD(state, i) (state.words[i])
104
#endif
105
106
-void HELPER(crypto_aese)(void *vd, void *vm, uint32_t decrypt)
107
+static void do_crypto_aese(uint64_t *rd, uint64_t *rn,
108
+ uint64_t *rm, bool decrypt)
109
{
110
static uint8_t const * const sbox[2] = { AES_sbox, AES_isbox };
111
static uint8_t const * const shift[2] = { AES_shifts, AES_ishifts };
112
- uint64_t *rd = vd;
113
- uint64_t *rm = vm;
114
union CRYPTO_STATE rk = { .l = { rm[0], rm[1] } };
115
- union CRYPTO_STATE st = { .l = { rd[0], rd[1] } };
116
+ union CRYPTO_STATE st = { .l = { rn[0], rn[1] } };
117
int i;
118
119
- assert(decrypt < 2);
120
-
121
/* xor state vector with round key */
122
rk.l[0] ^= st.l[0];
123
rk.l[1] ^= st.l[1];
124
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_aese)(void *vd, void *vm, uint32_t decrypt)
125
rd[1] = st.l[1];
126
}
127
128
-void HELPER(crypto_aesmc)(void *vd, void *vm, uint32_t decrypt)
129
+void HELPER(crypto_aese)(void *vd, void *vn, void *vm, uint32_t desc)
130
+{
131
+ intptr_t i, opr_sz = simd_oprsz(desc);
132
+ bool decrypt = simd_data(desc);
133
+
134
+ for (i = 0; i < opr_sz; i += 16) {
135
+ do_crypto_aese(vd + i, vn + i, vm + i, decrypt);
136
+ }
137
+ clear_tail(vd, opr_sz, simd_maxsz(desc));
138
+}
139
+
140
+static void do_crypto_aesmc(uint64_t *rd, uint64_t *rm, bool decrypt)
141
{
142
static uint32_t const mc[][256] = { {
143
/* MixColumns lookup table */
144
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_aesmc)(void *vd, void *vm, uint32_t decrypt)
145
0xbe805d9f, 0xb58d5491, 0xa89a4f83, 0xa397468d,
146
} };
147
148
- uint64_t *rd = vd;
149
- uint64_t *rm = vm;
150
union CRYPTO_STATE st = { .l = { rm[0], rm[1] } };
151
int i;
152
153
- assert(decrypt < 2);
154
-
155
for (i = 0; i < 16; i += 4) {
156
CR_ST_WORD(st, i >> 2) =
157
mc[decrypt][CR_ST_BYTE(st, i)] ^
158
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_aesmc)(void *vd, void *vm, uint32_t decrypt)
159
rd[1] = st.l[1];
160
}
161
162
+void HELPER(crypto_aesmc)(void *vd, void *vm, uint32_t desc)
163
+{
164
+ intptr_t i, opr_sz = simd_oprsz(desc);
165
+ bool decrypt = simd_data(desc);
166
+
167
+ for (i = 0; i < opr_sz; i += 16) {
168
+ do_crypto_aesmc(vd + i, vm + i, decrypt);
169
+ }
170
+ clear_tail(vd, opr_sz, simd_maxsz(desc));
171
+}
172
+
173
/*
174
* SHA-1 logical functions
175
*/
176
@@ -XXX,XX +XXX,XX @@ static uint8_t const sm4_sbox[] = {
177
0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48,
178
};
179
180
-void HELPER(crypto_sm4e)(void *vd, void *vn)
181
+static void do_crypto_sm4e(uint64_t *rd, uint64_t *rn, uint64_t *rm)
182
{
183
- uint64_t *rd = vd;
184
- uint64_t *rn = vn;
185
- union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
186
- union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
187
+ union CRYPTO_STATE d = { .l = { rn[0], rn[1] } };
188
+ union CRYPTO_STATE n = { .l = { rm[0], rm[1] } };
189
uint32_t t, i;
190
191
for (i = 0; i < 4; i++) {
192
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sm4e)(void *vd, void *vn)
193
rd[1] = d.l[1];
194
}
195
196
-void HELPER(crypto_sm4ekey)(void *vd, void *vn, void* vm)
197
+void HELPER(crypto_sm4e)(void *vd, void *vn, void *vm, uint32_t desc)
198
+{
199
+ intptr_t i, opr_sz = simd_oprsz(desc);
200
+
201
+ for (i = 0; i < opr_sz; i += 16) {
202
+ do_crypto_sm4e(vd + i, vn + i, vm + i);
203
+ }
204
+ clear_tail(vd, opr_sz, simd_maxsz(desc));
205
+}
206
+
207
+static void do_crypto_sm4ekey(uint64_t *rd, uint64_t *rn, uint64_t *rm)
208
{
209
- uint64_t *rd = vd;
210
- uint64_t *rn = vn;
211
- uint64_t *rm = vm;
212
union CRYPTO_STATE d;
213
union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
214
union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
215
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sm4ekey)(void *vd, void *vn, void* vm)
216
rd[0] = d.l[0];
217
rd[1] = d.l[1];
218
}
219
+
220
+void HELPER(crypto_sm4ekey)(void *vd, void *vn, void* vm, uint32_t desc)
221
+{
222
+ intptr_t i, opr_sz = simd_oprsz(desc);
223
+
224
+ for (i = 0; i < opr_sz; i += 16) {
225
+ do_crypto_sm4ekey(vd + i, vn + i, vm + i);
226
+ }
227
+ clear_tail(vd, opr_sz, simd_maxsz(desc));
228
+}
229
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
230
index XXXXXXX..XXXXXXX 100644
231
--- a/target/arm/translate-a64.c
232
+++ b/target/arm/translate-a64.c
233
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_fn4(DisasContext *s, bool is_q, int rd, int rn, int rm,
234
is_q ? 16 : 8, vec_full_reg_size(s));
235
}
236
237
+/* Expand a 2-operand operation using an out-of-line helper. */
238
+static void gen_gvec_op2_ool(DisasContext *s, bool is_q, int rd,
239
+ int rn, int data, gen_helper_gvec_2 *fn)
240
+{
241
+ tcg_gen_gvec_2_ool(vec_full_reg_offset(s, rd),
242
+ vec_full_reg_offset(s, rn),
243
+ is_q ? 16 : 8, vec_full_reg_size(s), data, fn);
244
+}
245
+
246
/* Expand a 3-operand operation using an out-of-line helper. */
247
static void gen_gvec_op3_ool(DisasContext *s, bool is_q, int rd,
248
int rn, int rm, int data, gen_helper_gvec_3 *fn)
249
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_aes(DisasContext *s, uint32_t insn)
250
int rn = extract32(insn, 5, 5);
251
int rd = extract32(insn, 0, 5);
252
int decrypt;
253
- TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
254
- TCGv_i32 tcg_decrypt;
255
- CryptoThreeOpIntFn *genfn;
256
+ gen_helper_gvec_2 *genfn2 = NULL;
257
+ gen_helper_gvec_3 *genfn3 = NULL;
258
259
if (!dc_isar_feature(aa64_aes, s) || size != 0) {
260
unallocated_encoding(s);
261
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_aes(DisasContext *s, uint32_t insn)
262
switch (opcode) {
263
case 0x4: /* AESE */
264
decrypt = 0;
265
- genfn = gen_helper_crypto_aese;
266
+ genfn3 = gen_helper_crypto_aese;
267
break;
268
case 0x6: /* AESMC */
269
decrypt = 0;
270
- genfn = gen_helper_crypto_aesmc;
271
+ genfn2 = gen_helper_crypto_aesmc;
272
break;
273
case 0x5: /* AESD */
274
decrypt = 1;
275
- genfn = gen_helper_crypto_aese;
276
+ genfn3 = gen_helper_crypto_aese;
277
break;
278
case 0x7: /* AESIMC */
279
decrypt = 1;
280
- genfn = gen_helper_crypto_aesmc;
281
+ genfn2 = gen_helper_crypto_aesmc;
282
break;
283
default:
284
unallocated_encoding(s);
285
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_aes(DisasContext *s, uint32_t insn)
286
if (!fp_access_check(s)) {
287
return;
288
}
289
-
290
- tcg_rd_ptr = vec_full_reg_ptr(s, rd);
291
- tcg_rn_ptr = vec_full_reg_ptr(s, rn);
292
- tcg_decrypt = tcg_const_i32(decrypt);
293
-
294
- genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_decrypt);
295
-
296
- tcg_temp_free_ptr(tcg_rd_ptr);
297
- tcg_temp_free_ptr(tcg_rn_ptr);
298
- tcg_temp_free_i32(tcg_decrypt);
299
+ if (genfn2) {
300
+ gen_gvec_op2_ool(s, true, rd, rn, decrypt, genfn2);
301
+ } else {
302
+ gen_gvec_op3_ool(s, true, rd, rd, rn, decrypt, genfn3);
303
+ }
304
}
305
306
/* Crypto three-reg SHA
307
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
308
int rn = extract32(insn, 5, 5);
309
int rd = extract32(insn, 0, 5);
310
bool feature;
311
- CryptoThreeOpFn *genfn;
312
+ CryptoThreeOpFn *genfn = NULL;
313
+ gen_helper_gvec_3 *oolfn = NULL;
314
315
if (o == 0) {
316
switch (opcode) {
317
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
318
break;
319
case 2: /* SM4EKEY */
320
feature = dc_isar_feature(aa64_sm4, s);
321
- genfn = gen_helper_crypto_sm4ekey;
322
+ oolfn = gen_helper_crypto_sm4ekey;
323
break;
324
default:
325
unallocated_encoding(s);
326
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
327
return;
328
}
329
330
+ if (oolfn) {
331
+ gen_gvec_op3_ool(s, true, rd, rn, rm, 0, oolfn);
332
+ return;
333
+ }
334
+
335
if (genfn) {
336
TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
337
338
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha512(DisasContext *s, uint32_t insn)
339
TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
340
bool feature;
341
CryptoTwoOpFn *genfn;
342
+ gen_helper_gvec_3 *oolfn = NULL;
343
344
switch (opcode) {
345
case 0: /* SHA512SU0 */
346
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha512(DisasContext *s, uint32_t insn)
347
break;
348
case 1: /* SM4E */
349
feature = dc_isar_feature(aa64_sm4, s);
350
- genfn = gen_helper_crypto_sm4e;
351
+ oolfn = gen_helper_crypto_sm4e;
352
break;
353
default:
354
unallocated_encoding(s);
355
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha512(DisasContext *s, uint32_t insn)
356
return;
357
}
358
359
+ if (oolfn) {
360
+ gen_gvec_op3_ool(s, true, rd, rd, rn, 0, oolfn);
361
+ return;
362
+ }
363
+
364
tcg_rd_ptr = vec_full_reg_ptr(s, rd);
365
tcg_rn_ptr = vec_full_reg_ptr(s, rn);
366
367
diff --git a/target/arm/translate.c b/target/arm/translate.c
368
index XXXXXXX..XXXXXXX 100644
369
--- a/target/arm/translate.c
370
+++ b/target/arm/translate.c
371
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
372
if (!dc_isar_feature(aa32_aes, s) || ((rm | rd) & 1)) {
373
return 1;
374
}
375
- ptr1 = vfp_reg_ptr(true, rd);
376
- ptr2 = vfp_reg_ptr(true, rm);
377
-
378
- /* Bit 6 is the lowest opcode bit; it distinguishes between
379
- * encryption (AESE/AESMC) and decryption (AESD/AESIMC)
380
- */
381
- tmp3 = tcg_const_i32(extract32(insn, 6, 1));
382
-
383
+ /*
384
+ * Bit 6 is the lowest opcode bit; it distinguishes
385
+ * between encryption (AESE/AESMC) and decryption
386
+ * (AESD/AESIMC).
387
+ */
388
if (op == NEON_2RM_AESE) {
389
- gen_helper_crypto_aese(ptr1, ptr2, tmp3);
390
+ tcg_gen_gvec_3_ool(vfp_reg_offset(true, rd),
391
+ vfp_reg_offset(true, rd),
392
+ vfp_reg_offset(true, rm),
393
+ 16, 16, extract32(insn, 6, 1),
394
+ gen_helper_crypto_aese);
395
} else {
396
- gen_helper_crypto_aesmc(ptr1, ptr2, tmp3);
397
+ tcg_gen_gvec_2_ool(vfp_reg_offset(true, rd),
398
+ vfp_reg_offset(true, rm),
399
+ 16, 16, extract32(insn, 6, 1),
400
+ gen_helper_crypto_aesmc);
401
}
402
- tcg_temp_free_ptr(ptr1);
403
- tcg_temp_free_ptr(ptr2);
404
- tcg_temp_free_i32(tmp3);
405
break;
406
case NEON_2RM_SHA1H:
407
if (!dc_isar_feature(aa32_sha1, s) || ((rm | rd) & 1)) {
408
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
409
index XXXXXXX..XXXXXXX 100644
410
--- a/target/arm/vec_helper.c
411
+++ b/target/arm/vec_helper.c
412
@@ -XXX,XX +XXX,XX @@
413
#include "exec/helper-proto.h"
414
#include "tcg/tcg-gvec-desc.h"
415
#include "fpu/softfloat.h"
416
-
417
+#include "vec_internal.h"
418
419
/* Note that vector data is stored in host-endian 64-bit chunks,
420
so addressing units smaller than that needs a host-endian fixup. */
421
@@ -XXX,XX +XXX,XX @@
422
#define H4(x) (x)
423
#endif
424
425
-static void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz)
426
-{
427
- uint64_t *d = vd + opr_sz;
428
- uintptr_t i;
429
-
430
- for (i = opr_sz; i < max_sz; i += 8) {
431
- *d++ = 0;
432
- }
433
-}
434
-
435
/* Signed saturating rounding doubling multiply-accumulate high half, 16-bit */
436
static int16_t inl_qrdmlah_s16(int16_t src1, int16_t src2,
437
int16_t src3, uint32_t *sat)
438
--
439
2.20.1
440
441
diff view generated by jsdifflib
1
From: Paul Zimmerman <pauldzim@gmail.com>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
The dwc-hsotg (dwc2) USB host depends on a short packet to
3
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
4
indicate the end of an IN transfer. The usb-storage driver
4
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
5
currently doesn't provide this, so fix it.
5
Message-id: 20210108185154.8108-5-leif@nuviainc.com
6
7
I have tested this change rather extensively using a PC
8
emulation with xhci, ehci, and uhci controllers, and have
9
not observed any regressions.
10
11
Signed-off-by: Paul Zimmerman <pauldzim@gmail.com>
12
Message-id: 20200520235349.21215-6-pauldzim@gmail.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
7
---
15
hw/usb/dev-storage.c | 15 ++++++++++++++-
8
target/arm/cpu.h | 31 +++++++++++++++++++++++++++++++
16
1 file changed, 14 insertions(+), 1 deletion(-)
9
1 file changed, 31 insertions(+)
17
10
18
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
11
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
19
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/usb/dev-storage.c
13
--- a/target/arm/cpu.h
21
+++ b/hw/usb/dev-storage.c
14
+++ b/target/arm/cpu.h
22
@@ -XXX,XX +XXX,XX @@ static void usb_msd_copy_data(MSDState *s, USBPacket *p)
15
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_FPCCR, ASPEN, 31, 1)
23
usb_packet_copy(p, scsi_req_get_buf(s->req) + s->scsi_off, len);
16
/*
24
s->scsi_len -= len;
17
* System register ID fields.
25
s->scsi_off += len;
18
*/
26
+ if (len > s->data_len) {
19
+FIELD(CLIDR_EL1, CTYPE1, 0, 3)
27
+ len = s->data_len;
20
+FIELD(CLIDR_EL1, CTYPE2, 3, 3)
28
+ }
21
+FIELD(CLIDR_EL1, CTYPE3, 6, 3)
29
s->data_len -= len;
22
+FIELD(CLIDR_EL1, CTYPE4, 9, 3)
30
if (s->scsi_len == 0 || s->data_len == 0) {
23
+FIELD(CLIDR_EL1, CTYPE5, 12, 3)
31
scsi_req_continue(s->req);
24
+FIELD(CLIDR_EL1, CTYPE6, 15, 3)
32
@@ -XXX,XX +XXX,XX @@ static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, size_t r
25
+FIELD(CLIDR_EL1, CTYPE7, 18, 3)
33
if (s->data_len) {
26
+FIELD(CLIDR_EL1, LOUIS, 21, 3)
34
int len = (p->iov.size - p->actual_length);
27
+FIELD(CLIDR_EL1, LOC, 24, 3)
35
usb_packet_skip(p, len);
28
+FIELD(CLIDR_EL1, LOUU, 27, 3)
36
+ if (len > s->data_len) {
29
+FIELD(CLIDR_EL1, ICB, 30, 3)
37
+ len = s->data_len;
30
+
38
+ }
31
+/* When FEAT_CCIDX is implemented */
39
s->data_len -= len;
32
+FIELD(CCSIDR_EL1, CCIDX_LINESIZE, 0, 3)
40
}
33
+FIELD(CCSIDR_EL1, CCIDX_ASSOCIATIVITY, 3, 21)
41
if (s->data_len == 0) {
34
+FIELD(CCSIDR_EL1, CCIDX_NUMSETS, 32, 24)
42
@@ -XXX,XX +XXX,XX @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p)
35
+
43
int len = p->iov.size - p->actual_length;
36
+/* When FEAT_CCIDX is not implemented */
44
if (len) {
37
+FIELD(CCSIDR_EL1, LINESIZE, 0, 3)
45
usb_packet_skip(p, len);
38
+FIELD(CCSIDR_EL1, ASSOCIATIVITY, 3, 10)
46
+ if (len > s->data_len) {
39
+FIELD(CCSIDR_EL1, NUMSETS, 13, 15)
47
+ len = s->data_len;
40
+
48
+ }
41
+FIELD(CTR_EL0, IMINLINE, 0, 4)
49
s->data_len -= len;
42
+FIELD(CTR_EL0, L1IP, 14, 2)
50
if (s->data_len == 0) {
43
+FIELD(CTR_EL0, DMINLINE, 16, 4)
51
s->mode = USB_MSDM_CSW;
44
+FIELD(CTR_EL0, ERG, 20, 4)
52
@@ -XXX,XX +XXX,XX @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p)
45
+FIELD(CTR_EL0, CWG, 24, 4)
53
int len = p->iov.size - p->actual_length;
46
+FIELD(CTR_EL0, IDC, 28, 1)
54
if (len) {
47
+FIELD(CTR_EL0, DIC, 29, 1)
55
usb_packet_skip(p, len);
48
+FIELD(CTR_EL0, TMINLINE, 32, 6)
56
+ if (len > s->data_len) {
49
+
57
+ len = s->data_len;
50
FIELD(MIDR_EL1, REVISION, 0, 4)
58
+ }
51
FIELD(MIDR_EL1, PARTNUM, 4, 12)
59
s->data_len -= len;
52
FIELD(MIDR_EL1, ARCHITECTURE, 16, 4)
60
if (s->data_len == 0) {
61
s->mode = USB_MSDM_CSW;
62
}
63
}
64
}
65
- if (p->actual_length < p->iov.size) {
66
+ if (p->actual_length < p->iov.size && (p->short_not_ok ||
67
+ s->scsi_len >= p->ep->max_packet_size)) {
68
DPRINTF("Deferring packet %p [wait data-in]\n", p);
69
s->packet = p;
70
p->status = USB_RET_ASYNC;
71
--
53
--
72
2.20.1
54
2.20.1
73
55
74
56
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
As described by Edgar here:
3
Add entries present in ARM DDI 0487F.c (August 2020).
4
4
5
https://www.mail-archive.com/qemu-devel@nongnu.org/msg605124.html
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
6
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
we can use the Ubuntu kernel for testing the xlnx-versal-virt machine.
7
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
8
So let's add a boot test for this now.
8
Message-id: 20210108185154.8108-6-leif@nuviainc.com
9
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Signed-off-by: Thomas Huth <thuth@redhat.com>
13
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
14
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
15
Message-id: 20200525141237.15243-1-thuth@redhat.com
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
10
---
18
tests/acceptance/boot_linux_console.py | 26 ++++++++++++++++++++++++++
11
target/arm/cpu.h | 15 +++++++++++++++
19
1 file changed, 26 insertions(+)
12
1 file changed, 15 insertions(+)
20
13
21
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
22
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
23
--- a/tests/acceptance/boot_linux_console.py
16
--- a/target/arm/cpu.h
24
+++ b/tests/acceptance/boot_linux_console.py
17
+++ b/target/arm/cpu.h
25
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(LinuxKernelTest):
18
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64ISAR1, GPI, 28, 4)
26
console_pattern = 'Kernel command line: %s' % kernel_command_line
19
FIELD(ID_AA64ISAR1, FRINTTS, 32, 4)
27
self.wait_for_console_pattern(console_pattern)
20
FIELD(ID_AA64ISAR1, SB, 36, 4)
28
21
FIELD(ID_AA64ISAR1, SPECRES, 40, 4)
29
+ def test_aarch64_xlnx_versal_virt(self):
22
+FIELD(ID_AA64ISAR1, BF16, 44, 4)
30
+ """
23
+FIELD(ID_AA64ISAR1, DGH, 48, 4)
31
+ :avocado: tags=arch:aarch64
24
+FIELD(ID_AA64ISAR1, I8MM, 52, 4)
32
+ :avocado: tags=machine:xlnx-versal-virt
25
33
+ :avocado: tags=device:pl011
26
FIELD(ID_AA64PFR0, EL0, 0, 4)
34
+ :avocado: tags=device:arm_gicv3
27
FIELD(ID_AA64PFR0, EL1, 4, 4)
35
+ """
28
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64PFR0, ADVSIMD, 20, 4)
36
+ kernel_url = ('http://ports.ubuntu.com/ubuntu-ports/dists/'
29
FIELD(ID_AA64PFR0, GIC, 24, 4)
37
+ 'bionic-updates/main/installer-arm64/current/images/'
30
FIELD(ID_AA64PFR0, RAS, 28, 4)
38
+ 'netboot/ubuntu-installer/arm64/linux')
31
FIELD(ID_AA64PFR0, SVE, 32, 4)
39
+ kernel_hash = '5bfc54cf7ed8157d93f6e5b0241e727b6dc22c50'
32
+FIELD(ID_AA64PFR0, SEL2, 36, 4)
40
+ kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
33
+FIELD(ID_AA64PFR0, MPAM, 40, 4)
41
+
34
+FIELD(ID_AA64PFR0, AMU, 44, 4)
42
+ initrd_url = ('http://ports.ubuntu.com/ubuntu-ports/dists/'
35
+FIELD(ID_AA64PFR0, DIT, 48, 4)
43
+ 'bionic-updates/main/installer-arm64/current/images/'
36
+FIELD(ID_AA64PFR0, CSV2, 56, 4)
44
+ 'netboot/ubuntu-installer/arm64/initrd.gz')
37
+FIELD(ID_AA64PFR0, CSV3, 60, 4)
45
+ initrd_hash = 'd385d3e88d53e2004c5d43cbe668b458a094f772'
38
46
+ initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
39
FIELD(ID_AA64PFR1, BT, 0, 4)
47
+
40
FIELD(ID_AA64PFR1, SSBS, 4, 4)
48
+ self.vm.set_console()
41
FIELD(ID_AA64PFR1, MTE, 8, 4)
49
+ self.vm.add_args('-m', '2G',
42
FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4)
50
+ '-kernel', kernel_path,
43
+FIELD(ID_AA64PFR1, MPAM_FRAC, 16, 4)
51
+ '-initrd', initrd_path)
44
52
+ self.vm.launch()
45
FIELD(ID_AA64MMFR0, PARANGE, 0, 4)
53
+ self.wait_for_console_pattern('Checked W+X mappings: passed')
46
FIELD(ID_AA64MMFR0, ASIDBITS, 4, 4)
54
+
47
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64MMFR0, TGRAN16_2, 32, 4)
55
def test_arm_virt(self):
48
FIELD(ID_AA64MMFR0, TGRAN64_2, 36, 4)
56
"""
49
FIELD(ID_AA64MMFR0, TGRAN4_2, 40, 4)
57
:avocado: tags=arch:arm
50
FIELD(ID_AA64MMFR0, EXS, 44, 4)
51
+FIELD(ID_AA64MMFR0, FGT, 56, 4)
52
+FIELD(ID_AA64MMFR0, ECV, 60, 4)
53
54
FIELD(ID_AA64MMFR1, HAFDBS, 0, 4)
55
FIELD(ID_AA64MMFR1, VMIDBITS, 4, 4)
56
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64MMFR1, LO, 16, 4)
57
FIELD(ID_AA64MMFR1, PAN, 20, 4)
58
FIELD(ID_AA64MMFR1, SPECSEI, 24, 4)
59
FIELD(ID_AA64MMFR1, XNX, 28, 4)
60
+FIELD(ID_AA64MMFR1, TWED, 32, 4)
61
+FIELD(ID_AA64MMFR1, ETS, 36, 4)
62
63
FIELD(ID_AA64MMFR2, CNP, 0, 4)
64
FIELD(ID_AA64MMFR2, UAO, 4, 4)
65
@@ -XXX,XX +XXX,XX @@ FIELD(ID_AA64DFR0, CTX_CMPS, 28, 4)
66
FIELD(ID_AA64DFR0, PMSVER, 32, 4)
67
FIELD(ID_AA64DFR0, DOUBLELOCK, 36, 4)
68
FIELD(ID_AA64DFR0, TRACEFILT, 40, 4)
69
+FIELD(ID_AA64DFR0, MTPMU, 48, 4)
70
71
FIELD(ID_DFR0, COPDBG, 0, 4)
72
FIELD(ID_DFR0, COPSDBG, 4, 4)
58
--
73
--
59
2.20.1
74
2.20.1
60
75
61
76
diff view generated by jsdifflib
1
From: Paul Zimmerman <pauldzim@gmail.com>
1
From: Leif Lindholm <leif@nuviainc.com>
2
2
3
Import the dwc-hsotg (dwc2) register definitions file from the
3
Add entries present in ARM DDI 0487F.c (August 2020).
4
Linux kernel. This is a copy of drivers/usb/dwc2/hw.h from the
5
mainline Linux kernel, the only changes being to the header, and
6
two instances of 'u32' changed to 'uint32_t' to allow it to
7
compile. Checkpatch throws a boatload of errors due to the tab
8
indentation, but I would rather import it as-is than reformat it.
9
4
10
Signed-off-by: Paul Zimmerman <pauldzim@gmail.com>
5
Signed-off-by: Leif Lindholm <leif@nuviainc.com>
11
Message-id: 20200520235349.21215-3-pauldzim@gmail.com
12
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
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
10
---
15
include/hw/usb/dwc2-regs.h | 899 +++++++++++++++++++++++++++++++++++++
11
target/arm/cpu.h | 28 ++++++++++++++++++++++++++++
16
1 file changed, 899 insertions(+)
12
1 file changed, 28 insertions(+)
17
create mode 100644 include/hw/usb/dwc2-regs.h
18
13
19
diff --git a/include/hw/usb/dwc2-regs.h b/include/hw/usb/dwc2-regs.h
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
new file mode 100644
15
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX
16
--- a/target/arm/cpu.h
22
--- /dev/null
17
+++ b/target/arm/cpu.h
23
+++ b/include/hw/usb/dwc2-regs.h
18
@@ -XXX,XX +XXX,XX @@ FIELD(ID_ISAR6, DP, 4, 4)
24
@@ -XXX,XX +XXX,XX @@
19
FIELD(ID_ISAR6, FHM, 8, 4)
25
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
20
FIELD(ID_ISAR6, SB, 12, 4)
26
+/*
21
FIELD(ID_ISAR6, SPECRES, 16, 4)
27
+ * Imported from the Linux kernel file drivers/usb/dwc2/hw.h, commit
22
+FIELD(ID_ISAR6, BF16, 20, 4)
28
+ * a89bae709b3492b478480a2c9734e7e9393b279c ("usb: dwc2: Move
23
+FIELD(ID_ISAR6, I8MM, 24, 4)
29
+ * UTMI_PHY_DATA defines closer")
24
30
+ *
25
FIELD(ID_MMFR0, VMSA, 0, 4)
31
+ * hw.h - DesignWare HS OTG Controller hardware definitions
26
FIELD(ID_MMFR0, PMSA, 4, 4)
32
+ *
27
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR0, AUXREG, 20, 4)
33
+ * Copyright 2004-2013 Synopsys, Inc.
28
FIELD(ID_MMFR0, FCSE, 24, 4)
34
+ *
29
FIELD(ID_MMFR0, INNERSHR, 28, 4)
35
+ * Redistribution and use in source and binary forms, with or without
30
36
+ * modification, are permitted provided that the following conditions
31
+FIELD(ID_MMFR1, L1HVDVA, 0, 4)
37
+ * are met:
32
+FIELD(ID_MMFR1, L1UNIVA, 4, 4)
38
+ * 1. Redistributions of source code must retain the above copyright
33
+FIELD(ID_MMFR1, L1HVDSW, 8, 4)
39
+ * notice, this list of conditions, and the following disclaimer,
34
+FIELD(ID_MMFR1, L1UNISW, 12, 4)
40
+ * without modification.
35
+FIELD(ID_MMFR1, L1HVD, 16, 4)
41
+ * 2. Redistributions in binary form must reproduce the above copyright
36
+FIELD(ID_MMFR1, L1UNI, 20, 4)
42
+ * notice, this list of conditions and the following disclaimer in the
37
+FIELD(ID_MMFR1, L1TSTCLN, 24, 4)
43
+ * documentation and/or other materials provided with the distribution.
38
+FIELD(ID_MMFR1, BPRED, 28, 4)
44
+ * 3. The names of the above-listed copyright holders may not be used
45
+ * to endorse or promote products derived from this software without
46
+ * specific prior written permission.
47
+ *
48
+ * ALTERNATIVELY, this software may be distributed under the terms of the
49
+ * GNU General Public License ("GPL") as published by the Free Software
50
+ * Foundation; either version 2 of the License, or (at your option) any
51
+ * later version.
52
+ *
53
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
54
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
55
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
57
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
58
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
59
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
60
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
61
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
62
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
63
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64
+ */
65
+
39
+
66
+#ifndef __DWC2_HW_H__
40
+FIELD(ID_MMFR2, L1HVDFG, 0, 4)
67
+#define __DWC2_HW_H__
41
+FIELD(ID_MMFR2, L1HVDBG, 4, 4)
42
+FIELD(ID_MMFR2, L1HVDRNG, 8, 4)
43
+FIELD(ID_MMFR2, HVDTLB, 12, 4)
44
+FIELD(ID_MMFR2, UNITLB, 16, 4)
45
+FIELD(ID_MMFR2, MEMBARR, 20, 4)
46
+FIELD(ID_MMFR2, WFISTALL, 24, 4)
47
+FIELD(ID_MMFR2, HWACCFLG, 28, 4)
68
+
48
+
69
+#define HSOTG_REG(x)    (x)
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)
70
+
57
+
71
+#define GOTGCTL                HSOTG_REG(0x000)
58
FIELD(ID_PFR0, STATE0, 0, 4)
72
+#define GOTGCTL_CHIRPEN            BIT(27)
59
FIELD(ID_PFR0, STATE1, 4, 4)
73
+#define GOTGCTL_MULT_VALID_BC_MASK    (0x1f << 22)
60
FIELD(ID_PFR0, STATE2, 8, 4)
74
+#define GOTGCTL_MULT_VALID_BC_SHIFT    22
61
@@ -XXX,XX +XXX,XX @@ FIELD(ID_PFR1, SEC_FRAC, 20, 4)
75
+#define GOTGCTL_OTGVER            BIT(20)
62
FIELD(ID_PFR1, VIRT_FRAC, 24, 4)
76
+#define GOTGCTL_BSESVLD            BIT(19)
63
FIELD(ID_PFR1, GIC, 28, 4)
77
+#define GOTGCTL_ASESVLD            BIT(18)
64
78
+#define GOTGCTL_DBNC_SHORT        BIT(17)
65
+FIELD(ID_PFR2, CSV3, 0, 4)
79
+#define GOTGCTL_CONID_B            BIT(16)
66
+FIELD(ID_PFR2, SSBS, 4, 4)
80
+#define GOTGCTL_DBNCE_FLTR_BYPASS    BIT(15)
67
+FIELD(ID_PFR2, RAS_FRAC, 8, 4)
81
+#define GOTGCTL_DEVHNPEN        BIT(11)
82
+#define GOTGCTL_HSTSETHNPEN        BIT(10)
83
+#define GOTGCTL_HNPREQ            BIT(9)
84
+#define GOTGCTL_HSTNEGSCS        BIT(8)
85
+#define GOTGCTL_SESREQ            BIT(1)
86
+#define GOTGCTL_SESREQSCS        BIT(0)
87
+
68
+
88
+#define GOTGINT                HSOTG_REG(0x004)
69
FIELD(ID_AA64ISAR0, AES, 4, 4)
89
+#define GOTGINT_DBNCE_DONE        BIT(19)
70
FIELD(ID_AA64ISAR0, SHA1, 8, 4)
90
+#define GOTGINT_A_DEV_TOUT_CHG        BIT(18)
71
FIELD(ID_AA64ISAR0, SHA2, 12, 4)
91
+#define GOTGINT_HST_NEG_DET        BIT(17)
72
@@ -XXX,XX +XXX,XX @@ FIELD(ID_DFR0, MPROFDBG, 20, 4)
92
+#define GOTGINT_HST_NEG_SUC_STS_CHNG    BIT(9)
73
FIELD(ID_DFR0, PERFMON, 24, 4)
93
+#define GOTGINT_SES_REQ_SUC_STS_CHNG    BIT(8)
74
FIELD(ID_DFR0, TRACEFILT, 28, 4)
94
+#define GOTGINT_SES_END_DET        BIT(2)
75
76
+FIELD(ID_DFR1, MTPMU, 0, 4)
95
+
77
+
96
+#define GAHBCFG                HSOTG_REG(0x008)
78
FIELD(DBGDIDR, SE_IMP, 12, 1)
97
+#define GAHBCFG_AHB_SINGLE        BIT(23)
79
FIELD(DBGDIDR, NSUHD_IMP, 14, 1)
98
+#define GAHBCFG_NOTI_ALL_DMA_WRIT    BIT(22)
80
FIELD(DBGDIDR, VERSION, 16, 4)
99
+#define GAHBCFG_REM_MEM_SUPP        BIT(21)
100
+#define GAHBCFG_P_TXF_EMP_LVL        BIT(8)
101
+#define GAHBCFG_NP_TXF_EMP_LVL        BIT(7)
102
+#define GAHBCFG_DMA_EN            BIT(5)
103
+#define GAHBCFG_HBSTLEN_MASK        (0xf << 1)
104
+#define GAHBCFG_HBSTLEN_SHIFT        1
105
+#define GAHBCFG_HBSTLEN_SINGLE        0
106
+#define GAHBCFG_HBSTLEN_INCR        1
107
+#define GAHBCFG_HBSTLEN_INCR4        3
108
+#define GAHBCFG_HBSTLEN_INCR8        5
109
+#define GAHBCFG_HBSTLEN_INCR16        7
110
+#define GAHBCFG_GLBL_INTR_EN        BIT(0)
111
+#define GAHBCFG_CTRL_MASK        (GAHBCFG_P_TXF_EMP_LVL | \
112
+                     GAHBCFG_NP_TXF_EMP_LVL | \
113
+                     GAHBCFG_DMA_EN | \
114
+                     GAHBCFG_GLBL_INTR_EN)
115
+
116
+#define GUSBCFG                HSOTG_REG(0x00C)
117
+#define GUSBCFG_FORCEDEVMODE        BIT(30)
118
+#define GUSBCFG_FORCEHOSTMODE        BIT(29)
119
+#define GUSBCFG_TXENDDELAY        BIT(28)
120
+#define GUSBCFG_ICTRAFFICPULLREMOVE    BIT(27)
121
+#define GUSBCFG_ICUSBCAP        BIT(26)
122
+#define GUSBCFG_ULPI_INT_PROT_DIS    BIT(25)
123
+#define GUSBCFG_INDICATORPASSTHROUGH    BIT(24)
124
+#define GUSBCFG_INDICATORCOMPLEMENT    BIT(23)
125
+#define GUSBCFG_TERMSELDLPULSE        BIT(22)
126
+#define GUSBCFG_ULPI_INT_VBUS_IND    BIT(21)
127
+#define GUSBCFG_ULPI_EXT_VBUS_DRV    BIT(20)
128
+#define GUSBCFG_ULPI_CLK_SUSP_M        BIT(19)
129
+#define GUSBCFG_ULPI_AUTO_RES        BIT(18)
130
+#define GUSBCFG_ULPI_FS_LS        BIT(17)
131
+#define GUSBCFG_OTG_UTMI_FS_SEL        BIT(16)
132
+#define GUSBCFG_PHY_LP_CLK_SEL        BIT(15)
133
+#define GUSBCFG_USBTRDTIM_MASK        (0xf << 10)
134
+#define GUSBCFG_USBTRDTIM_SHIFT        10
135
+#define GUSBCFG_HNPCAP            BIT(9)
136
+#define GUSBCFG_SRPCAP            BIT(8)
137
+#define GUSBCFG_DDRSEL            BIT(7)
138
+#define GUSBCFG_PHYSEL            BIT(6)
139
+#define GUSBCFG_FSINTF            BIT(5)
140
+#define GUSBCFG_ULPI_UTMI_SEL        BIT(4)
141
+#define GUSBCFG_PHYIF16            BIT(3)
142
+#define GUSBCFG_PHYIF8            (0 << 3)
143
+#define GUSBCFG_TOUTCAL_MASK        (0x7 << 0)
144
+#define GUSBCFG_TOUTCAL_SHIFT        0
145
+#define GUSBCFG_TOUTCAL_LIMIT        0x7
146
+#define GUSBCFG_TOUTCAL(_x)        ((_x) << 0)
147
+
148
+#define GRSTCTL                HSOTG_REG(0x010)
149
+#define GRSTCTL_AHBIDLE            BIT(31)
150
+#define GRSTCTL_DMAREQ            BIT(30)
151
+#define GRSTCTL_TXFNUM_MASK        (0x1f << 6)
152
+#define GRSTCTL_TXFNUM_SHIFT        6
153
+#define GRSTCTL_TXFNUM_LIMIT        0x1f
154
+#define GRSTCTL_TXFNUM(_x)        ((_x) << 6)
155
+#define GRSTCTL_TXFFLSH            BIT(5)
156
+#define GRSTCTL_RXFFLSH            BIT(4)
157
+#define GRSTCTL_IN_TKNQ_FLSH        BIT(3)
158
+#define GRSTCTL_FRMCNTRRST        BIT(2)
159
+#define GRSTCTL_HSFTRST            BIT(1)
160
+#define GRSTCTL_CSFTRST            BIT(0)
161
+
162
+#define GINTSTS                HSOTG_REG(0x014)
163
+#define GINTMSK                HSOTG_REG(0x018)
164
+#define GINTSTS_WKUPINT            BIT(31)
165
+#define GINTSTS_SESSREQINT        BIT(30)
166
+#define GINTSTS_DISCONNINT        BIT(29)
167
+#define GINTSTS_CONIDSTSCHNG        BIT(28)
168
+#define GINTSTS_LPMTRANRCVD        BIT(27)
169
+#define GINTSTS_PTXFEMP            BIT(26)
170
+#define GINTSTS_HCHINT            BIT(25)
171
+#define GINTSTS_PRTINT            BIT(24)
172
+#define GINTSTS_RESETDET        BIT(23)
173
+#define GINTSTS_FET_SUSP        BIT(22)
174
+#define GINTSTS_INCOMPL_IP        BIT(21)
175
+#define GINTSTS_INCOMPL_SOOUT        BIT(21)
176
+#define GINTSTS_INCOMPL_SOIN        BIT(20)
177
+#define GINTSTS_OEPINT            BIT(19)
178
+#define GINTSTS_IEPINT            BIT(18)
179
+#define GINTSTS_EPMIS            BIT(17)
180
+#define GINTSTS_RESTOREDONE        BIT(16)
181
+#define GINTSTS_EOPF            BIT(15)
182
+#define GINTSTS_ISOUTDROP        BIT(14)
183
+#define GINTSTS_ENUMDONE        BIT(13)
184
+#define GINTSTS_USBRST            BIT(12)
185
+#define GINTSTS_USBSUSP            BIT(11)
186
+#define GINTSTS_ERLYSUSP        BIT(10)
187
+#define GINTSTS_I2CINT            BIT(9)
188
+#define GINTSTS_ULPI_CK_INT        BIT(8)
189
+#define GINTSTS_GOUTNAKEFF        BIT(7)
190
+#define GINTSTS_GINNAKEFF        BIT(6)
191
+#define GINTSTS_NPTXFEMP        BIT(5)
192
+#define GINTSTS_RXFLVL            BIT(4)
193
+#define GINTSTS_SOF            BIT(3)
194
+#define GINTSTS_OTGINT            BIT(2)
195
+#define GINTSTS_MODEMIS            BIT(1)
196
+#define GINTSTS_CURMODE_HOST        BIT(0)
197
+
198
+#define GRXSTSR                HSOTG_REG(0x01C)
199
+#define GRXSTSP                HSOTG_REG(0x020)
200
+#define GRXSTS_FN_MASK            (0x7f << 25)
201
+#define GRXSTS_FN_SHIFT            25
202
+#define GRXSTS_PKTSTS_MASK        (0xf << 17)
203
+#define GRXSTS_PKTSTS_SHIFT        17
204
+#define GRXSTS_PKTSTS_GLOBALOUTNAK    1
205
+#define GRXSTS_PKTSTS_OUTRX        2
206
+#define GRXSTS_PKTSTS_HCHIN        2
207
+#define GRXSTS_PKTSTS_OUTDONE        3
208
+#define GRXSTS_PKTSTS_HCHIN_XFER_COMP    3
209
+#define GRXSTS_PKTSTS_SETUPDONE        4
210
+#define GRXSTS_PKTSTS_DATATOGGLEERR    5
211
+#define GRXSTS_PKTSTS_SETUPRX        6
212
+#define GRXSTS_PKTSTS_HCHHALTED        7
213
+#define GRXSTS_HCHNUM_MASK        (0xf << 0)
214
+#define GRXSTS_HCHNUM_SHIFT        0
215
+#define GRXSTS_DPID_MASK        (0x3 << 15)
216
+#define GRXSTS_DPID_SHIFT        15
217
+#define GRXSTS_BYTECNT_MASK        (0x7ff << 4)
218
+#define GRXSTS_BYTECNT_SHIFT        4
219
+#define GRXSTS_EPNUM_MASK        (0xf << 0)
220
+#define GRXSTS_EPNUM_SHIFT        0
221
+
222
+#define GRXFSIZ                HSOTG_REG(0x024)
223
+#define GRXFSIZ_DEPTH_MASK        (0xffff << 0)
224
+#define GRXFSIZ_DEPTH_SHIFT        0
225
+
226
+#define GNPTXFSIZ            HSOTG_REG(0x028)
227
+/* Use FIFOSIZE_* constants to access this register */
228
+
229
+#define GNPTXSTS            HSOTG_REG(0x02C)
230
+#define GNPTXSTS_NP_TXQ_TOP_MASK        (0x7f << 24)
231
+#define GNPTXSTS_NP_TXQ_TOP_SHIFT        24
232
+#define GNPTXSTS_NP_TXQ_SPC_AVAIL_MASK        (0xff << 16)
233
+#define GNPTXSTS_NP_TXQ_SPC_AVAIL_SHIFT        16
234
+#define GNPTXSTS_NP_TXQ_SPC_AVAIL_GET(_v)    (((_v) >> 16) & 0xff)
235
+#define GNPTXSTS_NP_TXF_SPC_AVAIL_MASK        (0xffff << 0)
236
+#define GNPTXSTS_NP_TXF_SPC_AVAIL_SHIFT        0
237
+#define GNPTXSTS_NP_TXF_SPC_AVAIL_GET(_v)    (((_v) >> 0) & 0xffff)
238
+
239
+#define GI2CCTL                HSOTG_REG(0x0030)
240
+#define GI2CCTL_BSYDNE            BIT(31)
241
+#define GI2CCTL_RW            BIT(30)
242
+#define GI2CCTL_I2CDATSE0        BIT(28)
243
+#define GI2CCTL_I2CDEVADDR_MASK        (0x3 << 26)
244
+#define GI2CCTL_I2CDEVADDR_SHIFT    26
245
+#define GI2CCTL_I2CSUSPCTL        BIT(25)
246
+#define GI2CCTL_ACK            BIT(24)
247
+#define GI2CCTL_I2CEN            BIT(23)
248
+#define GI2CCTL_ADDR_MASK        (0x7f << 16)
249
+#define GI2CCTL_ADDR_SHIFT        16
250
+#define GI2CCTL_REGADDR_MASK        (0xff << 8)
251
+#define GI2CCTL_REGADDR_SHIFT        8
252
+#define GI2CCTL_RWDATA_MASK        (0xff << 0)
253
+#define GI2CCTL_RWDATA_SHIFT        0
254
+
255
+#define GPVNDCTL            HSOTG_REG(0x0034)
256
+#define GGPIO                HSOTG_REG(0x0038)
257
+#define GGPIO_STM32_OTG_GCCFG_PWRDWN    BIT(16)
258
+
259
+#define GUID                HSOTG_REG(0x003c)
260
+#define GSNPSID                HSOTG_REG(0x0040)
261
+#define GHWCFG1                HSOTG_REG(0x0044)
262
+#define GSNPSID_ID_MASK            GENMASK(31, 16)
263
+
264
+#define GHWCFG2                HSOTG_REG(0x0048)
265
+#define GHWCFG2_OTG_ENABLE_IC_USB        BIT(31)
266
+#define GHWCFG2_DEV_TOKEN_Q_DEPTH_MASK        (0x1f << 26)
267
+#define GHWCFG2_DEV_TOKEN_Q_DEPTH_SHIFT        26
268
+#define GHWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK    (0x3 << 24)
269
+#define GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT    24
270
+#define GHWCFG2_NONPERIO_TX_Q_DEPTH_MASK    (0x3 << 22)
271
+#define GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT    22
272
+#define GHWCFG2_MULTI_PROC_INT            BIT(20)
273
+#define GHWCFG2_DYNAMIC_FIFO            BIT(19)
274
+#define GHWCFG2_PERIO_EP_SUPPORTED        BIT(18)
275
+#define GHWCFG2_NUM_HOST_CHAN_MASK        (0xf << 14)
276
+#define GHWCFG2_NUM_HOST_CHAN_SHIFT        14
277
+#define GHWCFG2_NUM_DEV_EP_MASK            (0xf << 10)
278
+#define GHWCFG2_NUM_DEV_EP_SHIFT        10
279
+#define GHWCFG2_FS_PHY_TYPE_MASK        (0x3 << 8)
280
+#define GHWCFG2_FS_PHY_TYPE_SHIFT        8
281
+#define GHWCFG2_FS_PHY_TYPE_NOT_SUPPORTED    0
282
+#define GHWCFG2_FS_PHY_TYPE_DEDICATED        1
283
+#define GHWCFG2_FS_PHY_TYPE_SHARED_UTMI        2
284
+#define GHWCFG2_FS_PHY_TYPE_SHARED_ULPI        3
285
+#define GHWCFG2_HS_PHY_TYPE_MASK        (0x3 << 6)
286
+#define GHWCFG2_HS_PHY_TYPE_SHIFT        6
287
+#define GHWCFG2_HS_PHY_TYPE_NOT_SUPPORTED    0
288
+#define GHWCFG2_HS_PHY_TYPE_UTMI        1
289
+#define GHWCFG2_HS_PHY_TYPE_ULPI        2
290
+#define GHWCFG2_HS_PHY_TYPE_UTMI_ULPI        3
291
+#define GHWCFG2_POINT2POINT            BIT(5)
292
+#define GHWCFG2_ARCHITECTURE_MASK        (0x3 << 3)
293
+#define GHWCFG2_ARCHITECTURE_SHIFT        3
294
+#define GHWCFG2_SLAVE_ONLY_ARCH            0
295
+#define GHWCFG2_EXT_DMA_ARCH            1
296
+#define GHWCFG2_INT_DMA_ARCH            2
297
+#define GHWCFG2_OP_MODE_MASK            (0x7 << 0)
298
+#define GHWCFG2_OP_MODE_SHIFT            0
299
+#define GHWCFG2_OP_MODE_HNP_SRP_CAPABLE        0
300
+#define GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE    1
301
+#define GHWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE    2
302
+#define GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE    3
303
+#define GHWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE    4
304
+#define GHWCFG2_OP_MODE_SRP_CAPABLE_HOST    5
305
+#define GHWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST    6
306
+#define GHWCFG2_OP_MODE_UNDEFINED        7
307
+
308
+#define GHWCFG3                HSOTG_REG(0x004c)
309
+#define GHWCFG3_DFIFO_DEPTH_MASK        (0xffff << 16)
310
+#define GHWCFG3_DFIFO_DEPTH_SHIFT        16
311
+#define GHWCFG3_OTG_LPM_EN            BIT(15)
312
+#define GHWCFG3_BC_SUPPORT            BIT(14)
313
+#define GHWCFG3_OTG_ENABLE_HSIC            BIT(13)
314
+#define GHWCFG3_ADP_SUPP            BIT(12)
315
+#define GHWCFG3_SYNCH_RESET_TYPE        BIT(11)
316
+#define GHWCFG3_OPTIONAL_FEATURES        BIT(10)
317
+#define GHWCFG3_VENDOR_CTRL_IF            BIT(9)
318
+#define GHWCFG3_I2C                BIT(8)
319
+#define GHWCFG3_OTG_FUNC            BIT(7)
320
+#define GHWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK    (0x7 << 4)
321
+#define GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT    4
322
+#define GHWCFG3_XFER_SIZE_CNTR_WIDTH_MASK    (0xf << 0)
323
+#define GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT    0
324
+
325
+#define GHWCFG4                HSOTG_REG(0x0050)
326
+#define GHWCFG4_DESC_DMA_DYN            BIT(31)
327
+#define GHWCFG4_DESC_DMA            BIT(30)
328
+#define GHWCFG4_NUM_IN_EPS_MASK            (0xf << 26)
329
+#define GHWCFG4_NUM_IN_EPS_SHIFT        26
330
+#define GHWCFG4_DED_FIFO_EN            BIT(25)
331
+#define GHWCFG4_DED_FIFO_SHIFT        25
332
+#define GHWCFG4_SESSION_END_FILT_EN        BIT(24)
333
+#define GHWCFG4_B_VALID_FILT_EN            BIT(23)
334
+#define GHWCFG4_A_VALID_FILT_EN            BIT(22)
335
+#define GHWCFG4_VBUS_VALID_FILT_EN        BIT(21)
336
+#define GHWCFG4_IDDIG_FILT_EN            BIT(20)
337
+#define GHWCFG4_NUM_DEV_MODE_CTRL_EP_MASK    (0xf << 16)
338
+#define GHWCFG4_NUM_DEV_MODE_CTRL_EP_SHIFT    16
339
+#define GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK    (0x3 << 14)
340
+#define GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT    14
341
+#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8        0
342
+#define GHWCFG4_UTMI_PHY_DATA_WIDTH_16        1
343
+#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8_OR_16    2
344
+#define GHWCFG4_ACG_SUPPORTED            BIT(12)
345
+#define GHWCFG4_IPG_ISOC_SUPPORTED        BIT(11)
346
+#define GHWCFG4_SERVICE_INTERVAL_SUPPORTED BIT(10)
347
+#define GHWCFG4_XHIBER                BIT(7)
348
+#define GHWCFG4_HIBER                BIT(6)
349
+#define GHWCFG4_MIN_AHB_FREQ            BIT(5)
350
+#define GHWCFG4_POWER_OPTIMIZ            BIT(4)
351
+#define GHWCFG4_NUM_DEV_PERIO_IN_EP_MASK    (0xf << 0)
352
+#define GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT    0
353
+
354
+#define GLPMCFG                HSOTG_REG(0x0054)
355
+#define GLPMCFG_INVSELHSIC        BIT(31)
356
+#define GLPMCFG_HSICCON            BIT(30)
357
+#define GLPMCFG_RSTRSLPSTS        BIT(29)
358
+#define GLPMCFG_ENBESL            BIT(28)
359
+#define GLPMCFG_LPM_RETRYCNT_STS_MASK    (0x7 << 25)
360
+#define GLPMCFG_LPM_RETRYCNT_STS_SHIFT    25
361
+#define GLPMCFG_SNDLPM            BIT(24)
362
+#define GLPMCFG_RETRY_CNT_MASK        (0x7 << 21)
363
+#define GLPMCFG_RETRY_CNT_SHIFT        21
364
+#define GLPMCFG_LPM_REJECT_CTRL_CONTROL    BIT(21)
365
+#define GLPMCFG_LPM_ACCEPT_CTRL_ISOC    BIT(22)
366
+#define GLPMCFG_LPM_CHNL_INDX_MASK    (0xf << 17)
367
+#define GLPMCFG_LPM_CHNL_INDX_SHIFT    17
368
+#define GLPMCFG_L1RESUMEOK        BIT(16)
369
+#define GLPMCFG_SLPSTS            BIT(15)
370
+#define GLPMCFG_COREL1RES_MASK        (0x3 << 13)
371
+#define GLPMCFG_COREL1RES_SHIFT        13
372
+#define GLPMCFG_HIRD_THRES_MASK        (0x1f << 8)
373
+#define GLPMCFG_HIRD_THRES_SHIFT    8
374
+#define GLPMCFG_HIRD_THRES_EN        (0x10 << 8)
375
+#define GLPMCFG_ENBLSLPM        BIT(7)
376
+#define GLPMCFG_BREMOTEWAKE        BIT(6)
377
+#define GLPMCFG_HIRD_MASK        (0xf << 2)
378
+#define GLPMCFG_HIRD_SHIFT        2
379
+#define GLPMCFG_APPL1RES        BIT(1)
380
+#define GLPMCFG_LPMCAP            BIT(0)
381
+
382
+#define GPWRDN                HSOTG_REG(0x0058)
383
+#define GPWRDN_MULT_VAL_ID_BC_MASK    (0x1f << 24)
384
+#define GPWRDN_MULT_VAL_ID_BC_SHIFT    24
385
+#define GPWRDN_ADP_INT            BIT(23)
386
+#define GPWRDN_BSESSVLD            BIT(22)
387
+#define GPWRDN_IDSTS            BIT(21)
388
+#define GPWRDN_LINESTATE_MASK        (0x3 << 19)
389
+#define GPWRDN_LINESTATE_SHIFT        19
390
+#define GPWRDN_STS_CHGINT_MSK        BIT(18)
391
+#define GPWRDN_STS_CHGINT        BIT(17)
392
+#define GPWRDN_SRP_DET_MSK        BIT(16)
393
+#define GPWRDN_SRP_DET            BIT(15)
394
+#define GPWRDN_CONNECT_DET_MSK        BIT(14)
395
+#define GPWRDN_CONNECT_DET        BIT(13)
396
+#define GPWRDN_DISCONN_DET_MSK        BIT(12)
397
+#define GPWRDN_DISCONN_DET        BIT(11)
398
+#define GPWRDN_RST_DET_MSK        BIT(10)
399
+#define GPWRDN_RST_DET            BIT(9)
400
+#define GPWRDN_LNSTSCHG_MSK        BIT(8)
401
+#define GPWRDN_LNSTSCHG            BIT(7)
402
+#define GPWRDN_DIS_VBUS            BIT(6)
403
+#define GPWRDN_PWRDNSWTCH        BIT(5)
404
+#define GPWRDN_PWRDNRSTN        BIT(4)
405
+#define GPWRDN_PWRDNCLMP        BIT(3)
406
+#define GPWRDN_RESTORE            BIT(2)
407
+#define GPWRDN_PMUACTV            BIT(1)
408
+#define GPWRDN_PMUINTSEL        BIT(0)
409
+
410
+#define GDFIFOCFG            HSOTG_REG(0x005c)
411
+#define GDFIFOCFG_EPINFOBASE_MASK    (0xffff << 16)
412
+#define GDFIFOCFG_EPINFOBASE_SHIFT    16
413
+#define GDFIFOCFG_GDFIFOCFG_MASK    (0xffff << 0)
414
+#define GDFIFOCFG_GDFIFOCFG_SHIFT    0
415
+
416
+#define ADPCTL                HSOTG_REG(0x0060)
417
+#define ADPCTL_AR_MASK            (0x3 << 27)
418
+#define ADPCTL_AR_SHIFT            27
419
+#define ADPCTL_ADP_TMOUT_INT_MSK    BIT(26)
420
+#define ADPCTL_ADP_SNS_INT_MSK        BIT(25)
421
+#define ADPCTL_ADP_PRB_INT_MSK        BIT(24)
422
+#define ADPCTL_ADP_TMOUT_INT        BIT(23)
423
+#define ADPCTL_ADP_SNS_INT        BIT(22)
424
+#define ADPCTL_ADP_PRB_INT        BIT(21)
425
+#define ADPCTL_ADPENA            BIT(20)
426
+#define ADPCTL_ADPRES            BIT(19)
427
+#define ADPCTL_ENASNS            BIT(18)
428
+#define ADPCTL_ENAPRB            BIT(17)
429
+#define ADPCTL_RTIM_MASK        (0x7ff << 6)
430
+#define ADPCTL_RTIM_SHIFT        6
431
+#define ADPCTL_PRB_PER_MASK        (0x3 << 4)
432
+#define ADPCTL_PRB_PER_SHIFT        4
433
+#define ADPCTL_PRB_DELTA_MASK        (0x3 << 2)
434
+#define ADPCTL_PRB_DELTA_SHIFT        2
435
+#define ADPCTL_PRB_DSCHRG_MASK        (0x3 << 0)
436
+#define ADPCTL_PRB_DSCHRG_SHIFT        0
437
+
438
+#define GREFCLK                 HSOTG_REG(0x0064)
439
+#define GREFCLK_REFCLKPER_MASK         (0x1ffff << 15)
440
+#define GREFCLK_REFCLKPER_SHIFT         15
441
+#define GREFCLK_REF_CLK_MODE         BIT(14)
442
+#define GREFCLK_SOF_CNT_WKUP_ALERT_MASK     (0x3ff)
443
+#define GREFCLK_SOF_CNT_WKUP_ALERT_SHIFT 0
444
+
445
+#define GINTMSK2            HSOTG_REG(0x0068)
446
+#define GINTMSK2_WKUP_ALERT_INT_MSK    BIT(0)
447
+
448
+#define GINTSTS2            HSOTG_REG(0x006c)
449
+#define GINTSTS2_WKUP_ALERT_INT        BIT(0)
450
+
451
+#define HPTXFSIZ            HSOTG_REG(0x100)
452
+/* Use FIFOSIZE_* constants to access this register */
453
+
454
+#define DPTXFSIZN(_a)            HSOTG_REG(0x104 + (((_a) - 1) * 4))
455
+/* Use FIFOSIZE_* constants to access this register */
456
+
457
+/* These apply to the GNPTXFSIZ, HPTXFSIZ and DPTXFSIZN registers */
458
+#define FIFOSIZE_DEPTH_MASK        (0xffff << 16)
459
+#define FIFOSIZE_DEPTH_SHIFT        16
460
+#define FIFOSIZE_STARTADDR_MASK        (0xffff << 0)
461
+#define FIFOSIZE_STARTADDR_SHIFT    0
462
+#define FIFOSIZE_DEPTH_GET(_x)        (((_x) >> 16) & 0xffff)
463
+
464
+/* Device mode registers */
465
+
466
+#define DCFG                HSOTG_REG(0x800)
467
+#define DCFG_DESCDMA_EN            BIT(23)
468
+#define DCFG_EPMISCNT_MASK        (0x1f << 18)
469
+#define DCFG_EPMISCNT_SHIFT        18
470
+#define DCFG_EPMISCNT_LIMIT        0x1f
471
+#define DCFG_EPMISCNT(_x)        ((_x) << 18)
472
+#define DCFG_IPG_ISOC_SUPPORDED        BIT(17)
473
+#define DCFG_PERFRINT_MASK        (0x3 << 11)
474
+#define DCFG_PERFRINT_SHIFT        11
475
+#define DCFG_PERFRINT_LIMIT        0x3
476
+#define DCFG_PERFRINT(_x)        ((_x) << 11)
477
+#define DCFG_DEVADDR_MASK        (0x7f << 4)
478
+#define DCFG_DEVADDR_SHIFT        4
479
+#define DCFG_DEVADDR_LIMIT        0x7f
480
+#define DCFG_DEVADDR(_x)        ((_x) << 4)
481
+#define DCFG_NZ_STS_OUT_HSHK        BIT(2)
482
+#define DCFG_DEVSPD_MASK        (0x3 << 0)
483
+#define DCFG_DEVSPD_SHIFT        0
484
+#define DCFG_DEVSPD_HS            0
485
+#define DCFG_DEVSPD_FS            1
486
+#define DCFG_DEVSPD_LS            2
487
+#define DCFG_DEVSPD_FS48        3
488
+
489
+#define DCTL                HSOTG_REG(0x804)
490
+#define DCTL_SERVICE_INTERVAL_SUPPORTED BIT(19)
491
+#define DCTL_PWRONPRGDONE        BIT(11)
492
+#define DCTL_CGOUTNAK            BIT(10)
493
+#define DCTL_SGOUTNAK            BIT(9)
494
+#define DCTL_CGNPINNAK            BIT(8)
495
+#define DCTL_SGNPINNAK            BIT(7)
496
+#define DCTL_TSTCTL_MASK        (0x7 << 4)
497
+#define DCTL_TSTCTL_SHIFT        4
498
+#define DCTL_GOUTNAKSTS            BIT(3)
499
+#define DCTL_GNPINNAKSTS        BIT(2)
500
+#define DCTL_SFTDISCON            BIT(1)
501
+#define DCTL_RMTWKUPSIG            BIT(0)
502
+
503
+#define DSTS                HSOTG_REG(0x808)
504
+#define DSTS_SOFFN_MASK            (0x3fff << 8)
505
+#define DSTS_SOFFN_SHIFT        8
506
+#define DSTS_SOFFN_LIMIT        0x3fff
507
+#define DSTS_SOFFN(_x)            ((_x) << 8)
508
+#define DSTS_ERRATICERR            BIT(3)
509
+#define DSTS_ENUMSPD_MASK        (0x3 << 1)
510
+#define DSTS_ENUMSPD_SHIFT        1
511
+#define DSTS_ENUMSPD_HS            0
512
+#define DSTS_ENUMSPD_FS            1
513
+#define DSTS_ENUMSPD_LS            2
514
+#define DSTS_ENUMSPD_FS48        3
515
+#define DSTS_SUSPSTS            BIT(0)
516
+
517
+#define DIEPMSK                HSOTG_REG(0x810)
518
+#define DIEPMSK_NAKMSK            BIT(13)
519
+#define DIEPMSK_BNAININTRMSK        BIT(9)
520
+#define DIEPMSK_TXFIFOUNDRNMSK        BIT(8)
521
+#define DIEPMSK_TXFIFOEMPTY        BIT(7)
522
+#define DIEPMSK_INEPNAKEFFMSK        BIT(6)
523
+#define DIEPMSK_INTKNEPMISMSK        BIT(5)
524
+#define DIEPMSK_INTKNTXFEMPMSK        BIT(4)
525
+#define DIEPMSK_TIMEOUTMSK        BIT(3)
526
+#define DIEPMSK_AHBERRMSK        BIT(2)
527
+#define DIEPMSK_EPDISBLDMSK        BIT(1)
528
+#define DIEPMSK_XFERCOMPLMSK        BIT(0)
529
+
530
+#define DOEPMSK                HSOTG_REG(0x814)
531
+#define DOEPMSK_BNAMSK            BIT(9)
532
+#define DOEPMSK_BACK2BACKSETUP        BIT(6)
533
+#define DOEPMSK_STSPHSERCVDMSK        BIT(5)
534
+#define DOEPMSK_OUTTKNEPDISMSK        BIT(4)
535
+#define DOEPMSK_SETUPMSK        BIT(3)
536
+#define DOEPMSK_AHBERRMSK        BIT(2)
537
+#define DOEPMSK_EPDISBLDMSK        BIT(1)
538
+#define DOEPMSK_XFERCOMPLMSK        BIT(0)
539
+
540
+#define DAINT                HSOTG_REG(0x818)
541
+#define DAINTMSK            HSOTG_REG(0x81C)
542
+#define DAINT_OUTEP_SHIFT        16
543
+#define DAINT_OUTEP(_x)            (1 << ((_x) + 16))
544
+#define DAINT_INEP(_x)            (1 << (_x))
545
+
546
+#define DTKNQR1                HSOTG_REG(0x820)
547
+#define DTKNQR2                HSOTG_REG(0x824)
548
+#define DTKNQR3                HSOTG_REG(0x830)
549
+#define DTKNQR4                HSOTG_REG(0x834)
550
+#define DIEPEMPMSK            HSOTG_REG(0x834)
551
+
552
+#define DVBUSDIS            HSOTG_REG(0x828)
553
+#define DVBUSPULSE            HSOTG_REG(0x82C)
554
+
555
+#define DIEPCTL0            HSOTG_REG(0x900)
556
+#define DIEPCTL(_a)            HSOTG_REG(0x900 + ((_a) * 0x20))
557
+
558
+#define DOEPCTL0            HSOTG_REG(0xB00)
559
+#define DOEPCTL(_a)            HSOTG_REG(0xB00 + ((_a) * 0x20))
560
+
561
+/* EP0 specialness:
562
+ * bits[29..28] - reserved (no SetD0PID, SetD1PID)
563
+ * bits[25..22] - should always be zero, this isn't a periodic endpoint
564
+ * bits[10..0] - MPS setting different for EP0
565
+ */
566
+#define D0EPCTL_MPS_MASK        (0x3 << 0)
567
+#define D0EPCTL_MPS_SHIFT        0
568
+#define D0EPCTL_MPS_64            0
569
+#define D0EPCTL_MPS_32            1
570
+#define D0EPCTL_MPS_16            2
571
+#define D0EPCTL_MPS_8            3
572
+
573
+#define DXEPCTL_EPENA            BIT(31)
574
+#define DXEPCTL_EPDIS            BIT(30)
575
+#define DXEPCTL_SETD1PID        BIT(29)
576
+#define DXEPCTL_SETODDFR        BIT(29)
577
+#define DXEPCTL_SETD0PID        BIT(28)
578
+#define DXEPCTL_SETEVENFR        BIT(28)
579
+#define DXEPCTL_SNAK            BIT(27)
580
+#define DXEPCTL_CNAK            BIT(26)
581
+#define DXEPCTL_TXFNUM_MASK        (0xf << 22)
582
+#define DXEPCTL_TXFNUM_SHIFT        22
583
+#define DXEPCTL_TXFNUM_LIMIT        0xf
584
+#define DXEPCTL_TXFNUM(_x)        ((_x) << 22)
585
+#define DXEPCTL_STALL            BIT(21)
586
+#define DXEPCTL_SNP            BIT(20)
587
+#define DXEPCTL_EPTYPE_MASK        (0x3 << 18)
588
+#define DXEPCTL_EPTYPE_CONTROL        (0x0 << 18)
589
+#define DXEPCTL_EPTYPE_ISO        (0x1 << 18)
590
+#define DXEPCTL_EPTYPE_BULK        (0x2 << 18)
591
+#define DXEPCTL_EPTYPE_INTERRUPT    (0x3 << 18)
592
+
593
+#define DXEPCTL_NAKSTS            BIT(17)
594
+#define DXEPCTL_DPID            BIT(16)
595
+#define DXEPCTL_EOFRNUM            BIT(16)
596
+#define DXEPCTL_USBACTEP        BIT(15)
597
+#define DXEPCTL_NEXTEP_MASK        (0xf << 11)
598
+#define DXEPCTL_NEXTEP_SHIFT        11
599
+#define DXEPCTL_NEXTEP_LIMIT        0xf
600
+#define DXEPCTL_NEXTEP(_x)        ((_x) << 11)
601
+#define DXEPCTL_MPS_MASK        (0x7ff << 0)
602
+#define DXEPCTL_MPS_SHIFT        0
603
+#define DXEPCTL_MPS_LIMIT        0x7ff
604
+#define DXEPCTL_MPS(_x)            ((_x) << 0)
605
+
606
+#define DIEPINT(_a)            HSOTG_REG(0x908 + ((_a) * 0x20))
607
+#define DOEPINT(_a)            HSOTG_REG(0xB08 + ((_a) * 0x20))
608
+#define DXEPINT_SETUP_RCVD        BIT(15)
609
+#define DXEPINT_NYETINTRPT        BIT(14)
610
+#define DXEPINT_NAKINTRPT        BIT(13)
611
+#define DXEPINT_BBLEERRINTRPT        BIT(12)
612
+#define DXEPINT_PKTDRPSTS        BIT(11)
613
+#define DXEPINT_BNAINTR            BIT(9)
614
+#define DXEPINT_TXFIFOUNDRN        BIT(8)
615
+#define DXEPINT_OUTPKTERR        BIT(8)
616
+#define DXEPINT_TXFEMP            BIT(7)
617
+#define DXEPINT_INEPNAKEFF        BIT(6)
618
+#define DXEPINT_BACK2BACKSETUP        BIT(6)
619
+#define DXEPINT_INTKNEPMIS        BIT(5)
620
+#define DXEPINT_STSPHSERCVD        BIT(5)
621
+#define DXEPINT_INTKNTXFEMP        BIT(4)
622
+#define DXEPINT_OUTTKNEPDIS        BIT(4)
623
+#define DXEPINT_TIMEOUT            BIT(3)
624
+#define DXEPINT_SETUP            BIT(3)
625
+#define DXEPINT_AHBERR            BIT(2)
626
+#define DXEPINT_EPDISBLD        BIT(1)
627
+#define DXEPINT_XFERCOMPL        BIT(0)
628
+
629
+#define DIEPTSIZ0            HSOTG_REG(0x910)
630
+#define DIEPTSIZ0_PKTCNT_MASK        (0x3 << 19)
631
+#define DIEPTSIZ0_PKTCNT_SHIFT        19
632
+#define DIEPTSIZ0_PKTCNT_LIMIT        0x3
633
+#define DIEPTSIZ0_PKTCNT(_x)        ((_x) << 19)
634
+#define DIEPTSIZ0_XFERSIZE_MASK        (0x7f << 0)
635
+#define DIEPTSIZ0_XFERSIZE_SHIFT    0
636
+#define DIEPTSIZ0_XFERSIZE_LIMIT    0x7f
637
+#define DIEPTSIZ0_XFERSIZE(_x)        ((_x) << 0)
638
+
639
+#define DOEPTSIZ0            HSOTG_REG(0xB10)
640
+#define DOEPTSIZ0_SUPCNT_MASK        (0x3 << 29)
641
+#define DOEPTSIZ0_SUPCNT_SHIFT        29
642
+#define DOEPTSIZ0_SUPCNT_LIMIT        0x3
643
+#define DOEPTSIZ0_SUPCNT(_x)        ((_x) << 29)
644
+#define DOEPTSIZ0_PKTCNT        BIT(19)
645
+#define DOEPTSIZ0_XFERSIZE_MASK        (0x7f << 0)
646
+#define DOEPTSIZ0_XFERSIZE_SHIFT    0
647
+
648
+#define DIEPTSIZ(_a)            HSOTG_REG(0x910 + ((_a) * 0x20))
649
+#define DOEPTSIZ(_a)            HSOTG_REG(0xB10 + ((_a) * 0x20))
650
+#define DXEPTSIZ_MC_MASK        (0x3 << 29)
651
+#define DXEPTSIZ_MC_SHIFT        29
652
+#define DXEPTSIZ_MC_LIMIT        0x3
653
+#define DXEPTSIZ_MC(_x)            ((_x) << 29)
654
+#define DXEPTSIZ_PKTCNT_MASK        (0x3ff << 19)
655
+#define DXEPTSIZ_PKTCNT_SHIFT        19
656
+#define DXEPTSIZ_PKTCNT_LIMIT        0x3ff
657
+#define DXEPTSIZ_PKTCNT_GET(_v)        (((_v) >> 19) & 0x3ff)
658
+#define DXEPTSIZ_PKTCNT(_x)        ((_x) << 19)
659
+#define DXEPTSIZ_XFERSIZE_MASK        (0x7ffff << 0)
660
+#define DXEPTSIZ_XFERSIZE_SHIFT        0
661
+#define DXEPTSIZ_XFERSIZE_LIMIT        0x7ffff
662
+#define DXEPTSIZ_XFERSIZE_GET(_v)    (((_v) >> 0) & 0x7ffff)
663
+#define DXEPTSIZ_XFERSIZE(_x)        ((_x) << 0)
664
+
665
+#define DIEPDMA(_a)            HSOTG_REG(0x914 + ((_a) * 0x20))
666
+#define DOEPDMA(_a)            HSOTG_REG(0xB14 + ((_a) * 0x20))
667
+
668
+#define DTXFSTS(_a)            HSOTG_REG(0x918 + ((_a) * 0x20))
669
+
670
+#define PCGCTL                HSOTG_REG(0x0e00)
671
+#define PCGCTL_IF_DEV_MODE        BIT(31)
672
+#define PCGCTL_P2HD_PRT_SPD_MASK    (0x3 << 29)
673
+#define PCGCTL_P2HD_PRT_SPD_SHIFT    29
674
+#define PCGCTL_P2HD_DEV_ENUM_SPD_MASK    (0x3 << 27)
675
+#define PCGCTL_P2HD_DEV_ENUM_SPD_SHIFT    27
676
+#define PCGCTL_MAC_DEV_ADDR_MASK    (0x7f << 20)
677
+#define PCGCTL_MAC_DEV_ADDR_SHIFT    20
678
+#define PCGCTL_MAX_TERMSEL        BIT(19)
679
+#define PCGCTL_MAX_XCVRSELECT_MASK    (0x3 << 17)
680
+#define PCGCTL_MAX_XCVRSELECT_SHIFT    17
681
+#define PCGCTL_PORT_POWER        BIT(16)
682
+#define PCGCTL_PRT_CLK_SEL_MASK        (0x3 << 14)
683
+#define PCGCTL_PRT_CLK_SEL_SHIFT    14
684
+#define PCGCTL_ESS_REG_RESTORED        BIT(13)
685
+#define PCGCTL_EXTND_HIBER_SWITCH    BIT(12)
686
+#define PCGCTL_EXTND_HIBER_PWRCLMP    BIT(11)
687
+#define PCGCTL_ENBL_EXTND_HIBER        BIT(10)
688
+#define PCGCTL_RESTOREMODE        BIT(9)
689
+#define PCGCTL_RESETAFTSUSP        BIT(8)
690
+#define PCGCTL_DEEP_SLEEP        BIT(7)
691
+#define PCGCTL_PHY_IN_SLEEP        BIT(6)
692
+#define PCGCTL_ENBL_SLEEP_GATING    BIT(5)
693
+#define PCGCTL_RSTPDWNMODULE        BIT(3)
694
+#define PCGCTL_PWRCLMP            BIT(2)
695
+#define PCGCTL_GATEHCLK            BIT(1)
696
+#define PCGCTL_STOPPCLK            BIT(0)
697
+
698
+#define PCGCCTL1 HSOTG_REG(0xe04)
699
+#define PCGCCTL1_TIMER (0x3 << 1)
700
+#define PCGCCTL1_GATEEN BIT(0)
701
+
702
+#define EPFIFO(_a)            HSOTG_REG(0x1000 + ((_a) * 0x1000))
703
+
704
+/* Host Mode Registers */
705
+
706
+#define HCFG                HSOTG_REG(0x0400)
707
+#define HCFG_MODECHTIMEN        BIT(31)
708
+#define HCFG_PERSCHEDENA        BIT(26)
709
+#define HCFG_FRLISTEN_MASK        (0x3 << 24)
710
+#define HCFG_FRLISTEN_SHIFT        24
711
+#define HCFG_FRLISTEN_8                (0 << 24)
712
+#define FRLISTEN_8_SIZE                8
713
+#define HCFG_FRLISTEN_16            BIT(24)
714
+#define FRLISTEN_16_SIZE            16
715
+#define HCFG_FRLISTEN_32            (2 << 24)
716
+#define FRLISTEN_32_SIZE            32
717
+#define HCFG_FRLISTEN_64            (3 << 24)
718
+#define FRLISTEN_64_SIZE            64
719
+#define HCFG_DESCDMA            BIT(23)
720
+#define HCFG_RESVALID_MASK        (0xff << 8)
721
+#define HCFG_RESVALID_SHIFT        8
722
+#define HCFG_ENA32KHZ            BIT(7)
723
+#define HCFG_FSLSSUPP            BIT(2)
724
+#define HCFG_FSLSPCLKSEL_MASK        (0x3 << 0)
725
+#define HCFG_FSLSPCLKSEL_SHIFT        0
726
+#define HCFG_FSLSPCLKSEL_30_60_MHZ    0
727
+#define HCFG_FSLSPCLKSEL_48_MHZ        1
728
+#define HCFG_FSLSPCLKSEL_6_MHZ        2
729
+
730
+#define HFIR                HSOTG_REG(0x0404)
731
+#define HFIR_FRINT_MASK            (0xffff << 0)
732
+#define HFIR_FRINT_SHIFT        0
733
+#define HFIR_RLDCTRL            BIT(16)
734
+
735
+#define HFNUM                HSOTG_REG(0x0408)
736
+#define HFNUM_FRREM_MASK        (0xffff << 16)
737
+#define HFNUM_FRREM_SHIFT        16
738
+#define HFNUM_FRNUM_MASK        (0xffff << 0)
739
+#define HFNUM_FRNUM_SHIFT        0
740
+#define HFNUM_MAX_FRNUM            0x3fff
741
+
742
+#define HPTXSTS                HSOTG_REG(0x0410)
743
+#define TXSTS_QTOP_ODD            BIT(31)
744
+#define TXSTS_QTOP_CHNEP_MASK        (0xf << 27)
745
+#define TXSTS_QTOP_CHNEP_SHIFT        27
746
+#define TXSTS_QTOP_TOKEN_MASK        (0x3 << 25)
747
+#define TXSTS_QTOP_TOKEN_SHIFT        25
748
+#define TXSTS_QTOP_TERMINATE        BIT(24)
749
+#define TXSTS_QSPCAVAIL_MASK        (0xff << 16)
750
+#define TXSTS_QSPCAVAIL_SHIFT        16
751
+#define TXSTS_FSPCAVAIL_MASK        (0xffff << 0)
752
+#define TXSTS_FSPCAVAIL_SHIFT        0
753
+
754
+#define HAINT                HSOTG_REG(0x0414)
755
+#define HAINTMSK            HSOTG_REG(0x0418)
756
+#define HFLBADDR            HSOTG_REG(0x041c)
757
+
758
+#define HPRT0                HSOTG_REG(0x0440)
759
+#define HPRT0_SPD_MASK            (0x3 << 17)
760
+#define HPRT0_SPD_SHIFT            17
761
+#define HPRT0_SPD_HIGH_SPEED        0
762
+#define HPRT0_SPD_FULL_SPEED        1
763
+#define HPRT0_SPD_LOW_SPEED        2
764
+#define HPRT0_TSTCTL_MASK        (0xf << 13)
765
+#define HPRT0_TSTCTL_SHIFT        13
766
+#define HPRT0_PWR            BIT(12)
767
+#define HPRT0_LNSTS_MASK        (0x3 << 10)
768
+#define HPRT0_LNSTS_SHIFT        10
769
+#define HPRT0_RST            BIT(8)
770
+#define HPRT0_SUSP            BIT(7)
771
+#define HPRT0_RES            BIT(6)
772
+#define HPRT0_OVRCURRCHG        BIT(5)
773
+#define HPRT0_OVRCURRACT        BIT(4)
774
+#define HPRT0_ENACHG            BIT(3)
775
+#define HPRT0_ENA            BIT(2)
776
+#define HPRT0_CONNDET            BIT(1)
777
+#define HPRT0_CONNSTS            BIT(0)
778
+
779
+#define HCCHAR(_ch)            HSOTG_REG(0x0500 + 0x20 * (_ch))
780
+#define HCCHAR_CHENA            BIT(31)
781
+#define HCCHAR_CHDIS            BIT(30)
782
+#define HCCHAR_ODDFRM            BIT(29)
783
+#define HCCHAR_DEVADDR_MASK        (0x7f << 22)
784
+#define HCCHAR_DEVADDR_SHIFT        22
785
+#define HCCHAR_MULTICNT_MASK        (0x3 << 20)
786
+#define HCCHAR_MULTICNT_SHIFT        20
787
+#define HCCHAR_EPTYPE_MASK        (0x3 << 18)
788
+#define HCCHAR_EPTYPE_SHIFT        18
789
+#define HCCHAR_LSPDDEV            BIT(17)
790
+#define HCCHAR_EPDIR            BIT(15)
791
+#define HCCHAR_EPNUM_MASK        (0xf << 11)
792
+#define HCCHAR_EPNUM_SHIFT        11
793
+#define HCCHAR_MPS_MASK            (0x7ff << 0)
794
+#define HCCHAR_MPS_SHIFT        0
795
+
796
+#define HCSPLT(_ch)            HSOTG_REG(0x0504 + 0x20 * (_ch))
797
+#define HCSPLT_SPLTENA            BIT(31)
798
+#define HCSPLT_COMPSPLT            BIT(16)
799
+#define HCSPLT_XACTPOS_MASK        (0x3 << 14)
800
+#define HCSPLT_XACTPOS_SHIFT        14
801
+#define HCSPLT_XACTPOS_MID        0
802
+#define HCSPLT_XACTPOS_END        1
803
+#define HCSPLT_XACTPOS_BEGIN        2
804
+#define HCSPLT_XACTPOS_ALL        3
805
+#define HCSPLT_HUBADDR_MASK        (0x7f << 7)
806
+#define HCSPLT_HUBADDR_SHIFT        7
807
+#define HCSPLT_PRTADDR_MASK        (0x7f << 0)
808
+#define HCSPLT_PRTADDR_SHIFT        0
809
+
810
+#define HCINT(_ch)            HSOTG_REG(0x0508 + 0x20 * (_ch))
811
+#define HCINTMSK(_ch)            HSOTG_REG(0x050c + 0x20 * (_ch))
812
+#define HCINTMSK_RESERVED14_31        (0x3ffff << 14)
813
+#define HCINTMSK_FRM_LIST_ROLL        BIT(13)
814
+#define HCINTMSK_XCS_XACT        BIT(12)
815
+#define HCINTMSK_BNA            BIT(11)
816
+#define HCINTMSK_DATATGLERR        BIT(10)
817
+#define HCINTMSK_FRMOVRUN        BIT(9)
818
+#define HCINTMSK_BBLERR            BIT(8)
819
+#define HCINTMSK_XACTERR        BIT(7)
820
+#define HCINTMSK_NYET            BIT(6)
821
+#define HCINTMSK_ACK            BIT(5)
822
+#define HCINTMSK_NAK            BIT(4)
823
+#define HCINTMSK_STALL            BIT(3)
824
+#define HCINTMSK_AHBERR            BIT(2)
825
+#define HCINTMSK_CHHLTD            BIT(1)
826
+#define HCINTMSK_XFERCOMPL        BIT(0)
827
+
828
+#define HCTSIZ(_ch)            HSOTG_REG(0x0510 + 0x20 * (_ch))
829
+#define TSIZ_DOPNG            BIT(31)
830
+#define TSIZ_SC_MC_PID_MASK        (0x3 << 29)
831
+#define TSIZ_SC_MC_PID_SHIFT        29
832
+#define TSIZ_SC_MC_PID_DATA0        0
833
+#define TSIZ_SC_MC_PID_DATA2        1
834
+#define TSIZ_SC_MC_PID_DATA1        2
835
+#define TSIZ_SC_MC_PID_MDATA        3
836
+#define TSIZ_SC_MC_PID_SETUP        3
837
+#define TSIZ_PKTCNT_MASK        (0x3ff << 19)
838
+#define TSIZ_PKTCNT_SHIFT        19
839
+#define TSIZ_NTD_MASK            (0xff << 8)
840
+#define TSIZ_NTD_SHIFT            8
841
+#define TSIZ_SCHINFO_MASK        (0xff << 0)
842
+#define TSIZ_SCHINFO_SHIFT        0
843
+#define TSIZ_XFERSIZE_MASK        (0x7ffff << 0)
844
+#define TSIZ_XFERSIZE_SHIFT        0
845
+
846
+#define HCDMA(_ch)            HSOTG_REG(0x0514 + 0x20 * (_ch))
847
+
848
+#define HCDMAB(_ch)            HSOTG_REG(0x051c + 0x20 * (_ch))
849
+
850
+#define HCFIFO(_ch)            HSOTG_REG(0x1000 + 0x1000 * (_ch))
851
+
852
+/**
853
+ * struct dwc2_dma_desc - DMA descriptor structure,
854
+ * used for both host and gadget modes
855
+ *
856
+ * @status: DMA descriptor status quadlet
857
+ * @buf: DMA descriptor data buffer pointer
858
+ *
859
+ * DMA Descriptor structure contains two quadlets:
860
+ * Status quadlet and Data buffer pointer.
861
+ */
862
+struct dwc2_dma_desc {
863
+    uint32_t status;
864
+    uint32_t buf;
865
+} __packed;
866
+
867
+/* Host Mode DMA descriptor status quadlet */
868
+
869
+#define HOST_DMA_A            BIT(31)
870
+#define HOST_DMA_STS_MASK        (0x3 << 28)
871
+#define HOST_DMA_STS_SHIFT        28
872
+#define HOST_DMA_STS_PKTERR        BIT(28)
873
+#define HOST_DMA_EOL            BIT(26)
874
+#define HOST_DMA_IOC            BIT(25)
875
+#define HOST_DMA_SUP            BIT(24)
876
+#define HOST_DMA_ALT_QTD        BIT(23)
877
+#define HOST_DMA_QTD_OFFSET_MASK    (0x3f << 17)
878
+#define HOST_DMA_QTD_OFFSET_SHIFT    17
879
+#define HOST_DMA_ISOC_NBYTES_MASK    (0xfff << 0)
880
+#define HOST_DMA_ISOC_NBYTES_SHIFT    0
881
+#define HOST_DMA_NBYTES_MASK        (0x1ffff << 0)
882
+#define HOST_DMA_NBYTES_SHIFT        0
883
+#define HOST_DMA_NBYTES_LIMIT        131071
884
+
885
+/* Device Mode DMA descriptor status quadlet */
886
+
887
+#define DEV_DMA_BUFF_STS_MASK        (0x3 << 30)
888
+#define DEV_DMA_BUFF_STS_SHIFT        30
889
+#define DEV_DMA_BUFF_STS_HREADY        0
890
+#define DEV_DMA_BUFF_STS_DMABUSY    1
891
+#define DEV_DMA_BUFF_STS_DMADONE    2
892
+#define DEV_DMA_BUFF_STS_HBUSY        3
893
+#define DEV_DMA_STS_MASK        (0x3 << 28)
894
+#define DEV_DMA_STS_SHIFT        28
895
+#define DEV_DMA_STS_SUCC        0
896
+#define DEV_DMA_STS_BUFF_FLUSH        1
897
+#define DEV_DMA_STS_BUFF_ERR        3
898
+#define DEV_DMA_L            BIT(27)
899
+#define DEV_DMA_SHORT            BIT(26)
900
+#define DEV_DMA_IOC            BIT(25)
901
+#define DEV_DMA_SR            BIT(24)
902
+#define DEV_DMA_MTRF            BIT(23)
903
+#define DEV_DMA_ISOC_PID_MASK        (0x3 << 23)
904
+#define DEV_DMA_ISOC_PID_SHIFT        23
905
+#define DEV_DMA_ISOC_PID_DATA0        0
906
+#define DEV_DMA_ISOC_PID_DATA2        1
907
+#define DEV_DMA_ISOC_PID_DATA1        2
908
+#define DEV_DMA_ISOC_PID_MDATA        3
909
+#define DEV_DMA_ISOC_FRNUM_MASK        (0x7ff << 12)
910
+#define DEV_DMA_ISOC_FRNUM_SHIFT    12
911
+#define DEV_DMA_ISOC_TX_NBYTES_MASK    (0xfff << 0)
912
+#define DEV_DMA_ISOC_TX_NBYTES_LIMIT    0xfff
913
+#define DEV_DMA_ISOC_RX_NBYTES_MASK    (0x7ff << 0)
914
+#define DEV_DMA_ISOC_RX_NBYTES_LIMIT    0x7ff
915
+#define DEV_DMA_ISOC_NBYTES_SHIFT    0
916
+#define DEV_DMA_NBYTES_MASK        (0xffff << 0)
917
+#define DEV_DMA_NBYTES_SHIFT        0
918
+#define DEV_DMA_NBYTES_LIMIT        0xffff
919
+
920
+#define MAX_DMA_DESC_NUM_GENERIC    64
921
+#define MAX_DMA_DESC_NUM_HS_ISOC    256
922
+
923
+#endif /* __DWC2_HW_H__ */
924
--
81
--
925
2.20.1
82
2.20.1
926
83
927
84
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Roman Bolshakov <r.bolshakov@yadro.com>
2
2
3
Rather than passing an opcode to a helper, fully decode the
3
QEMU documentation can't be opened if QEMU is run from build tree
4
operation at translate time. Use clear_tail_16 to zap the
4
because executables are placed in the top of build tree after conversion
5
balance of the SVE register with the AdvSIMD write.
5
to meson.
6
6
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Roman Bolshakov <r.bolshakov@yadro.com>
8
Message-id: 20200514212831.31248-7-richard.henderson@linaro.org
8
Reported-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20210108213815.64678-1-r.bolshakov@yadro.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
target/arm/helper.h | 5 ++++-
13
ui/cocoa.m | 2 +-
13
target/arm/crypto_helper.c | 24 ++++++++++++++++++------
14
1 file changed, 1 insertion(+), 1 deletion(-)
14
target/arm/translate-a64.c | 21 +++++----------------
15
3 files changed, 27 insertions(+), 23 deletions(-)
16
15
17
diff --git a/target/arm/helper.h b/target/arm/helper.h
16
diff --git a/ui/cocoa.m b/ui/cocoa.m
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.h
18
--- a/ui/cocoa.m
20
+++ b/target/arm/helper.h
19
+++ b/ui/cocoa.m
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(crypto_sha512su0, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
20
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
22
DEF_HELPER_FLAGS_4(crypto_sha512su1, TCG_CALL_NO_RWG,
21
- (void) openDocumentation: (NSString *) filename
23
void, ptr, ptr, ptr, i32)
24
25
-DEF_HELPER_FLAGS_5(crypto_sm3tt, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32, i32)
26
+DEF_HELPER_FLAGS_4(crypto_sm3tt1a, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
27
+DEF_HELPER_FLAGS_4(crypto_sm3tt1b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
28
+DEF_HELPER_FLAGS_4(crypto_sm3tt2a, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
29
+DEF_HELPER_FLAGS_4(crypto_sm3tt2b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
30
DEF_HELPER_FLAGS_4(crypto_sm3partw1, TCG_CALL_NO_RWG,
31
void, ptr, ptr, ptr, i32)
32
DEF_HELPER_FLAGS_4(crypto_sm3partw2, TCG_CALL_NO_RWG,
33
diff --git a/target/arm/crypto_helper.c b/target/arm/crypto_helper.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/crypto_helper.c
36
+++ b/target/arm/crypto_helper.c
37
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sm3partw2)(void *vd, void *vn, void *vm, uint32_t desc)
38
clear_tail_16(vd, desc);
39
}
40
41
-void HELPER(crypto_sm3tt)(void *vd, void *vn, void *vm, uint32_t imm2,
42
- uint32_t opcode)
43
+static inline void QEMU_ALWAYS_INLINE
44
+crypto_sm3tt(uint64_t *rd, uint64_t *rn, uint64_t *rm,
45
+ uint32_t desc, uint32_t opcode)
46
{
22
{
47
- uint64_t *rd = vd;
23
/* Where to look for local files */
48
- uint64_t *rn = vn;
24
- NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"../docs/"};
49
- uint64_t *rm = vm;
25
+ NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"docs/"};
50
union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
26
NSString *full_file_path;
51
union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
27
52
union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
28
/* iterate thru the possible paths until the file is found */
53
+ uint32_t imm2 = simd_data(desc);
54
uint32_t t;
55
56
assert(imm2 < 4);
57
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sm3tt)(void *vd, void *vn, void *vm, uint32_t imm2,
58
/* SM3TT2B */
59
t = cho(CR_ST_WORD(d, 3), CR_ST_WORD(d, 2), CR_ST_WORD(d, 1));
60
} else {
61
- g_assert_not_reached();
62
+ qemu_build_not_reached();
63
}
64
65
t += CR_ST_WORD(d, 0) + CR_ST_WORD(m, imm2);
66
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sm3tt)(void *vd, void *vn, void *vm, uint32_t imm2,
67
68
rd[0] = d.l[0];
69
rd[1] = d.l[1];
70
+
71
+ clear_tail_16(rd, desc);
72
}
73
74
+#define DO_SM3TT(NAME, OPCODE) \
75
+ void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \
76
+ { crypto_sm3tt(vd, vn, vm, desc, OPCODE); }
77
+
78
+DO_SM3TT(crypto_sm3tt1a, 0)
79
+DO_SM3TT(crypto_sm3tt1b, 1)
80
+DO_SM3TT(crypto_sm3tt2a, 2)
81
+DO_SM3TT(crypto_sm3tt2b, 3)
82
+
83
+#undef DO_SM3TT
84
+
85
static uint8_t const sm4_sbox[] = {
86
0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7,
87
0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
88
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
89
index XXXXXXX..XXXXXXX 100644
90
--- a/target/arm/translate-a64.c
91
+++ b/target/arm/translate-a64.c
92
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_xar(DisasContext *s, uint32_t insn)
93
*/
94
static void disas_crypto_three_reg_imm2(DisasContext *s, uint32_t insn)
95
{
96
+ static gen_helper_gvec_3 * const fns[4] = {
97
+ gen_helper_crypto_sm3tt1a, gen_helper_crypto_sm3tt1b,
98
+ gen_helper_crypto_sm3tt2a, gen_helper_crypto_sm3tt2b,
99
+ };
100
int opcode = extract32(insn, 10, 2);
101
int imm2 = extract32(insn, 12, 2);
102
int rm = extract32(insn, 16, 5);
103
int rn = extract32(insn, 5, 5);
104
int rd = extract32(insn, 0, 5);
105
- TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
106
- TCGv_i32 tcg_imm2, tcg_opcode;
107
108
if (!dc_isar_feature(aa64_sm3, s)) {
109
unallocated_encoding(s);
110
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_imm2(DisasContext *s, uint32_t insn)
111
return;
112
}
113
114
- tcg_rd_ptr = vec_full_reg_ptr(s, rd);
115
- tcg_rn_ptr = vec_full_reg_ptr(s, rn);
116
- tcg_rm_ptr = vec_full_reg_ptr(s, rm);
117
- tcg_imm2 = tcg_const_i32(imm2);
118
- tcg_opcode = tcg_const_i32(opcode);
119
-
120
- gen_helper_crypto_sm3tt(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr, tcg_imm2,
121
- tcg_opcode);
122
-
123
- tcg_temp_free_ptr(tcg_rd_ptr);
124
- tcg_temp_free_ptr(tcg_rn_ptr);
125
- tcg_temp_free_ptr(tcg_rm_ptr);
126
- tcg_temp_free_i32(tcg_imm2);
127
- tcg_temp_free_i32(tcg_opcode);
128
+ gen_gvec_op3_ool(s, true, rd, rn, rm, imm2, fns[opcode]);
129
}
130
131
/* C3.6 Data processing - SIMD, inc Crypto
132
--
29
--
133
2.20.1
30
2.20.1
134
31
135
32
diff view generated by jsdifflib
1
Convert the insns in the one-register-and-immediate group to decodetree.
1
In commit 1982e1602d15 we added a new qemu-storage-daemon(1) manpage.
2
2
At the moment new manpages have to be listed both in the conf.py for
3
In the new decode, our asimd_imm_const() function returns a 64-bit value
3
Sphinx and also in docs/meson.build for Meson. We forgot the second
4
rather than a 32-bit one, which means we don't need to treat cmode=14 op=1
4
of those -- correct the omission.
5
as a special case in the decoder (it is the only encoding where the two
6
halves of the 64-bit value are different).
7
5
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Message-id: 20200522145520.6778-10-peter.maydell@linaro.org
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Message-id: 20210108161416.21129-2-peter.maydell@linaro.org
11
---
10
---
12
target/arm/neon-dp.decode | 22 ++++++
11
docs/meson.build | 1 +
13
target/arm/translate-neon.inc.c | 118 ++++++++++++++++++++++++++++++++
12
1 file changed, 1 insertion(+)
14
target/arm/translate.c | 101 +--------------------------
15
3 files changed, 142 insertions(+), 99 deletions(-)
16
13
17
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
14
diff --git a/docs/meson.build b/docs/meson.build
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/neon-dp.decode
16
--- a/docs/meson.build
20
+++ b/target/arm/neon-dp.decode
17
+++ b/docs/meson.build
21
@@ -XXX,XX +XXX,XX @@ VCVT_SF_2sh 1111 001 0 1 . ...... .... 1110 0 . . 1 .... @2reg_vcvt
18
@@ -XXX,XX +XXX,XX @@ if build_docs
22
VCVT_UF_2sh 1111 001 1 1 . ...... .... 1110 0 . . 1 .... @2reg_vcvt
19
'qemu-img.1': (have_tools ? 'man1' : ''),
23
VCVT_FS_2sh 1111 001 0 1 . ...... .... 1111 0 . . 1 .... @2reg_vcvt
20
'qemu-nbd.8': (have_tools ? 'man8' : ''),
24
VCVT_FU_2sh 1111 001 1 1 . ...... .... 1111 0 . . 1 .... @2reg_vcvt
21
'qemu-pr-helper.8': (have_tools ? 'man8' : ''),
25
+
22
+ 'qemu-storage-daemon.1': (have_tools ? 'man1' : ''),
26
+######################################################################
23
'qemu-trace-stap.1': (config_host.has_key('CONFIG_TRACE_SYSTEMTAP') ? 'man1' : ''),
27
+# 1-reg-and-modified-immediate grouping:
24
'virtfs-proxy-helper.1': (have_virtfs_proxy_helper ? 'man1' : ''),
28
+# 1111 001 i 1 D 000 imm:3 Vd:4 cmode:4 0 Q op 1 Vm:4
25
'virtiofsd.1': (have_virtiofsd ? 'man1' : ''),
29
+######################################################################
30
+
31
+&1reg_imm vd q imm cmode op
32
+
33
+%asimd_imm_value 24:1 16:3 0:4
34
+
35
+@1reg_imm .... ... . . . ... ... .... .... . q:1 . . .... \
36
+ &1reg_imm imm=%asimd_imm_value vd=%vd_dp
37
+
38
+# The cmode/op bits here decode VORR/VBIC/VMOV/VMNV, but
39
+# not in a way we can conveniently represent in decodetree without
40
+# a lot of repetition:
41
+# VORR: op=0, (cmode & 1) && cmode < 12
42
+# VBIC: op=1, (cmode & 1) && cmode < 12
43
+# VMOV: everything else
44
+# So we have a single decode line and check the cmode/op in the
45
+# trans function.
46
+Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
47
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/translate-neon.inc.c
50
+++ b/target/arm/translate-neon.inc.c
51
@@ -XXX,XX +XXX,XX @@ DO_FP_2SH(VCVT_SF, gen_helper_vfp_sltos)
52
DO_FP_2SH(VCVT_UF, gen_helper_vfp_ultos)
53
DO_FP_2SH(VCVT_FS, gen_helper_vfp_tosls_round_to_zero)
54
DO_FP_2SH(VCVT_FU, gen_helper_vfp_touls_round_to_zero)
55
+
56
+static uint64_t asimd_imm_const(uint32_t imm, int cmode, int op)
57
+{
58
+ /*
59
+ * Expand the encoded constant.
60
+ * Note that cmode = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
61
+ * We choose to not special-case this and will behave as if a
62
+ * valid constant encoding of 0 had been given.
63
+ * cmode = 15 op = 1 must UNDEF; we assume decode has handled that.
64
+ */
65
+ switch (cmode) {
66
+ case 0: case 1:
67
+ /* no-op */
68
+ break;
69
+ case 2: case 3:
70
+ imm <<= 8;
71
+ break;
72
+ case 4: case 5:
73
+ imm <<= 16;
74
+ break;
75
+ case 6: case 7:
76
+ imm <<= 24;
77
+ break;
78
+ case 8: case 9:
79
+ imm |= imm << 16;
80
+ break;
81
+ case 10: case 11:
82
+ imm = (imm << 8) | (imm << 24);
83
+ break;
84
+ case 12:
85
+ imm = (imm << 8) | 0xff;
86
+ break;
87
+ case 13:
88
+ imm = (imm << 16) | 0xffff;
89
+ break;
90
+ case 14:
91
+ if (op) {
92
+ /*
93
+ * This is the only case where the top and bottom 32 bits
94
+ * of the encoded constant differ.
95
+ */
96
+ uint64_t imm64 = 0;
97
+ int n;
98
+
99
+ for (n = 0; n < 8; n++) {
100
+ if (imm & (1 << n)) {
101
+ imm64 |= (0xffULL << (n * 8));
102
+ }
103
+ }
104
+ return imm64;
105
+ }
106
+ imm |= (imm << 8) | (imm << 16) | (imm << 24);
107
+ break;
108
+ case 15:
109
+ imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
110
+ | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
111
+ break;
112
+ }
113
+ if (op) {
114
+ imm = ~imm;
115
+ }
116
+ return dup_const(MO_32, imm);
117
+}
118
+
119
+static bool do_1reg_imm(DisasContext *s, arg_1reg_imm *a,
120
+ GVecGen2iFn *fn)
121
+{
122
+ uint64_t imm;
123
+ int reg_ofs, vec_size;
124
+
125
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
126
+ return false;
127
+ }
128
+
129
+ /* UNDEF accesses to D16-D31 if they don't exist. */
130
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
131
+ return false;
132
+ }
133
+
134
+ if (a->vd & a->q) {
135
+ return false;
136
+ }
137
+
138
+ if (!vfp_access_check(s)) {
139
+ return true;
140
+ }
141
+
142
+ reg_ofs = neon_reg_offset(a->vd, 0);
143
+ vec_size = a->q ? 16 : 8;
144
+ imm = asimd_imm_const(a->imm, a->cmode, a->op);
145
+
146
+ fn(MO_64, reg_ofs, reg_ofs, imm, vec_size, vec_size);
147
+ return true;
148
+}
149
+
150
+static void gen_VMOV_1r(unsigned vece, uint32_t dofs, uint32_t aofs,
151
+ int64_t c, uint32_t oprsz, uint32_t maxsz)
152
+{
153
+ tcg_gen_gvec_dup_imm(MO_64, dofs, oprsz, maxsz, c);
154
+}
155
+
156
+static bool trans_Vimm_1r(DisasContext *s, arg_1reg_imm *a)
157
+{
158
+ /* Handle decode of cmode/op here between VORR/VBIC/VMOV */
159
+ GVecGen2iFn *fn;
160
+
161
+ if ((a->cmode & 1) && a->cmode < 12) {
162
+ /* for op=1, the imm will be inverted, so BIC becomes AND. */
163
+ fn = a->op ? tcg_gen_gvec_andi : tcg_gen_gvec_ori;
164
+ } else {
165
+ /* There is one unallocated cmode/op combination in this space */
166
+ if (a->cmode == 15 && a->op == 1) {
167
+ return false;
168
+ }
169
+ fn = gen_VMOV_1r;
170
+ }
171
+ return do_1reg_imm(s, a, fn);
172
+}
173
diff --git a/target/arm/translate.c b/target/arm/translate.c
174
index XXXXXXX..XXXXXXX 100644
175
--- a/target/arm/translate.c
176
+++ b/target/arm/translate.c
177
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
178
/* Three register same length: handled by decodetree */
179
return 1;
180
} else if (insn & (1 << 4)) {
181
- if ((insn & 0x00380080) != 0) {
182
- /* Two registers and shift: handled by decodetree */
183
- return 1;
184
- } else { /* (insn & 0x00380080) == 0 */
185
- int invert, reg_ofs, vec_size;
186
-
187
- if (q && (rd & 1)) {
188
- return 1;
189
- }
190
-
191
- op = (insn >> 8) & 0xf;
192
- /* One register and immediate. */
193
- imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
194
- invert = (insn & (1 << 5)) != 0;
195
- /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
196
- * We choose to not special-case this and will behave as if a
197
- * valid constant encoding of 0 had been given.
198
- */
199
- switch (op) {
200
- case 0: case 1:
201
- /* no-op */
202
- break;
203
- case 2: case 3:
204
- imm <<= 8;
205
- break;
206
- case 4: case 5:
207
- imm <<= 16;
208
- break;
209
- case 6: case 7:
210
- imm <<= 24;
211
- break;
212
- case 8: case 9:
213
- imm |= imm << 16;
214
- break;
215
- case 10: case 11:
216
- imm = (imm << 8) | (imm << 24);
217
- break;
218
- case 12:
219
- imm = (imm << 8) | 0xff;
220
- break;
221
- case 13:
222
- imm = (imm << 16) | 0xffff;
223
- break;
224
- case 14:
225
- imm |= (imm << 8) | (imm << 16) | (imm << 24);
226
- if (invert) {
227
- imm = ~imm;
228
- }
229
- break;
230
- case 15:
231
- if (invert) {
232
- return 1;
233
- }
234
- imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
235
- | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
236
- break;
237
- }
238
- if (invert) {
239
- imm = ~imm;
240
- }
241
-
242
- reg_ofs = neon_reg_offset(rd, 0);
243
- vec_size = q ? 16 : 8;
244
-
245
- if (op & 1 && op < 12) {
246
- if (invert) {
247
- /* The immediate value has already been inverted,
248
- * so BIC becomes AND.
249
- */
250
- tcg_gen_gvec_andi(MO_32, reg_ofs, reg_ofs, imm,
251
- vec_size, vec_size);
252
- } else {
253
- tcg_gen_gvec_ori(MO_32, reg_ofs, reg_ofs, imm,
254
- vec_size, vec_size);
255
- }
256
- } else {
257
- /* VMOV, VMVN. */
258
- if (op == 14 && invert) {
259
- TCGv_i64 t64 = tcg_temp_new_i64();
260
-
261
- for (pass = 0; pass <= q; ++pass) {
262
- uint64_t val = 0;
263
- int n;
264
-
265
- for (n = 0; n < 8; n++) {
266
- if (imm & (1 << (n + pass * 8))) {
267
- val |= 0xffull << (n * 8);
268
- }
269
- }
270
- tcg_gen_movi_i64(t64, val);
271
- neon_store_reg64(t64, rd + pass);
272
- }
273
- tcg_temp_free_i64(t64);
274
- } else {
275
- tcg_gen_gvec_dup_imm(MO_32, reg_ofs, vec_size,
276
- vec_size, imm);
277
- }
278
- }
279
- }
280
+ /* Two registers and shift or reg and imm: handled by decodetree */
281
+ return 1;
282
} else { /* (insn & 0x00800010 == 0x00800000) */
283
if (size != 3) {
284
op = (insn >> 8) & 0xf;
285
--
26
--
286
2.20.1
27
2.20.1
287
28
288
29
diff view generated by jsdifflib
1
Convert the VCVT fixed-point conversion operations in the
1
When we first converted our documentation to Sphinx, we split it into
2
Neon 2-regs-and-shift group to decodetree.
2
multiple manuals (system, interop, tools, etc), which are all built
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.
3
36
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
37
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
38
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
6
Message-id: 20200522145520.6778-9-peter.maydell@linaro.org
39
Message-id: 20210108161416.21129-3-peter.maydell@linaro.org
7
---
40
---
8
target/arm/neon-dp.decode | 11 +++++
41
docs/conf.py | 46 ++++++++++++++++++++++++++++++-
9
target/arm/translate-neon.inc.c | 49 +++++++++++++++++++++
42
docs/devel/conf.py | 15 -----------
10
target/arm/translate.c | 75 +--------------------------------
43
docs/index.html.in | 17 ------------
11
3 files changed, 62 insertions(+), 73 deletions(-)
44
docs/interop/conf.py | 28 -------------------
12
45
docs/meson.build | 64 +++++++++++++++++---------------------------
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
46
docs/specs/conf.py | 16 -----------
47
docs/system/conf.py | 28 -------------------
48
docs/tools/conf.py | 37 -------------------------
49
docs/user/conf.py | 15 -----------
50
9 files changed, 70 insertions(+), 196 deletions(-)
51
delete mode 100644 docs/devel/conf.py
52
delete mode 100644 docs/index.html.in
53
delete mode 100644 docs/interop/conf.py
54
delete mode 100644 docs/specs/conf.py
55
delete mode 100644 docs/system/conf.py
56
delete mode 100644 docs/tools/conf.py
57
delete mode 100644 docs/user/conf.py
58
59
diff --git a/docs/conf.py b/docs/conf.py
14
index XXXXXXX..XXXXXXX 100644
60
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
61
--- a/docs/conf.py
16
+++ b/target/arm/neon-dp.decode
62
+++ b/docs/conf.py
17
@@ -XXX,XX +XXX,XX @@ VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
63
@@ -XXX,XX +XXX,XX @@ latex_documents = [
18
@2reg_shll_b .... ... . . . 001 shift:3 .... .... 0 . . . .... \
64
19
&2reg_shift vm=%vm_dp vd=%vd_dp size=0 q=0
65
# -- Options for manual page output ---------------------------------------
20
66
# Individual manual/conf.py can override this to create man pages
21
+# We use size=0 for fp32 and size=1 for fp16 to match the 3-same encodings.
67
-man_pages = []
22
+@2reg_vcvt .... ... . . . 1 ..... .... .... . q:1 . . .... \
68
+man_pages = [
23
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=0 shift=%neon_rshift_i5
69
+ ('interop/qemu-ga', 'qemu-ga',
70
+ 'QEMU Guest Agent',
71
+ ['Michael Roth <mdroth@linux.vnet.ibm.com>'], 8),
72
+ ('interop/qemu-ga-ref', 'qemu-ga-ref',
73
+ 'QEMU Guest Agent Protocol Reference',
74
+ [], 7),
75
+ ('interop/qemu-qmp-ref', 'qemu-qmp-ref',
76
+ 'QEMU QMP Reference Manual',
77
+ [], 7),
78
+ ('interop/qemu-storage-daemon-qmp-ref', 'qemu-storage-daemon-qmp-ref',
79
+ 'QEMU Storage Daemon QMP Reference Manual',
80
+ [], 7),
81
+ ('system/qemu-manpage', 'qemu',
82
+ 'QEMU User Documentation',
83
+ ['Fabrice Bellard'], 1),
84
+ ('system/qemu-block-drivers', 'qemu-block-drivers',
85
+ 'QEMU block drivers reference',
86
+ ['Fabrice Bellard and the QEMU Project developers'], 7),
87
+ ('system/qemu-cpu-models', 'qemu-cpu-models',
88
+ 'QEMU CPU Models',
89
+ ['The QEMU Project developers'], 7),
90
+ ('tools/qemu-img', 'qemu-img',
91
+ 'QEMU disk image utility',
92
+ ['Fabrice Bellard'], 1),
93
+ ('tools/qemu-nbd', 'qemu-nbd',
94
+ 'QEMU Disk Network Block Device Server',
95
+ ['Anthony Liguori <anthony@codemonkey.ws>'], 8),
96
+ ('tools/qemu-pr-helper', 'qemu-pr-helper',
97
+ 'QEMU persistent reservation helper',
98
+ [], 8),
99
+ ('tools/qemu-storage-daemon', 'qemu-storage-daemon',
100
+ 'QEMU storage daemon',
101
+ [], 1),
102
+ ('tools/qemu-trace-stap', 'qemu-trace-stap',
103
+ 'QEMU SystemTap trace tool',
104
+ [], 1),
105
+ ('tools/virtfs-proxy-helper', 'virtfs-proxy-helper',
106
+ 'QEMU 9p virtfs proxy filesystem helper',
107
+ ['M. Mohan Kumar'], 1),
108
+ ('tools/virtiofsd', 'virtiofsd',
109
+ 'QEMU virtio-fs shared file system daemon',
110
+ ['Stefan Hajnoczi <stefanha@redhat.com>',
111
+ 'Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>'], 1),
112
+]
113
114
# -- Options for Texinfo output -------------------------------------------
115
116
diff --git a/docs/devel/conf.py b/docs/devel/conf.py
117
deleted file mode 100644
118
index XXXXXXX..XXXXXXX
119
--- a/docs/devel/conf.py
120
+++ /dev/null
121
@@ -XXX,XX +XXX,XX @@
122
-# -*- coding: utf-8 -*-
123
-#
124
-# QEMU documentation build configuration file for the 'devel' manual.
125
-#
126
-# This includes the top level conf file and then makes any necessary tweaks.
127
-import sys
128
-import os
129
-
130
-qemu_docdir = os.path.abspath("..")
131
-parent_config = os.path.join(qemu_docdir, "conf.py")
132
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
133
-
134
-# This slightly misuses the 'description', but is the best way to get
135
-# the manual title to appear in the sidebar.
136
-html_theme_options['description'] = u'Developer''s Guide'
137
diff --git a/docs/index.html.in b/docs/index.html.in
138
deleted file mode 100644
139
index XXXXXXX..XXXXXXX
140
--- a/docs/index.html.in
141
+++ /dev/null
142
@@ -XXX,XX +XXX,XX @@
143
-<!DOCTYPE html>
144
-<html lang="en">
145
- <head>
146
- <meta charset="UTF-8">
147
- <title>QEMU @VERSION@ Documentation</title>
148
- </head>
149
- <body>
150
- <h1>QEMU @VERSION@ Documentation</h1>
151
- <ul>
152
- <li><a href="system/index.html">System Emulation User's Guide</a></li>
153
- <li><a href="user/index.html">User Mode Emulation User's Guide</a></li>
154
- <li><a href="tools/index.html">Tools Guide</a></li>
155
- <li><a href="interop/index.html">System Emulation Management and Interoperability Guide</a></li>
156
- <li><a href="specs/index.html">System Emulation Guest Hardware Specifications</a></li>
157
- </ul>
158
- </body>
159
-</html>
160
diff --git a/docs/interop/conf.py b/docs/interop/conf.py
161
deleted file mode 100644
162
index XXXXXXX..XXXXXXX
163
--- a/docs/interop/conf.py
164
+++ /dev/null
165
@@ -XXX,XX +XXX,XX @@
166
-# -*- coding: utf-8 -*-
167
-#
168
-# QEMU documentation build configuration file for the 'interop' manual.
169
-#
170
-# This includes the top level conf file and then makes any necessary tweaks.
171
-import sys
172
-import os
173
-
174
-qemu_docdir = os.path.abspath("..")
175
-parent_config = os.path.join(qemu_docdir, "conf.py")
176
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
177
-
178
-# This slightly misuses the 'description', but is the best way to get
179
-# the manual title to appear in the sidebar.
180
-html_theme_options['description'] = u'System Emulation Management and Interoperability Guide'
181
-
182
-# One entry per manual page. List of tuples
183
-# (source start file, name, description, authors, manual section).
184
-man_pages = [
185
- ('qemu-ga', 'qemu-ga', u'QEMU Guest Agent',
186
- ['Michael Roth <mdroth@linux.vnet.ibm.com>'], 8),
187
- ('qemu-ga-ref', 'qemu-ga-ref', 'QEMU Guest Agent Protocol Reference',
188
- [], 7),
189
- ('qemu-qmp-ref', 'qemu-qmp-ref', 'QEMU QMP Reference Manual',
190
- [], 7),
191
- ('qemu-storage-daemon-qmp-ref', 'qemu-storage-daemon-qmp-ref',
192
- 'QEMU Storage Daemon QMP Reference Manual', [], 7),
193
-]
194
diff --git a/docs/meson.build b/docs/meson.build
195
index XXXXXXX..XXXXXXX 100644
196
--- a/docs/meson.build
197
+++ b/docs/meson.build
198
@@ -XXX,XX +XXX,XX @@ if build_docs
199
meson.source_root() / 'docs/sphinx/qmp_lexer.py',
200
qapi_gen_depends ]
201
202
- configure_file(output: 'index.html',
203
- input: files('index.html.in'),
204
- configuration: {'VERSION': meson.project_version()},
205
- install_dir: qemu_docdir)
206
- manuals = [ 'devel', 'interop', 'tools', 'specs', 'system', 'user' ]
207
man_pages = {
208
- 'interop' : {
209
'qemu-ga.8': (have_tools ? 'man8' : ''),
210
'qemu-ga-ref.7': 'man7',
211
'qemu-qmp-ref.7': 'man7',
212
'qemu-storage-daemon-qmp-ref.7': (have_tools ? 'man7' : ''),
213
- },
214
- 'tools': {
215
'qemu-img.1': (have_tools ? 'man1' : ''),
216
'qemu-nbd.8': (have_tools ? 'man8' : ''),
217
'qemu-pr-helper.8': (have_tools ? 'man8' : ''),
218
@@ -XXX,XX +XXX,XX @@ if build_docs
219
'qemu-trace-stap.1': (config_host.has_key('CONFIG_TRACE_SYSTEMTAP') ? 'man1' : ''),
220
'virtfs-proxy-helper.1': (have_virtfs_proxy_helper ? 'man1' : ''),
221
'virtiofsd.1': (have_virtiofsd ? 'man1' : ''),
222
- },
223
- 'system': {
224
'qemu.1': 'man1',
225
'qemu-block-drivers.7': 'man7',
226
'qemu-cpu-models.7': 'man7'
227
- },
228
}
229
230
sphinxdocs = []
231
sphinxmans = []
232
- foreach manual : manuals
233
- private_dir = meson.current_build_dir() / (manual + '.p')
234
- output_dir = meson.current_build_dir() / manual
235
- input_dir = meson.current_source_dir() / manual
236
237
- this_manual = custom_target(manual + ' manual',
238
+ private_dir = meson.current_build_dir() / 'manual.p'
239
+ output_dir = meson.current_build_dir() / 'manual'
240
+ input_dir = meson.current_source_dir()
24
+
241
+
25
VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_d
242
+ this_manual = custom_target('QEMU manual',
26
VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_s
243
build_by_default: build_docs,
27
VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_h
244
- output: [manual + '.stamp'],
28
@@ -XXX,XX +XXX,XX @@ VSHLL_S_2sh 1111 001 0 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_b
245
- input: [files('conf.py'), files(manual / 'conf.py')],
29
VSHLL_U_2sh 1111 001 1 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_s
246
- depfile: manual + '.d',
30
VSHLL_U_2sh 1111 001 1 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_h
247
+ output: 'docs.stamp',
31
VSHLL_U_2sh 1111 001 1 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_b
248
+ input: files('conf.py'),
249
+ depfile: 'docs.d',
250
depend_files: sphinx_extn_depends,
251
command: [SPHINX_ARGS, '-Ddepfile=@DEPFILE@',
252
'-Ddepfile_stamp=@OUTPUT0@',
253
'-b', 'html', '-d', private_dir,
254
input_dir, output_dir])
255
- sphinxdocs += this_manual
256
- if build_docs and manual != 'devel'
257
- install_subdir(output_dir, install_dir: qemu_docdir)
258
- endif
259
+ sphinxdocs += this_manual
260
+ install_subdir(output_dir, install_dir: qemu_docdir, strip_directory: true)
261
262
- these_man_pages = []
263
- install_dirs = []
264
- foreach page, section : man_pages.get(manual, {})
265
- these_man_pages += page
266
- install_dirs += section == '' ? false : get_option('mandir') / section
267
- endforeach
268
- if these_man_pages.length() > 0
269
- sphinxmans += custom_target(manual + ' man pages',
270
- build_by_default: build_docs,
271
- output: these_man_pages,
272
- input: this_manual,
273
- install: build_docs,
274
- install_dir: install_dirs,
275
- command: [SPHINX_ARGS, '-b', 'man', '-d', private_dir,
276
- input_dir, meson.current_build_dir()])
277
- endif
278
+ these_man_pages = []
279
+ install_dirs = []
280
+ foreach page, section : man_pages
281
+ these_man_pages += page
282
+ install_dirs += section == '' ? false : get_option('mandir') / section
283
endforeach
32
+
284
+
33
+# VCVT fixed<->float conversions
285
+ sphinxmans += custom_target('QEMU man pages',
34
+# TODO: FP16 fixed<->float conversions are opc==0b1100 and 0b1101
286
+ build_by_default: build_docs,
35
+VCVT_SF_2sh 1111 001 0 1 . ...... .... 1110 0 . . 1 .... @2reg_vcvt
287
+ output: these_man_pages,
36
+VCVT_UF_2sh 1111 001 1 1 . ...... .... 1110 0 . . 1 .... @2reg_vcvt
288
+ input: this_manual,
37
+VCVT_FS_2sh 1111 001 0 1 . ...... .... 1111 0 . . 1 .... @2reg_vcvt
289
+ install: build_docs,
38
+VCVT_FU_2sh 1111 001 1 1 . ...... .... 1111 0 . . 1 .... @2reg_vcvt
290
+ install_dir: install_dirs,
39
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
291
+ command: [SPHINX_ARGS, '-b', 'man', '-d', private_dir,
40
index XXXXXXX..XXXXXXX 100644
292
+ input_dir, meson.current_build_dir()])
41
--- a/target/arm/translate-neon.inc.c
42
+++ b/target/arm/translate-neon.inc.c
43
@@ -XXX,XX +XXX,XX @@ static bool trans_VSHLL_U_2sh(DisasContext *s, arg_2reg_shift *a)
44
};
45
return do_vshll_2sh(s, a, widenfn[a->size], true);
46
}
47
+
293
+
48
+static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a,
294
alias_target('sphinxdocs', sphinxdocs)
49
+ NeonGenTwoSingleOPFn *fn)
295
alias_target('html', sphinxdocs)
50
+{
296
alias_target('man', sphinxmans)
51
+ /* FP operations in 2-reg-and-shift group */
297
diff --git a/docs/specs/conf.py b/docs/specs/conf.py
52
+ TCGv_i32 tmp, shiftv;
298
deleted file mode 100644
53
+ TCGv_ptr fpstatus;
299
index XXXXXXX..XXXXXXX
54
+ int pass;
300
--- a/docs/specs/conf.py
55
+
301
+++ /dev/null
56
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
302
@@ -XXX,XX +XXX,XX @@
57
+ return false;
303
-# -*- coding: utf-8 -*-
58
+ }
304
-#
59
+
305
-# QEMU documentation build configuration file for the 'specs' manual.
60
+ /* UNDEF accesses to D16-D31 if they don't exist. */
306
-#
61
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
307
-# This includes the top level conf file and then makes any necessary tweaks.
62
+ ((a->vd | a->vm) & 0x10)) {
308
-import sys
63
+ return false;
309
-import os
64
+ }
310
-
65
+
311
-qemu_docdir = os.path.abspath("..")
66
+ if ((a->vm | a->vd) & a->q) {
312
-parent_config = os.path.join(qemu_docdir, "conf.py")
67
+ return false;
313
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
68
+ }
314
-
69
+
315
-# This slightly misuses the 'description', but is the best way to get
70
+ if (!vfp_access_check(s)) {
316
-# the manual title to appear in the sidebar.
71
+ return true;
317
-html_theme_options['description'] = \
72
+ }
318
- u'System Emulation Guest Hardware Specifications'
73
+
319
diff --git a/docs/system/conf.py b/docs/system/conf.py
74
+ fpstatus = get_fpstatus_ptr(1);
320
deleted file mode 100644
75
+ shiftv = tcg_const_i32(a->shift);
321
index XXXXXXX..XXXXXXX
76
+ for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
322
--- a/docs/system/conf.py
77
+ tmp = neon_load_reg(a->vm, pass);
323
+++ /dev/null
78
+ fn(tmp, tmp, shiftv, fpstatus);
324
@@ -XXX,XX +XXX,XX @@
79
+ neon_store_reg(a->vd, pass, tmp);
325
-# -*- coding: utf-8 -*-
80
+ }
326
-#
81
+ tcg_temp_free_ptr(fpstatus);
327
-# QEMU documentation build configuration file for the 'system' manual.
82
+ tcg_temp_free_i32(shiftv);
328
-#
83
+ return true;
329
-# This includes the top level conf file and then makes any necessary tweaks.
84
+}
330
-import sys
85
+
331
-import os
86
+#define DO_FP_2SH(INSN, FUNC) \
332
-
87
+ static bool trans_##INSN##_2sh(DisasContext *s, arg_2reg_shift *a) \
333
-qemu_docdir = os.path.abspath("..")
88
+ { \
334
-parent_config = os.path.join(qemu_docdir, "conf.py")
89
+ return do_fp_2sh(s, a, FUNC); \
335
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
90
+ }
336
-
91
+
337
-# This slightly misuses the 'description', but is the best way to get
92
+DO_FP_2SH(VCVT_SF, gen_helper_vfp_sltos)
338
-# the manual title to appear in the sidebar.
93
+DO_FP_2SH(VCVT_UF, gen_helper_vfp_ultos)
339
-html_theme_options['description'] = u'System Emulation User''s Guide'
94
+DO_FP_2SH(VCVT_FS, gen_helper_vfp_tosls_round_to_zero)
340
-
95
+DO_FP_2SH(VCVT_FU, gen_helper_vfp_touls_round_to_zero)
341
-# One entry per manual page. List of tuples
96
diff --git a/target/arm/translate.c b/target/arm/translate.c
342
-# (source start file, name, description, authors, manual section).
97
index XXXXXXX..XXXXXXX 100644
343
-man_pages = [
98
--- a/target/arm/translate.c
344
- ('qemu-manpage', 'qemu', u'QEMU User Documentation',
99
+++ b/target/arm/translate.c
345
- ['Fabrice Bellard'], 1),
100
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
346
- ('qemu-block-drivers', 'qemu-block-drivers',
101
int q;
347
- u'QEMU block drivers reference',
102
int rd, rn, rm, rd_ofs, rn_ofs, rm_ofs;
348
- ['Fabrice Bellard and the QEMU Project developers'], 7),
103
int size;
349
- ('qemu-cpu-models', 'qemu-cpu-models',
104
- int shift;
350
- u'QEMU CPU Models',
105
int pass;
351
- ['The QEMU Project developers'], 7)
106
int u;
352
-]
107
int vec_size;
353
diff --git a/docs/tools/conf.py b/docs/tools/conf.py
108
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
354
deleted file mode 100644
109
return 1;
355
index XXXXXXX..XXXXXXX
110
} else if (insn & (1 << 4)) {
356
--- a/docs/tools/conf.py
111
if ((insn & 0x00380080) != 0) {
357
+++ /dev/null
112
- /* Two registers and shift. */
358
@@ -XXX,XX +XXX,XX @@
113
- op = (insn >> 8) & 0xf;
359
-# -*- coding: utf-8 -*-
114
-
360
-#
115
- switch (op) {
361
-# QEMU documentation build configuration file for the 'tools' manual.
116
- case 0: /* VSHR */
362
-#
117
- case 1: /* VSRA */
363
-# This includes the top level conf file and then makes any necessary tweaks.
118
- case 2: /* VRSHR */
364
-import sys
119
- case 3: /* VRSRA */
365
-import os
120
- case 4: /* VSRI */
366
-
121
- case 5: /* VSHL, VSLI */
367
-qemu_docdir = os.path.abspath("..")
122
- case 6: /* VQSHLU */
368
-parent_config = os.path.join(qemu_docdir, "conf.py")
123
- case 7: /* VQSHL */
369
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
124
- case 8: /* VSHRN, VRSHRN, VQSHRUN, VQRSHRUN */
370
-
125
- case 9: /* VQSHRN, VQRSHRN */
371
-# This slightly misuses the 'description', but is the best way to get
126
- case 10: /* VSHLL, including VMOVL */
372
-# the manual title to appear in the sidebar.
127
- return 1; /* handled by decodetree */
373
-html_theme_options['description'] = \
128
- default:
374
- u'Tools Guide'
129
- break;
375
-
130
- }
376
-# One entry per manual page. List of tuples
131
-
377
-# (source start file, name, description, authors, manual section).
132
- if (insn & (1 << 7)) {
378
-man_pages = [
133
- /* 64-bit shift. */
379
- ('qemu-img', 'qemu-img', u'QEMU disk image utility',
134
- if (op > 7) {
380
- ['Fabrice Bellard'], 1),
135
- return 1;
381
- ('qemu-storage-daemon', 'qemu-storage-daemon', u'QEMU storage daemon',
136
- }
382
- [], 1),
137
- size = 3;
383
- ('qemu-nbd', 'qemu-nbd', u'QEMU Disk Network Block Device Server',
138
- } else {
384
- ['Anthony Liguori <anthony@codemonkey.ws>'], 8),
139
- size = 2;
385
- ('qemu-pr-helper', 'qemu-pr-helper', 'QEMU persistent reservation helper',
140
- while ((insn & (1 << (size + 19))) == 0)
386
- [], 8),
141
- size--;
387
- ('qemu-trace-stap', 'qemu-trace-stap', u'QEMU SystemTap trace tool',
142
- }
388
- [], 1),
143
- shift = (insn >> 16) & ((1 << (3 + size)) - 1);
389
- ('virtfs-proxy-helper', 'virtfs-proxy-helper',
144
- if (op >= 14) {
390
- u'QEMU 9p virtfs proxy filesystem helper',
145
- /* VCVT fixed-point. */
391
- ['M. Mohan Kumar'], 1),
146
- TCGv_ptr fpst;
392
- ('virtiofsd', 'virtiofsd', u'QEMU virtio-fs shared file system daemon',
147
- TCGv_i32 shiftv;
393
- ['Stefan Hajnoczi <stefanha@redhat.com>',
148
- VFPGenFixPointFn *fn;
394
- 'Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>'], 1),
149
-
395
-]
150
- if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
396
diff --git a/docs/user/conf.py b/docs/user/conf.py
151
- return 1;
397
deleted file mode 100644
152
- }
398
index XXXXXXX..XXXXXXX
153
-
399
--- a/docs/user/conf.py
154
- if (!(op & 1)) {
400
+++ /dev/null
155
- if (u) {
401
@@ -XXX,XX +XXX,XX @@
156
- fn = gen_helper_vfp_ultos;
402
-# -*- coding: utf-8 -*-
157
- } else {
403
-#
158
- fn = gen_helper_vfp_sltos;
404
-# QEMU documentation build configuration file for the 'user' manual.
159
- }
405
-#
160
- } else {
406
-# This includes the top level conf file and then makes any necessary tweaks.
161
- if (u) {
407
-import sys
162
- fn = gen_helper_vfp_touls_round_to_zero;
408
-import os
163
- } else {
409
-
164
- fn = gen_helper_vfp_tosls_round_to_zero;
410
-qemu_docdir = os.path.abspath("..")
165
- }
411
-parent_config = os.path.join(qemu_docdir, "conf.py")
166
- }
412
-exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
167
-
413
-
168
- /* We have already masked out the must-be-1 top bit of imm6,
414
-# This slightly misuses the 'description', but is the best way to get
169
- * hence this 32-shift where the ARM ARM has 64-imm6.
415
-# the manual title to appear in the sidebar.
170
- */
416
-html_theme_options['description'] = u'User Mode Emulation User''s Guide'
171
- shift = 32 - shift;
172
- fpst = get_fpstatus_ptr(1);
173
- shiftv = tcg_const_i32(shift);
174
- for (pass = 0; pass < (q ? 4 : 2); pass++) {
175
- TCGv_i32 tmpf = neon_load_reg(rm, pass);
176
- fn(tmpf, tmpf, shiftv, fpst);
177
- neon_store_reg(rd, pass, tmpf);
178
- }
179
- tcg_temp_free_ptr(fpst);
180
- tcg_temp_free_i32(shiftv);
181
- } else {
182
- return 1;
183
- }
184
+ /* Two registers and shift: handled by decodetree */
185
+ return 1;
186
} else { /* (insn & 0x00380080) == 0 */
187
int invert, reg_ofs, vec_size;
188
189
--
417
--
190
2.20.1
418
2.20.1
191
419
192
420
diff view generated by jsdifflib
1
Convert the VSHLL and VMOVL insns from the 2-reg-shift group
1
In commit cd8be50e58f63413c0 we converted the A32 coprocessor
2
to decodetree. Since the loop always has two passes, we unroll
2
insns to decodetree. This accidentally broke XScale/iWMMXt insns,
3
it to avoid the awkward reassignment of one TCGv to another.
3
because it moved the handling of "cp insns which are handled
4
by looking up the cp register in the hashtable" from after the
5
call to the legacy disas_xscale_insn() decode to before it,
6
with the result that all XScale/iWMMXt insns now UNDEF.
4
7
8
Update valid_cp() so that it knows that on XScale cp 0 and 1
9
are not standard coprocessor instructions; this will cause
10
the decodetree trans_ functions to ignore them, so that
11
execution will correctly get through to the legacy decode again.
12
13
Cc: qemu-stable@nongnu.org
14
Reported-by: Guenter Roeck <linux@roeck-us.net>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200522145520.6778-8-peter.maydell@linaro.org
17
Tested-by: Guenter Roeck <linux@roeck-us.net>
18
Message-id: 20210108195157.32067-1-peter.maydell@linaro.org
8
---
19
---
9
target/arm/neon-dp.decode | 16 +++++++
20
target/arm/translate.c | 7 +++++++
10
target/arm/translate-neon.inc.c | 81 +++++++++++++++++++++++++++++++++
21
1 file changed, 7 insertions(+)
11
target/arm/translate.c | 46 +------------------
12
3 files changed, 99 insertions(+), 44 deletions(-)
13
22
14
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/neon-dp.decode
17
+++ b/target/arm/neon-dp.decode
18
@@ -XXX,XX +XXX,XX @@ VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
19
&2reg_shift vm=%vm_dp vd=%vd_dp size=1 q=0 \
20
shift=%neon_rshift_i3
21
22
+# Long left shifts: again Q is part of opcode decode
23
+@2reg_shll_s .... ... . . . 1 shift:5 .... .... 0 . . . .... \
24
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=2 q=0
25
+@2reg_shll_h .... ... . . . 01 shift:4 .... .... 0 . . . .... \
26
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=1 q=0
27
+@2reg_shll_b .... ... . . . 001 shift:3 .... .... 0 . . . .... \
28
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=0 q=0
29
+
30
VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_d
31
VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_s
32
VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_h
33
@@ -XXX,XX +XXX,XX @@ VQSHRN_U16_2sh 1111 001 1 1 . ...... .... 1001 . 0 . 1 .... @2reg_shrn_h
34
VQRSHRN_U64_2sh 1111 001 1 1 . ...... .... 1001 . 1 . 1 .... @2reg_shrn_d
35
VQRSHRN_U32_2sh 1111 001 1 1 . ...... .... 1001 . 1 . 1 .... @2reg_shrn_s
36
VQRSHRN_U16_2sh 1111 001 1 1 . ...... .... 1001 . 1 . 1 .... @2reg_shrn_h
37
+
38
+VSHLL_S_2sh 1111 001 0 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_s
39
+VSHLL_S_2sh 1111 001 0 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_h
40
+VSHLL_S_2sh 1111 001 0 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_b
41
+
42
+VSHLL_U_2sh 1111 001 1 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_s
43
+VSHLL_U_2sh 1111 001 1 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_h
44
+VSHLL_U_2sh 1111 001 1 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_b
45
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/translate-neon.inc.c
48
+++ b/target/arm/translate-neon.inc.c
49
@@ -XXX,XX +XXX,XX @@ DO_2SN_32(VQSHRN_U16, gen_helper_neon_shl_u16, gen_helper_neon_narrow_sat_u8)
50
DO_2SN_64(VQRSHRN_U64, gen_helper_neon_rshl_u64, gen_helper_neon_narrow_sat_u32)
51
DO_2SN_32(VQRSHRN_U32, gen_helper_neon_rshl_u32, gen_helper_neon_narrow_sat_u16)
52
DO_2SN_32(VQRSHRN_U16, gen_helper_neon_rshl_u16, gen_helper_neon_narrow_sat_u8)
53
+
54
+static bool do_vshll_2sh(DisasContext *s, arg_2reg_shift *a,
55
+ NeonGenWidenFn *widenfn, bool u)
56
+{
57
+ TCGv_i64 tmp;
58
+ TCGv_i32 rm0, rm1;
59
+ uint64_t widen_mask = 0;
60
+
61
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
62
+ return false;
63
+ }
64
+
65
+ /* UNDEF accesses to D16-D31 if they don't exist. */
66
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
67
+ ((a->vd | a->vm) & 0x10)) {
68
+ return false;
69
+ }
70
+
71
+ if (a->vd & 1) {
72
+ return false;
73
+ }
74
+
75
+ if (!vfp_access_check(s)) {
76
+ return true;
77
+ }
78
+
79
+ /*
80
+ * This is a widen-and-shift operation. The shift is always less
81
+ * than the width of the source type, so after widening the input
82
+ * vector we can simply shift the whole 64-bit widened register,
83
+ * and then clear the potential overflow bits resulting from left
84
+ * bits of the narrow input appearing as right bits of the left
85
+ * neighbour narrow input. Calculate a mask of bits to clear.
86
+ */
87
+ if ((a->shift != 0) && (a->size < 2 || u)) {
88
+ int esize = 8 << a->size;
89
+ widen_mask = MAKE_64BIT_MASK(0, esize);
90
+ widen_mask >>= esize - a->shift;
91
+ widen_mask = dup_const(a->size + 1, widen_mask);
92
+ }
93
+
94
+ rm0 = neon_load_reg(a->vm, 0);
95
+ rm1 = neon_load_reg(a->vm, 1);
96
+ tmp = tcg_temp_new_i64();
97
+
98
+ widenfn(tmp, rm0);
99
+ if (a->shift != 0) {
100
+ tcg_gen_shli_i64(tmp, tmp, a->shift);
101
+ tcg_gen_andi_i64(tmp, tmp, ~widen_mask);
102
+ }
103
+ neon_store_reg64(tmp, a->vd);
104
+
105
+ widenfn(tmp, rm1);
106
+ if (a->shift != 0) {
107
+ tcg_gen_shli_i64(tmp, tmp, a->shift);
108
+ tcg_gen_andi_i64(tmp, tmp, ~widen_mask);
109
+ }
110
+ neon_store_reg64(tmp, a->vd + 1);
111
+ tcg_temp_free_i64(tmp);
112
+ return true;
113
+}
114
+
115
+static bool trans_VSHLL_S_2sh(DisasContext *s, arg_2reg_shift *a)
116
+{
117
+ NeonGenWidenFn *widenfn[] = {
118
+ gen_helper_neon_widen_s8,
119
+ gen_helper_neon_widen_s16,
120
+ tcg_gen_ext_i32_i64,
121
+ };
122
+ return do_vshll_2sh(s, a, widenfn[a->size], false);
123
+}
124
+
125
+static bool trans_VSHLL_U_2sh(DisasContext *s, arg_2reg_shift *a)
126
+{
127
+ NeonGenWidenFn *widenfn[] = {
128
+ gen_helper_neon_widen_u8,
129
+ gen_helper_neon_widen_u16,
130
+ tcg_gen_extu_i32_i64,
131
+ };
132
+ return do_vshll_2sh(s, a, widenfn[a->size], true);
133
+}
134
diff --git a/target/arm/translate.c b/target/arm/translate.c
23
diff --git a/target/arm/translate.c b/target/arm/translate.c
135
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
136
--- a/target/arm/translate.c
25
--- a/target/arm/translate.c
137
+++ b/target/arm/translate.c
26
+++ b/target/arm/translate.c
138
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
27
@@ -XXX,XX +XXX,XX @@ static bool valid_cp(DisasContext *s, int cp)
139
case 7: /* VQSHL */
28
* only cp14 and cp15 are valid, and other values aren't considered
140
case 8: /* VSHRN, VRSHRN, VQSHRUN, VQRSHRUN */
29
* to be in the coprocessor-instruction space at all. v8M still
141
case 9: /* VQSHRN, VQRSHRN */
30
* permits coprocessors 0..7.
142
+ case 10: /* VSHLL, including VMOVL */
31
+ * For XScale, we must not decode the XScale cp0, cp1 space as
143
return 1; /* handled by decodetree */
32
+ * a standard coprocessor insn, because we want to fall through to
144
default:
33
+ * the legacy disas_xscale_insn() decoder after decodetree is done.
145
break;
34
*/
146
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
35
+ if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cp == 0 || cp == 1)) {
147
size--;
36
+ return false;
148
}
37
+ }
149
shift = (insn >> 16) & ((1 << (3 + size)) - 1);
38
+
150
- if (op == 10) {
39
if (arm_dc_feature(s, ARM_FEATURE_V8) &&
151
- /* VSHLL, VMOVL */
40
!arm_dc_feature(s, ARM_FEATURE_M)) {
152
- if (q || (rd & 1)) {
41
return cp >= 14;
153
- return 1;
154
- }
155
- tmp = neon_load_reg(rm, 0);
156
- tmp2 = neon_load_reg(rm, 1);
157
- for (pass = 0; pass < 2; pass++) {
158
- if (pass == 1)
159
- tmp = tmp2;
160
-
161
- gen_neon_widen(cpu_V0, tmp, size, u);
162
-
163
- if (shift != 0) {
164
- /* The shift is less than the width of the source
165
- type, so we can just shift the whole register. */
166
- tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
167
- /* Widen the result of shift: we need to clear
168
- * the potential overflow bits resulting from
169
- * left bits of the narrow input appearing as
170
- * right bits of left the neighbour narrow
171
- * input. */
172
- if (size < 2 || !u) {
173
- uint64_t imm64;
174
- if (size == 0) {
175
- imm = (0xffu >> (8 - shift));
176
- imm |= imm << 16;
177
- } else if (size == 1) {
178
- imm = 0xffff >> (16 - shift);
179
- } else {
180
- /* size == 2 */
181
- imm = 0xffffffff >> (32 - shift);
182
- }
183
- if (size < 2) {
184
- imm64 = imm | (((uint64_t)imm) << 32);
185
- } else {
186
- imm64 = imm;
187
- }
188
- tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
189
- }
190
- }
191
- neon_store_reg64(cpu_V0, rd + pass);
192
- }
193
- } else if (op >= 14) {
194
+ if (op >= 14) {
195
/* VCVT fixed-point. */
196
TCGv_ptr fpst;
197
TCGv_i32 shiftv;
198
--
42
--
199
2.20.1
43
2.20.1
200
44
201
45
diff view generated by jsdifflib
1
Convert the remaining Neon narrowing shifts to decodetree:
1
A copy-and-paste error meant that the return value for register offset 0x44
2
* VQSHRN
2
(the RX Status FIFO PEEK register) returned a byte from a bogus offset in
3
* VQRSHRN
3
the rx status FIFO. Fix the typo.
4
4
5
Cc: qemu-stable@nongnu.org
6
Fixes: https://bugs.launchpad.net/qemu/+bug/1904954
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20200522145520.6778-7-peter.maydell@linaro.org
9
Message-id: 20210108180401.2263-2-peter.maydell@linaro.org
8
---
10
---
9
target/arm/neon-dp.decode | 20 ++++++
11
hw/net/lan9118.c | 2 +-
10
target/arm/translate-neon.inc.c | 15 +++++
12
1 file changed, 1 insertion(+), 1 deletion(-)
11
target/arm/translate.c | 110 +-------------------------------
12
3 files changed, 37 insertions(+), 108 deletions(-)
13
13
14
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
14
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/neon-dp.decode
16
--- a/hw/net/lan9118.c
17
+++ b/target/arm/neon-dp.decode
17
+++ b/hw/net/lan9118.c
18
@@ -XXX,XX +XXX,XX @@ VQSHRUN_16_2sh 1111 001 1 1 . ...... .... 1000 . 0 . 1 .... @2reg_shrn_h
18
@@ -XXX,XX +XXX,XX @@ static uint64_t lan9118_readl(void *opaque, hwaddr offset,
19
VQRSHRUN_64_2sh 1111 001 1 1 . ...... .... 1000 . 1 . 1 .... @2reg_shrn_d
19
case 0x40:
20
VQRSHRUN_32_2sh 1111 001 1 1 . ...... .... 1000 . 1 . 1 .... @2reg_shrn_s
20
return rx_status_fifo_pop(s);
21
VQRSHRUN_16_2sh 1111 001 1 1 . ...... .... 1000 . 1 . 1 .... @2reg_shrn_h
21
case 0x44:
22
+
22
- return s->rx_status_fifo[s->tx_status_fifo_head];
23
+# VQSHRN with signed input
23
+ return s->rx_status_fifo[s->rx_status_fifo_head];
24
+VQSHRN_S64_2sh 1111 001 0 1 . ...... .... 1001 . 0 . 1 .... @2reg_shrn_d
24
case 0x48:
25
+VQSHRN_S32_2sh 1111 001 0 1 . ...... .... 1001 . 0 . 1 .... @2reg_shrn_s
25
return tx_status_fifo_pop(s);
26
+VQSHRN_S16_2sh 1111 001 0 1 . ...... .... 1001 . 0 . 1 .... @2reg_shrn_h
26
case 0x4c:
27
+
28
+# VQRSHRN with signed input
29
+VQRSHRN_S64_2sh 1111 001 0 1 . ...... .... 1001 . 1 . 1 .... @2reg_shrn_d
30
+VQRSHRN_S32_2sh 1111 001 0 1 . ...... .... 1001 . 1 . 1 .... @2reg_shrn_s
31
+VQRSHRN_S16_2sh 1111 001 0 1 . ...... .... 1001 . 1 . 1 .... @2reg_shrn_h
32
+
33
+# VQSHRN with unsigned input
34
+VQSHRN_U64_2sh 1111 001 1 1 . ...... .... 1001 . 0 . 1 .... @2reg_shrn_d
35
+VQSHRN_U32_2sh 1111 001 1 1 . ...... .... 1001 . 0 . 1 .... @2reg_shrn_s
36
+VQSHRN_U16_2sh 1111 001 1 1 . ...... .... 1001 . 0 . 1 .... @2reg_shrn_h
37
+
38
+# VQRSHRN with unsigned input
39
+VQRSHRN_U64_2sh 1111 001 1 1 . ...... .... 1001 . 1 . 1 .... @2reg_shrn_d
40
+VQRSHRN_U32_2sh 1111 001 1 1 . ...... .... 1001 . 1 . 1 .... @2reg_shrn_s
41
+VQRSHRN_U16_2sh 1111 001 1 1 . ...... .... 1001 . 1 . 1 .... @2reg_shrn_h
42
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/translate-neon.inc.c
45
+++ b/target/arm/translate-neon.inc.c
46
@@ -XXX,XX +XXX,XX @@ DO_2SN_32(VQSHRUN_16, gen_helper_neon_shl_s16, gen_helper_neon_unarrow_sat8)
47
DO_2SN_64(VQRSHRUN_64, gen_helper_neon_rshl_s64, gen_helper_neon_unarrow_sat32)
48
DO_2SN_32(VQRSHRUN_32, gen_helper_neon_rshl_s32, gen_helper_neon_unarrow_sat16)
49
DO_2SN_32(VQRSHRUN_16, gen_helper_neon_rshl_s16, gen_helper_neon_unarrow_sat8)
50
+DO_2SN_64(VQSHRN_S64, gen_sshl_i64, gen_helper_neon_narrow_sat_s32)
51
+DO_2SN_32(VQSHRN_S32, gen_sshl_i32, gen_helper_neon_narrow_sat_s16)
52
+DO_2SN_32(VQSHRN_S16, gen_helper_neon_shl_s16, gen_helper_neon_narrow_sat_s8)
53
+
54
+DO_2SN_64(VQRSHRN_S64, gen_helper_neon_rshl_s64, gen_helper_neon_narrow_sat_s32)
55
+DO_2SN_32(VQRSHRN_S32, gen_helper_neon_rshl_s32, gen_helper_neon_narrow_sat_s16)
56
+DO_2SN_32(VQRSHRN_S16, gen_helper_neon_rshl_s16, gen_helper_neon_narrow_sat_s8)
57
+
58
+DO_2SN_64(VQSHRN_U64, gen_ushl_i64, gen_helper_neon_narrow_sat_u32)
59
+DO_2SN_32(VQSHRN_U32, gen_ushl_i32, gen_helper_neon_narrow_sat_u16)
60
+DO_2SN_32(VQSHRN_U16, gen_helper_neon_shl_u16, gen_helper_neon_narrow_sat_u8)
61
+
62
+DO_2SN_64(VQRSHRN_U64, gen_helper_neon_rshl_u64, gen_helper_neon_narrow_sat_u32)
63
+DO_2SN_32(VQRSHRN_U32, gen_helper_neon_rshl_u32, gen_helper_neon_narrow_sat_u16)
64
+DO_2SN_32(VQRSHRN_U16, gen_helper_neon_rshl_u16, gen_helper_neon_narrow_sat_u8)
65
diff --git a/target/arm/translate.c b/target/arm/translate.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/target/arm/translate.c
68
+++ b/target/arm/translate.c
69
@@ -XXX,XX +XXX,XX @@ static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
70
}
71
}
72
73
-static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift,
74
- int q, int u)
75
-{
76
- if (q) {
77
- if (u) {
78
- switch (size) {
79
- case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
80
- case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
81
- default: abort();
82
- }
83
- } else {
84
- switch (size) {
85
- case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
86
- case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
87
- default: abort();
88
- }
89
- }
90
- } else {
91
- if (u) {
92
- switch (size) {
93
- case 1: gen_helper_neon_shl_u16(var, var, shift); break;
94
- case 2: gen_ushl_i32(var, var, shift); break;
95
- default: abort();
96
- }
97
- } else {
98
- switch (size) {
99
- case 1: gen_helper_neon_shl_s16(var, var, shift); break;
100
- case 2: gen_sshl_i32(var, var, shift); break;
101
- default: abort();
102
- }
103
- }
104
- }
105
-}
106
-
107
static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
108
{
109
if (u) {
110
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
111
case 6: /* VQSHLU */
112
case 7: /* VQSHL */
113
case 8: /* VSHRN, VRSHRN, VQSHRUN, VQRSHRUN */
114
+ case 9: /* VQSHRN, VQRSHRN */
115
return 1; /* handled by decodetree */
116
default:
117
break;
118
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
119
size--;
120
}
121
shift = (insn >> 16) & ((1 << (3 + size)) - 1);
122
- if (op < 10) {
123
- /* Shift by immediate and narrow:
124
- VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
125
- int input_unsigned = (op == 8) ? !u : u;
126
- if (rm & 1) {
127
- return 1;
128
- }
129
- shift = shift - (1 << (size + 3));
130
- size++;
131
- if (size == 3) {
132
- tmp64 = tcg_const_i64(shift);
133
- neon_load_reg64(cpu_V0, rm);
134
- neon_load_reg64(cpu_V1, rm + 1);
135
- for (pass = 0; pass < 2; pass++) {
136
- TCGv_i64 in;
137
- if (pass == 0) {
138
- in = cpu_V0;
139
- } else {
140
- in = cpu_V1;
141
- }
142
- if (q) {
143
- if (input_unsigned) {
144
- gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
145
- } else {
146
- gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
147
- }
148
- } else {
149
- if (input_unsigned) {
150
- gen_ushl_i64(cpu_V0, in, tmp64);
151
- } else {
152
- gen_sshl_i64(cpu_V0, in, tmp64);
153
- }
154
- }
155
- tmp = tcg_temp_new_i32();
156
- gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
157
- neon_store_reg(rd, pass, tmp);
158
- } /* for pass */
159
- tcg_temp_free_i64(tmp64);
160
- } else {
161
- if (size == 1) {
162
- imm = (uint16_t)shift;
163
- imm |= imm << 16;
164
- } else {
165
- /* size == 2 */
166
- imm = (uint32_t)shift;
167
- }
168
- tmp2 = tcg_const_i32(imm);
169
- tmp4 = neon_load_reg(rm + 1, 0);
170
- tmp5 = neon_load_reg(rm + 1, 1);
171
- for (pass = 0; pass < 2; pass++) {
172
- if (pass == 0) {
173
- tmp = neon_load_reg(rm, 0);
174
- } else {
175
- tmp = tmp4;
176
- }
177
- gen_neon_shift_narrow(size, tmp, tmp2, q,
178
- input_unsigned);
179
- if (pass == 0) {
180
- tmp3 = neon_load_reg(rm, 1);
181
- } else {
182
- tmp3 = tmp5;
183
- }
184
- gen_neon_shift_narrow(size, tmp3, tmp2, q,
185
- input_unsigned);
186
- tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
187
- tcg_temp_free_i32(tmp);
188
- tcg_temp_free_i32(tmp3);
189
- tmp = tcg_temp_new_i32();
190
- gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
191
- neon_store_reg(rd, pass, tmp);
192
- } /* for pass */
193
- tcg_temp_free_i32(tmp2);
194
- }
195
- } else if (op == 10) {
196
+ if (op == 10) {
197
/* VSHLL, VMOVL */
198
if (q || (rd & 1)) {
199
return 1;
200
--
27
--
201
2.20.1
28
2.20.1
202
29
203
30
diff view generated by jsdifflib
1
Convert the Neon narrowing shifts where op==8 to decodetree:
1
The lan9118 code mostly uses symbolic constants for register offsets;
2
* VSHRN
2
the exceptions are those which the datasheet doesn't give an official
3
* VRSHRN
3
symbolic name to.
4
* VQSHRUN
4
5
* VQRSHRUN
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.
6
7
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20200522145520.6778-6-peter.maydell@linaro.org
10
Message-id: 20210108180401.2263-3-peter.maydell@linaro.org
10
---
11
---
11
target/arm/neon-dp.decode | 27 ++++++
12
hw/net/lan9118.c | 24 ++++++++++++++++++------
12
target/arm/translate-neon.inc.c | 167 ++++++++++++++++++++++++++++++++
13
1 file changed, 18 insertions(+), 6 deletions(-)
13
target/arm/translate.c | 1 +
14
3 files changed, 195 insertions(+)
15
14
16
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
15
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/neon-dp.decode
17
--- a/hw/net/lan9118.c
19
+++ b/target/arm/neon-dp.decode
18
+++ b/hw/net/lan9118.c
20
@@ -XXX,XX +XXX,XX @@ VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
19
@@ -XXX,XX +XXX,XX @@ do { hw_error("lan9118: error: " fmt , ## __VA_ARGS__);} while (0)
21
@2reg_shl_b .... ... . . . 001 shift:3 .... .... 0 q:1 . . .... \
20
do { fprintf(stderr, "lan9118: error: " fmt , ## __VA_ARGS__);} while (0)
22
&2reg_shift vm=%vm_dp vd=%vd_dp size=0
21
#endif
23
22
24
+# Narrowing right shifts: here the Q bit is part of the opcode decode
23
+/* The tx and rx fifo ports are a range of aliased 32-bit registers */
25
+@2reg_shrn_d .... ... . . . 1 ..... .... .... 0 . . . .... \
24
+#define RX_DATA_FIFO_PORT_FIRST 0x00
26
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=3 q=0 \
25
+#define RX_DATA_FIFO_PORT_LAST 0x1f
27
+ shift=%neon_rshift_i5
26
+#define TX_DATA_FIFO_PORT_FIRST 0x20
28
+@2reg_shrn_s .... ... . . . 01 .... .... .... 0 . . . .... \
27
+#define TX_DATA_FIFO_PORT_LAST 0x3f
29
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=2 q=0 \
30
+ shift=%neon_rshift_i4
31
+@2reg_shrn_h .... ... . . . 001 ... .... .... 0 . . . .... \
32
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=1 q=0 \
33
+ shift=%neon_rshift_i3
34
+
28
+
35
VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_d
29
+#define RX_STATUS_FIFO_PORT 0x40
36
VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_s
30
+#define RX_STATUS_FIFO_PEEK 0x44
37
VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_h
31
+#define TX_STATUS_FIFO_PORT 0x48
38
@@ -XXX,XX +XXX,XX @@ VQSHL_U_64_2sh 1111 001 1 1 . ...... .... 0111 . . . 1 .... @2reg_shl_d
32
+#define TX_STATUS_FIFO_PEEK 0x4c
39
VQSHL_U_2sh 1111 001 1 1 . ...... .... 0111 . . . 1 .... @2reg_shl_s
40
VQSHL_U_2sh 1111 001 1 1 . ...... .... 0111 . . . 1 .... @2reg_shl_h
41
VQSHL_U_2sh 1111 001 1 1 . ...... .... 0111 . . . 1 .... @2reg_shl_b
42
+
33
+
43
+VSHRN_64_2sh 1111 001 0 1 . ...... .... 1000 . 0 . 1 .... @2reg_shrn_d
34
#define CSR_ID_REV 0x50
44
+VSHRN_32_2sh 1111 001 0 1 . ...... .... 1000 . 0 . 1 .... @2reg_shrn_s
35
#define CSR_IRQ_CFG 0x54
45
+VSHRN_16_2sh 1111 001 0 1 . ...... .... 1000 . 0 . 1 .... @2reg_shrn_h
36
#define CSR_INT_STS 0x58
46
+
37
@@ -XXX,XX +XXX,XX @@ static void lan9118_writel(void *opaque, hwaddr offset,
47
+VRSHRN_64_2sh 1111 001 0 1 . ...... .... 1000 . 1 . 1 .... @2reg_shrn_d
38
offset &= 0xff;
48
+VRSHRN_32_2sh 1111 001 0 1 . ...... .... 1000 . 1 . 1 .... @2reg_shrn_s
39
49
+VRSHRN_16_2sh 1111 001 0 1 . ...... .... 1000 . 1 . 1 .... @2reg_shrn_h
40
//DPRINTF("Write reg 0x%02x = 0x%08x\n", (int)offset, val);
50
+
41
- if (offset >= 0x20 && offset < 0x40) {
51
+VQSHRUN_64_2sh 1111 001 1 1 . ...... .... 1000 . 0 . 1 .... @2reg_shrn_d
42
+ if (offset >= TX_DATA_FIFO_PORT_FIRST &&
52
+VQSHRUN_32_2sh 1111 001 1 1 . ...... .... 1000 . 0 . 1 .... @2reg_shrn_s
43
+ offset <= TX_DATA_FIFO_PORT_LAST) {
53
+VQSHRUN_16_2sh 1111 001 1 1 . ...... .... 1000 . 0 . 1 .... @2reg_shrn_h
44
/* TX FIFO */
54
+
45
tx_fifo_push(s, val);
55
+VQRSHRUN_64_2sh 1111 001 1 1 . ...... .... 1000 . 1 . 1 .... @2reg_shrn_d
46
return;
56
+VQRSHRUN_32_2sh 1111 001 1 1 . ...... .... 1000 . 1 . 1 .... @2reg_shrn_s
47
@@ -XXX,XX +XXX,XX @@ static uint64_t lan9118_readl(void *opaque, hwaddr offset,
57
+VQRSHRUN_16_2sh 1111 001 1 1 . ...... .... 1000 . 1 . 1 .... @2reg_shrn_h
48
lan9118_state *s = (lan9118_state *)opaque;
58
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
49
59
index XXXXXXX..XXXXXXX 100644
50
//DPRINTF("Read reg 0x%02x\n", (int)offset);
60
--- a/target/arm/translate-neon.inc.c
51
- if (offset < 0x20) {
61
+++ b/target/arm/translate-neon.inc.c
52
+ if (offset <= RX_DATA_FIFO_PORT_LAST) {
62
@@ -XXX,XX +XXX,XX @@ static bool do_2shift_env_32(DisasContext *s, arg_2reg_shift *a,
53
/* RX FIFO */
63
DO_2SHIFT_ENV(VQSHLU, qshlu_s)
54
return rx_fifo_pop(s);
64
DO_2SHIFT_ENV(VQSHL_U, qshl_u)
55
}
65
DO_2SHIFT_ENV(VQSHL_S, qshl_s)
56
switch (offset) {
66
+
57
- case 0x40:
67
+static bool do_2shift_narrow_64(DisasContext *s, arg_2reg_shift *a,
58
+ case RX_STATUS_FIFO_PORT:
68
+ NeonGenTwo64OpFn *shiftfn,
59
return rx_status_fifo_pop(s);
69
+ NeonGenNarrowEnvFn *narrowfn)
60
- case 0x44:
70
+{
61
+ case RX_STATUS_FIFO_PEEK:
71
+ /* 2-reg-and-shift narrowing-shift operations, size == 3 case */
62
return s->rx_status_fifo[s->rx_status_fifo_head];
72
+ TCGv_i64 constimm, rm1, rm2;
63
- case 0x48:
73
+ TCGv_i32 rd;
64
+ case TX_STATUS_FIFO_PORT:
74
+
65
return tx_status_fifo_pop(s);
75
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
66
- case 0x4c:
76
+ return false;
67
+ case TX_STATUS_FIFO_PEEK:
77
+ }
68
return s->tx_status_fifo[s->tx_status_fifo_head];
78
+
69
case CSR_ID_REV:
79
+ /* UNDEF accesses to D16-D31 if they don't exist. */
70
return 0x01180001;
80
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
81
+ ((a->vd | a->vm) & 0x10)) {
82
+ return false;
83
+ }
84
+
85
+ if (a->vm & 1) {
86
+ return false;
87
+ }
88
+
89
+ if (!vfp_access_check(s)) {
90
+ return true;
91
+ }
92
+
93
+ /*
94
+ * This is always a right shift, and the shiftfn is always a
95
+ * left-shift helper, which thus needs the negated shift count.
96
+ */
97
+ constimm = tcg_const_i64(-a->shift);
98
+ rm1 = tcg_temp_new_i64();
99
+ rm2 = tcg_temp_new_i64();
100
+
101
+ /* Load both inputs first to avoid potential overwrite if rm == rd */
102
+ neon_load_reg64(rm1, a->vm);
103
+ neon_load_reg64(rm2, a->vm + 1);
104
+
105
+ shiftfn(rm1, rm1, constimm);
106
+ rd = tcg_temp_new_i32();
107
+ narrowfn(rd, cpu_env, rm1);
108
+ neon_store_reg(a->vd, 0, rd);
109
+
110
+ shiftfn(rm2, rm2, constimm);
111
+ rd = tcg_temp_new_i32();
112
+ narrowfn(rd, cpu_env, rm2);
113
+ neon_store_reg(a->vd, 1, rd);
114
+
115
+ tcg_temp_free_i64(rm1);
116
+ tcg_temp_free_i64(rm2);
117
+ tcg_temp_free_i64(constimm);
118
+
119
+ return true;
120
+}
121
+
122
+static bool do_2shift_narrow_32(DisasContext *s, arg_2reg_shift *a,
123
+ NeonGenTwoOpFn *shiftfn,
124
+ NeonGenNarrowEnvFn *narrowfn)
125
+{
126
+ /* 2-reg-and-shift narrowing-shift operations, size < 3 case */
127
+ TCGv_i32 constimm, rm1, rm2, rm3, rm4;
128
+ TCGv_i64 rtmp;
129
+ uint32_t imm;
130
+
131
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
132
+ return false;
133
+ }
134
+
135
+ /* UNDEF accesses to D16-D31 if they don't exist. */
136
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
137
+ ((a->vd | a->vm) & 0x10)) {
138
+ return false;
139
+ }
140
+
141
+ if (a->vm & 1) {
142
+ return false;
143
+ }
144
+
145
+ if (!vfp_access_check(s)) {
146
+ return true;
147
+ }
148
+
149
+ /*
150
+ * This is always a right shift, and the shiftfn is always a
151
+ * left-shift helper, which thus needs the negated shift count
152
+ * duplicated into each lane of the immediate value.
153
+ */
154
+ if (a->size == 1) {
155
+ imm = (uint16_t)(-a->shift);
156
+ imm |= imm << 16;
157
+ } else {
158
+ /* size == 2 */
159
+ imm = -a->shift;
160
+ }
161
+ constimm = tcg_const_i32(imm);
162
+
163
+ /* Load all inputs first to avoid potential overwrite */
164
+ rm1 = neon_load_reg(a->vm, 0);
165
+ rm2 = neon_load_reg(a->vm, 1);
166
+ rm3 = neon_load_reg(a->vm + 1, 0);
167
+ rm4 = neon_load_reg(a->vm + 1, 1);
168
+ rtmp = tcg_temp_new_i64();
169
+
170
+ shiftfn(rm1, rm1, constimm);
171
+ shiftfn(rm2, rm2, constimm);
172
+
173
+ tcg_gen_concat_i32_i64(rtmp, rm1, rm2);
174
+ tcg_temp_free_i32(rm2);
175
+
176
+ narrowfn(rm1, cpu_env, rtmp);
177
+ neon_store_reg(a->vd, 0, rm1);
178
+
179
+ shiftfn(rm3, rm3, constimm);
180
+ shiftfn(rm4, rm4, constimm);
181
+ tcg_temp_free_i32(constimm);
182
+
183
+ tcg_gen_concat_i32_i64(rtmp, rm3, rm4);
184
+ tcg_temp_free_i32(rm4);
185
+
186
+ narrowfn(rm3, cpu_env, rtmp);
187
+ tcg_temp_free_i64(rtmp);
188
+ neon_store_reg(a->vd, 1, rm3);
189
+ return true;
190
+}
191
+
192
+#define DO_2SN_64(INSN, FUNC, NARROWFUNC) \
193
+ static bool trans_##INSN##_2sh(DisasContext *s, arg_2reg_shift *a) \
194
+ { \
195
+ return do_2shift_narrow_64(s, a, FUNC, NARROWFUNC); \
196
+ }
197
+#define DO_2SN_32(INSN, FUNC, NARROWFUNC) \
198
+ static bool trans_##INSN##_2sh(DisasContext *s, arg_2reg_shift *a) \
199
+ { \
200
+ return do_2shift_narrow_32(s, a, FUNC, NARROWFUNC); \
201
+ }
202
+
203
+static void gen_neon_narrow_u32(TCGv_i32 dest, TCGv_ptr env, TCGv_i64 src)
204
+{
205
+ tcg_gen_extrl_i64_i32(dest, src);
206
+}
207
+
208
+static void gen_neon_narrow_u16(TCGv_i32 dest, TCGv_ptr env, TCGv_i64 src)
209
+{
210
+ gen_helper_neon_narrow_u16(dest, src);
211
+}
212
+
213
+static void gen_neon_narrow_u8(TCGv_i32 dest, TCGv_ptr env, TCGv_i64 src)
214
+{
215
+ gen_helper_neon_narrow_u8(dest, src);
216
+}
217
+
218
+DO_2SN_64(VSHRN_64, gen_ushl_i64, gen_neon_narrow_u32)
219
+DO_2SN_32(VSHRN_32, gen_ushl_i32, gen_neon_narrow_u16)
220
+DO_2SN_32(VSHRN_16, gen_helper_neon_shl_u16, gen_neon_narrow_u8)
221
+
222
+DO_2SN_64(VRSHRN_64, gen_helper_neon_rshl_u64, gen_neon_narrow_u32)
223
+DO_2SN_32(VRSHRN_32, gen_helper_neon_rshl_u32, gen_neon_narrow_u16)
224
+DO_2SN_32(VRSHRN_16, gen_helper_neon_rshl_u16, gen_neon_narrow_u8)
225
+
226
+DO_2SN_64(VQSHRUN_64, gen_sshl_i64, gen_helper_neon_unarrow_sat32)
227
+DO_2SN_32(VQSHRUN_32, gen_sshl_i32, gen_helper_neon_unarrow_sat16)
228
+DO_2SN_32(VQSHRUN_16, gen_helper_neon_shl_s16, gen_helper_neon_unarrow_sat8)
229
+
230
+DO_2SN_64(VQRSHRUN_64, gen_helper_neon_rshl_s64, gen_helper_neon_unarrow_sat32)
231
+DO_2SN_32(VQRSHRUN_32, gen_helper_neon_rshl_s32, gen_helper_neon_unarrow_sat16)
232
+DO_2SN_32(VQRSHRUN_16, gen_helper_neon_rshl_s16, gen_helper_neon_unarrow_sat8)
233
diff --git a/target/arm/translate.c b/target/arm/translate.c
234
index XXXXXXX..XXXXXXX 100644
235
--- a/target/arm/translate.c
236
+++ b/target/arm/translate.c
237
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
238
case 5: /* VSHL, VSLI */
239
case 6: /* VQSHLU */
240
case 7: /* VQSHL */
241
+ case 8: /* VSHRN, VRSHRN, VQSHRUN, VQRSHRUN */
242
return 1; /* handled by decodetree */
243
default:
244
break;
245
--
71
--
246
2.20.1
72
2.20.1
247
73
248
74
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
Do not yet convert the helpers to loop over opr_sz, but the
3
This patch allows NPCM7XX CLK module to compute clocks that are used by
4
descriptor allows the vector tail to be cleared. Which fixes
4
other NPCM7XX modules.
5
an existing bug vs SVE.
6
5
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Add a new struct NPCM7xxClockConverterState which represents a
8
Message-id: 20200514212831.31248-4-richard.henderson@linaro.org
7
single converter. Each clock converter in CLK module represents one
8
converter in NPCM7XX CLK Module(PLL, SEL or Divider). Each converter
9
takes one or more input clocks and converts them into one output clock.
10
They form a clock hierarchy in the CLK module and are responsible for
11
outputing clocks for various other modules in an NPCM7XX SoC.
12
13
Each converter has a function pointer called "convert" which represents
14
the unique logic for that converter.
15
16
The clock contains two initialization information: ConverterInitInfo and
17
ConverterConnectionInfo. They represent the vertices and edges in the
18
clock diagram respectively.
19
20
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
21
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
22
Signed-off-by: Hao Wu <wuhaotsh@google.com>
9
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
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
26
---
12
target/arm/helper.h | 15 +++++++-----
27
include/hw/misc/npcm7xx_clk.h | 140 +++++-
13
target/arm/crypto_helper.c | 37 +++++++++++++++++++++++-----
28
hw/misc/npcm7xx_clk.c | 805 +++++++++++++++++++++++++++++++++-
14
target/arm/translate-a64.c | 50 ++++++++++++--------------------------
29
2 files changed, 932 insertions(+), 13 deletions(-)
15
3 files changed, 55 insertions(+), 47 deletions(-)
16
30
17
diff --git a/target/arm/helper.h b/target/arm/helper.h
31
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
18
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.h
33
--- a/include/hw/misc/npcm7xx_clk.h
20
+++ b/target/arm/helper.h
34
+++ b/include/hw/misc/npcm7xx_clk.h
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(crypto_sha256h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
35
@@ -XXX,XX +XXX,XX @@
22
DEF_HELPER_FLAGS_2(crypto_sha256su0, TCG_CALL_NO_RWG, void, ptr, ptr)
36
#define NPCM7XX_CLK_H
23
DEF_HELPER_FLAGS_3(crypto_sha256su1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
37
24
38
#include "exec/memory.h"
25
-DEF_HELPER_FLAGS_3(crypto_sha512h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
39
+#include "hw/clock.h"
26
-DEF_HELPER_FLAGS_3(crypto_sha512h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
40
#include "hw/sysbus.h"
27
-DEF_HELPER_FLAGS_2(crypto_sha512su0, TCG_CALL_NO_RWG, void, ptr, ptr)
41
28
-DEF_HELPER_FLAGS_3(crypto_sha512su1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
42
/*
29
+DEF_HELPER_FLAGS_4(crypto_sha512h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
43
@@ -XXX,XX +XXX,XX @@
30
+DEF_HELPER_FLAGS_4(crypto_sha512h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
44
31
+DEF_HELPER_FLAGS_3(crypto_sha512su0, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
45
#define NPCM7XX_WATCHDOG_RESET_GPIO_IN "npcm7xx-clk-watchdog-reset-gpio-in"
32
+DEF_HELPER_FLAGS_4(crypto_sha512su1, TCG_CALL_NO_RWG,
46
33
+ void, ptr, ptr, ptr, i32)
47
-typedef struct NPCM7xxCLKState {
34
48
+/* Maximum amount of clock inputs in a SEL module. */
35
DEF_HELPER_FLAGS_5(crypto_sm3tt, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32, i32)
49
+#define NPCM7XX_CLK_SEL_MAX_INPUT 5
36
-DEF_HELPER_FLAGS_3(crypto_sm3partw1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
50
+
37
-DEF_HELPER_FLAGS_3(crypto_sm3partw2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
51
+/* PLLs in CLK module. */
38
+DEF_HELPER_FLAGS_4(crypto_sm3partw1, TCG_CALL_NO_RWG,
52
+typedef enum NPCM7xxClockPLL {
39
+ void, ptr, ptr, ptr, i32)
53
+ NPCM7XX_CLOCK_PLL0,
40
+DEF_HELPER_FLAGS_4(crypto_sm3partw2, TCG_CALL_NO_RWG,
54
+ NPCM7XX_CLOCK_PLL1,
41
+ void, ptr, ptr, ptr, i32)
55
+ NPCM7XX_CLOCK_PLL2,
42
56
+ NPCM7XX_CLOCK_PLLG,
43
DEF_HELPER_FLAGS_4(crypto_sm4e, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
57
+ NPCM7XX_CLOCK_NR_PLLS,
44
DEF_HELPER_FLAGS_4(crypto_sm4ekey, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
58
+} NPCM7xxClockPLL;
45
diff --git a/target/arm/crypto_helper.c b/target/arm/crypto_helper.c
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
46
index XXXXXXX..XXXXXXX 100644
198
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/crypto_helper.c
199
--- a/hw/misc/npcm7xx_clk.c
48
+++ b/target/arm/crypto_helper.c
200
+++ b/hw/misc/npcm7xx_clk.c
49
@@ -XXX,XX +XXX,XX @@ union CRYPTO_STATE {
201
@@ -XXX,XX +XXX,XX @@
50
#define CR_ST_WORD(state, i) (state.words[i])
202
51
#endif
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"
52
212
53
+/*
213
+/*
54
+ * The caller has not been converted to full gvec, and so only
214
+ * The reference clock hz, and the SECCNT and CNTR25M registers in this module,
55
+ * modifies the low 16 bytes of the vector register.
215
+ * is always 25 MHz.
56
+ */
216
+ */
57
+static void clear_tail_16(void *vd, uint32_t desc)
217
+#define NPCM7XX_CLOCK_REF_HZ (25000000)
58
+{
218
+
59
+ int opr_sz = simd_oprsz(desc);
219
+/* Register Field Definitions */
60
+ int max_sz = simd_maxsz(desc);
220
+#define NPCM7XX_CLK_WDRCR_CA9C BIT(0) /* Cortex A9 Cores */
61
+
221
+
62
+ assert(opr_sz == 16);
222
#define PLLCON_LOKI BIT(31)
63
+ clear_tail(vd, opr_sz, max_sz);
223
#define PLLCON_LOKS BIT(30)
64
+}
224
#define PLLCON_PWDEN BIT(12)
65
+
225
+#define PLLCON_FBDV(con) extract32((con), 16, 12)
66
static void do_crypto_aese(uint64_t *rd, uint64_t *rn,
226
+#define PLLCON_OTDV2(con) extract32((con), 13, 3)
67
uint64_t *rm, bool decrypt)
227
+#define PLLCON_OTDV1(con) extract32((con), 8, 3)
228
+#define PLLCON_INDV(con) extract32((con), 0, 6)
229
230
enum NPCM7xxCLKRegisters {
231
NPCM7XX_CLK_CLKEN1,
232
@@ -XXX,XX +XXX,XX @@ static const uint32_t cold_reset_values[NPCM7XX_CLK_NR_REGS] = {
233
[NPCM7XX_CLK_AHBCKFI] = 0x000000c8,
234
};
235
236
-/* Register Field Definitions */
237
-#define NPCM7XX_CLK_WDRCR_CA9C BIT(0) /* Cortex A9 Cores */
238
-
239
/* The number of watchdogs that can trigger a reset. */
240
#define NPCM7XX_NR_WATCHDOGS (3)
241
242
+/* Clock converter functions */
243
+
244
+#define TYPE_NPCM7XX_CLOCK_PLL "npcm7xx-clock-pll"
245
+#define NPCM7XX_CLOCK_PLL(obj) OBJECT_CHECK(NPCM7xxClockPLLState, \
246
+ (obj), TYPE_NPCM7XX_CLOCK_PLL)
247
+#define TYPE_NPCM7XX_CLOCK_SEL "npcm7xx-clock-sel"
248
+#define NPCM7XX_CLOCK_SEL(obj) OBJECT_CHECK(NPCM7xxClockSELState, \
249
+ (obj), TYPE_NPCM7XX_CLOCK_SEL)
250
+#define TYPE_NPCM7XX_CLOCK_DIVIDER "npcm7xx-clock-divider"
251
+#define NPCM7XX_CLOCK_DIVIDER(obj) OBJECT_CHECK(NPCM7xxClockDividerState, \
252
+ (obj), TYPE_NPCM7XX_CLOCK_DIVIDER)
253
+
254
+static void npcm7xx_clk_update_pll(void *opaque)
255
+{
256
+ NPCM7xxClockPLLState *s = opaque;
257
+ uint32_t con = s->clk->regs[s->reg];
258
+ uint64_t freq;
259
+
260
+ /* The PLL is grounded if it is not locked yet. */
261
+ if (con & PLLCON_LOKI) {
262
+ freq = clock_get_hz(s->clock_in);
263
+ freq *= PLLCON_FBDV(con);
264
+ freq /= PLLCON_INDV(con) * PLLCON_OTDV1(con) * PLLCON_OTDV2(con);
265
+ } else {
266
+ freq = 0;
267
+ }
268
+
269
+ clock_update_hz(s->clock_out, freq);
270
+}
271
+
272
+static void npcm7xx_clk_update_sel(void *opaque)
273
+{
274
+ NPCM7xxClockSELState *s = opaque;
275
+ uint32_t index = extract32(s->clk->regs[NPCM7XX_CLK_CLKSEL], s->offset,
276
+ s->len);
277
+
278
+ if (index >= s->input_size) {
279
+ qemu_log_mask(LOG_GUEST_ERROR,
280
+ "%s: SEL index: %u out of range\n",
281
+ __func__, index);
282
+ index = 0;
283
+ }
284
+ clock_update_hz(s->clock_out, clock_get_hz(s->clock_in[index]));
285
+}
286
+
287
+static void npcm7xx_clk_update_divider(void *opaque)
288
+{
289
+ NPCM7xxClockDividerState *s = opaque;
290
+ uint32_t freq;
291
+
292
+ freq = s->divide(s);
293
+ clock_update_hz(s->clock_out, freq);
294
+}
295
+
296
+static uint32_t divide_by_constant(NPCM7xxClockDividerState *s)
297
+{
298
+ return clock_get_hz(s->clock_in) / s->divisor;
299
+}
300
+
301
+static uint32_t divide_by_reg_divisor(NPCM7xxClockDividerState *s)
302
+{
303
+ return clock_get_hz(s->clock_in) /
304
+ (extract32(s->clk->regs[s->reg], s->offset, s->len) + 1);
305
+}
306
+
307
+static uint32_t divide_by_reg_divisor_times_2(NPCM7xxClockDividerState *s)
308
+{
309
+ return divide_by_reg_divisor(s) / 2;
310
+}
311
+
312
+static uint32_t shift_by_reg_divisor(NPCM7xxClockDividerState *s)
313
+{
314
+ return clock_get_hz(s->clock_in) >>
315
+ extract32(s->clk->regs[s->reg], s->offset, s->len);
316
+}
317
+
318
+static NPCM7xxClockPLL find_pll_by_reg(enum NPCM7xxCLKRegisters reg)
319
+{
320
+ switch (reg) {
321
+ case NPCM7XX_CLK_PLLCON0:
322
+ return NPCM7XX_CLOCK_PLL0;
323
+ case NPCM7XX_CLK_PLLCON1:
324
+ return NPCM7XX_CLOCK_PLL1;
325
+ case NPCM7XX_CLK_PLLCON2:
326
+ return NPCM7XX_CLOCK_PLL2;
327
+ case NPCM7XX_CLK_PLLCONG:
328
+ return NPCM7XX_CLOCK_PLLG;
329
+ default:
330
+ g_assert_not_reached();
331
+ }
332
+}
333
+
334
+static void npcm7xx_clk_update_all_plls(NPCM7xxCLKState *clk)
335
+{
336
+ int i;
337
+
338
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
339
+ npcm7xx_clk_update_pll(&clk->plls[i]);
340
+ }
341
+}
342
+
343
+static void npcm7xx_clk_update_all_sels(NPCM7xxCLKState *clk)
344
+{
345
+ int i;
346
+
347
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
348
+ npcm7xx_clk_update_sel(&clk->sels[i]);
349
+ }
350
+}
351
+
352
+static void npcm7xx_clk_update_all_dividers(NPCM7xxCLKState *clk)
353
+{
354
+ int i;
355
+
356
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
357
+ npcm7xx_clk_update_divider(&clk->dividers[i]);
358
+ }
359
+}
360
+
361
+static void npcm7xx_clk_update_all_clocks(NPCM7xxCLKState *clk)
362
+{
363
+ clock_update_hz(clk->clkref, NPCM7XX_CLOCK_REF_HZ);
364
+ npcm7xx_clk_update_all_plls(clk);
365
+ npcm7xx_clk_update_all_sels(clk);
366
+ npcm7xx_clk_update_all_dividers(clk);
367
+}
368
+
369
+/* Types of clock sources. */
370
+typedef enum ClockSrcType {
371
+ CLKSRC_REF,
372
+ CLKSRC_PLL,
373
+ CLKSRC_SEL,
374
+ CLKSRC_DIV,
375
+} ClockSrcType;
376
+
377
+typedef struct PLLInitInfo {
378
+ const char *name;
379
+ ClockSrcType src_type;
380
+ int src_index;
381
+ int reg;
382
+ const char *public_name;
383
+} PLLInitInfo;
384
+
385
+typedef struct SELInitInfo {
386
+ const char *name;
387
+ uint8_t input_size;
388
+ ClockSrcType src_type[NPCM7XX_CLK_SEL_MAX_INPUT];
389
+ int src_index[NPCM7XX_CLK_SEL_MAX_INPUT];
390
+ int offset;
391
+ int len;
392
+ const char *public_name;
393
+} SELInitInfo;
394
+
395
+typedef struct DividerInitInfo {
396
+ const char *name;
397
+ ClockSrcType src_type;
398
+ int src_index;
399
+ uint32_t (*divide)(NPCM7xxClockDividerState *s);
400
+ int reg; /* not used when type == CONSTANT */
401
+ int offset; /* not used when type == CONSTANT */
402
+ int len; /* not used when type == CONSTANT */
403
+ int divisor; /* used only when type == CONSTANT */
404
+ const char *public_name;
405
+} DividerInitInfo;
406
+
407
+static const PLLInitInfo pll_init_info_list[] = {
408
+ [NPCM7XX_CLOCK_PLL0] = {
409
+ .name = "pll0",
410
+ .src_type = CLKSRC_REF,
411
+ .reg = NPCM7XX_CLK_PLLCON0,
412
+ },
413
+ [NPCM7XX_CLOCK_PLL1] = {
414
+ .name = "pll1",
415
+ .src_type = CLKSRC_REF,
416
+ .reg = NPCM7XX_CLK_PLLCON1,
417
+ },
418
+ [NPCM7XX_CLOCK_PLL2] = {
419
+ .name = "pll2",
420
+ .src_type = CLKSRC_REF,
421
+ .reg = NPCM7XX_CLK_PLLCON2,
422
+ },
423
+ [NPCM7XX_CLOCK_PLLG] = {
424
+ .name = "pllg",
425
+ .src_type = CLKSRC_REF,
426
+ .reg = NPCM7XX_CLK_PLLCONG,
427
+ },
428
+};
429
+
430
+static const SELInitInfo sel_init_info_list[] = {
431
+ [NPCM7XX_CLOCK_PIXCKSEL] = {
432
+ .name = "pixcksel",
433
+ .input_size = 2,
434
+ .src_type = {CLKSRC_PLL, CLKSRC_REF},
435
+ .src_index = {NPCM7XX_CLOCK_PLLG, 0},
436
+ .offset = 5,
437
+ .len = 1,
438
+ .public_name = "pixel-clock",
439
+ },
440
+ [NPCM7XX_CLOCK_MCCKSEL] = {
441
+ .name = "mccksel",
442
+ .input_size = 4,
443
+ .src_type = {CLKSRC_DIV, CLKSRC_REF, CLKSRC_REF,
444
+ /*MCBPCK, shouldn't be used in normal operation*/
445
+ CLKSRC_REF},
446
+ .src_index = {NPCM7XX_CLOCK_PLL1D2, 0, 0, 0},
447
+ .offset = 12,
448
+ .len = 2,
449
+ .public_name = "mc-phy-clock",
450
+ },
451
+ [NPCM7XX_CLOCK_CPUCKSEL] = {
452
+ .name = "cpucksel",
453
+ .input_size = 4,
454
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF,
455
+ /*SYSBPCK, shouldn't be used in normal operation*/
456
+ CLKSRC_REF},
457
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0, 0},
458
+ .offset = 0,
459
+ .len = 2,
460
+ .public_name = "system-clock",
461
+ },
462
+ [NPCM7XX_CLOCK_CLKOUTSEL] = {
463
+ .name = "clkoutsel",
464
+ .input_size = 5,
465
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF,
466
+ CLKSRC_PLL, CLKSRC_DIV},
467
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
468
+ NPCM7XX_CLOCK_PLLG, NPCM7XX_CLOCK_PLL2D2},
469
+ .offset = 18,
470
+ .len = 3,
471
+ .public_name = "tock",
472
+ },
473
+ [NPCM7XX_CLOCK_UARTCKSEL] = {
474
+ .name = "uartcksel",
475
+ .input_size = 4,
476
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
477
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
478
+ NPCM7XX_CLOCK_PLL2D2},
479
+ .offset = 8,
480
+ .len = 2,
481
+ },
482
+ [NPCM7XX_CLOCK_TIMCKSEL] = {
483
+ .name = "timcksel",
484
+ .input_size = 4,
485
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
486
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
487
+ NPCM7XX_CLOCK_PLL2D2},
488
+ .offset = 14,
489
+ .len = 2,
490
+ },
491
+ [NPCM7XX_CLOCK_SDCKSEL] = {
492
+ .name = "sdcksel",
493
+ .input_size = 4,
494
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
495
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
496
+ NPCM7XX_CLOCK_PLL2D2},
497
+ .offset = 6,
498
+ .len = 2,
499
+ },
500
+ [NPCM7XX_CLOCK_GFXMSEL] = {
501
+ .name = "gfxmksel",
502
+ .input_size = 2,
503
+ .src_type = {CLKSRC_REF, CLKSRC_PLL},
504
+ .src_index = {0, NPCM7XX_CLOCK_PLL2},
505
+ .offset = 21,
506
+ .len = 1,
507
+ },
508
+ [NPCM7XX_CLOCK_SUCKSEL] = {
509
+ .name = "sucksel",
510
+ .input_size = 4,
511
+ .src_type = {CLKSRC_PLL, CLKSRC_DIV, CLKSRC_REF, CLKSRC_DIV},
512
+ .src_index = {NPCM7XX_CLOCK_PLL0, NPCM7XX_CLOCK_PLL1D2, 0,
513
+ NPCM7XX_CLOCK_PLL2D2},
514
+ .offset = 10,
515
+ .len = 2,
516
+ },
517
+};
518
+
519
+static const DividerInitInfo divider_init_info_list[] = {
520
+ [NPCM7XX_CLOCK_PLL1D2] = {
521
+ .name = "pll1d2",
522
+ .src_type = CLKSRC_PLL,
523
+ .src_index = NPCM7XX_CLOCK_PLL1,
524
+ .divide = divide_by_constant,
525
+ .divisor = 2,
526
+ },
527
+ [NPCM7XX_CLOCK_PLL2D2] = {
528
+ .name = "pll2d2",
529
+ .src_type = CLKSRC_PLL,
530
+ .src_index = NPCM7XX_CLOCK_PLL2,
531
+ .divide = divide_by_constant,
532
+ .divisor = 2,
533
+ },
534
+ [NPCM7XX_CLOCK_MC_DIVIDER] = {
535
+ .name = "mc-divider",
536
+ .src_type = CLKSRC_SEL,
537
+ .src_index = NPCM7XX_CLOCK_MCCKSEL,
538
+ .divide = divide_by_constant,
539
+ .divisor = 2,
540
+ .public_name = "mc-clock"
541
+ },
542
+ [NPCM7XX_CLOCK_AXI_DIVIDER] = {
543
+ .name = "axi-divider",
544
+ .src_type = CLKSRC_SEL,
545
+ .src_index = NPCM7XX_CLOCK_CPUCKSEL,
546
+ .divide = shift_by_reg_divisor,
547
+ .reg = NPCM7XX_CLK_CLKDIV1,
548
+ .offset = 0,
549
+ .len = 1,
550
+ .public_name = "clk2"
551
+ },
552
+ [NPCM7XX_CLOCK_AHB_DIVIDER] = {
553
+ .name = "ahb-divider",
554
+ .src_type = CLKSRC_DIV,
555
+ .src_index = NPCM7XX_CLOCK_AXI_DIVIDER,
556
+ .divide = divide_by_reg_divisor,
557
+ .reg = NPCM7XX_CLK_CLKDIV1,
558
+ .offset = 26,
559
+ .len = 2,
560
+ .public_name = "clk4"
561
+ },
562
+ [NPCM7XX_CLOCK_AHB3_DIVIDER] = {
563
+ .name = "ahb3-divider",
564
+ .src_type = CLKSRC_DIV,
565
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
566
+ .divide = divide_by_reg_divisor,
567
+ .reg = NPCM7XX_CLK_CLKDIV1,
568
+ .offset = 6,
569
+ .len = 5,
570
+ .public_name = "ahb3-spi3-clock"
571
+ },
572
+ [NPCM7XX_CLOCK_SPI0_DIVIDER] = {
573
+ .name = "spi0-divider",
574
+ .src_type = CLKSRC_DIV,
575
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
576
+ .divide = divide_by_reg_divisor,
577
+ .reg = NPCM7XX_CLK_CLKDIV3,
578
+ .offset = 6,
579
+ .len = 5,
580
+ .public_name = "spi0-clock",
581
+ },
582
+ [NPCM7XX_CLOCK_SPIX_DIVIDER] = {
583
+ .name = "spix-divider",
584
+ .src_type = CLKSRC_DIV,
585
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
586
+ .divide = divide_by_reg_divisor,
587
+ .reg = NPCM7XX_CLK_CLKDIV3,
588
+ .offset = 1,
589
+ .len = 5,
590
+ .public_name = "spix-clock",
591
+ },
592
+ [NPCM7XX_CLOCK_APB1_DIVIDER] = {
593
+ .name = "apb1-divider",
594
+ .src_type = CLKSRC_DIV,
595
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
596
+ .divide = shift_by_reg_divisor,
597
+ .reg = NPCM7XX_CLK_CLKDIV2,
598
+ .offset = 24,
599
+ .len = 2,
600
+ .public_name = "apb1-clock",
601
+ },
602
+ [NPCM7XX_CLOCK_APB2_DIVIDER] = {
603
+ .name = "apb2-divider",
604
+ .src_type = CLKSRC_DIV,
605
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
606
+ .divide = shift_by_reg_divisor,
607
+ .reg = NPCM7XX_CLK_CLKDIV2,
608
+ .offset = 26,
609
+ .len = 2,
610
+ .public_name = "apb2-clock",
611
+ },
612
+ [NPCM7XX_CLOCK_APB3_DIVIDER] = {
613
+ .name = "apb3-divider",
614
+ .src_type = CLKSRC_DIV,
615
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
616
+ .divide = shift_by_reg_divisor,
617
+ .reg = NPCM7XX_CLK_CLKDIV2,
618
+ .offset = 28,
619
+ .len = 2,
620
+ .public_name = "apb3-clock",
621
+ },
622
+ [NPCM7XX_CLOCK_APB4_DIVIDER] = {
623
+ .name = "apb4-divider",
624
+ .src_type = CLKSRC_DIV,
625
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
626
+ .divide = shift_by_reg_divisor,
627
+ .reg = NPCM7XX_CLK_CLKDIV2,
628
+ .offset = 30,
629
+ .len = 2,
630
+ .public_name = "apb4-clock",
631
+ },
632
+ [NPCM7XX_CLOCK_APB5_DIVIDER] = {
633
+ .name = "apb5-divider",
634
+ .src_type = CLKSRC_DIV,
635
+ .src_index = NPCM7XX_CLOCK_AHB_DIVIDER,
636
+ .divide = shift_by_reg_divisor,
637
+ .reg = NPCM7XX_CLK_CLKDIV2,
638
+ .offset = 22,
639
+ .len = 2,
640
+ .public_name = "apb5-clock",
641
+ },
642
+ [NPCM7XX_CLOCK_CLKOUT_DIVIDER] = {
643
+ .name = "clkout-divider",
644
+ .src_type = CLKSRC_SEL,
645
+ .src_index = NPCM7XX_CLOCK_CLKOUTSEL,
646
+ .divide = divide_by_reg_divisor,
647
+ .reg = NPCM7XX_CLK_CLKDIV2,
648
+ .offset = 16,
649
+ .len = 5,
650
+ .public_name = "clkout",
651
+ },
652
+ [NPCM7XX_CLOCK_UART_DIVIDER] = {
653
+ .name = "uart-divider",
654
+ .src_type = CLKSRC_SEL,
655
+ .src_index = NPCM7XX_CLOCK_UARTCKSEL,
656
+ .divide = divide_by_reg_divisor,
657
+ .reg = NPCM7XX_CLK_CLKDIV1,
658
+ .offset = 16,
659
+ .len = 5,
660
+ .public_name = "uart-clock",
661
+ },
662
+ [NPCM7XX_CLOCK_TIMER_DIVIDER] = {
663
+ .name = "timer-divider",
664
+ .src_type = CLKSRC_SEL,
665
+ .src_index = NPCM7XX_CLOCK_TIMCKSEL,
666
+ .divide = divide_by_reg_divisor,
667
+ .reg = NPCM7XX_CLK_CLKDIV1,
668
+ .offset = 21,
669
+ .len = 5,
670
+ .public_name = "timer-clock",
671
+ },
672
+ [NPCM7XX_CLOCK_ADC_DIVIDER] = {
673
+ .name = "adc-divider",
674
+ .src_type = CLKSRC_DIV,
675
+ .src_index = NPCM7XX_CLOCK_TIMER_DIVIDER,
676
+ .divide = shift_by_reg_divisor,
677
+ .reg = NPCM7XX_CLK_CLKDIV1,
678
+ .offset = 28,
679
+ .len = 3,
680
+ .public_name = "adc-clock",
681
+ },
682
+ [NPCM7XX_CLOCK_MMC_DIVIDER] = {
683
+ .name = "mmc-divider",
684
+ .src_type = CLKSRC_SEL,
685
+ .src_index = NPCM7XX_CLOCK_SDCKSEL,
686
+ .divide = divide_by_reg_divisor,
687
+ .reg = NPCM7XX_CLK_CLKDIV1,
688
+ .offset = 11,
689
+ .len = 5,
690
+ .public_name = "mmc-clock",
691
+ },
692
+ [NPCM7XX_CLOCK_SDHC_DIVIDER] = {
693
+ .name = "sdhc-divider",
694
+ .src_type = CLKSRC_SEL,
695
+ .src_index = NPCM7XX_CLOCK_SDCKSEL,
696
+ .divide = divide_by_reg_divisor_times_2,
697
+ .reg = NPCM7XX_CLK_CLKDIV2,
698
+ .offset = 0,
699
+ .len = 4,
700
+ .public_name = "sdhc-clock",
701
+ },
702
+ [NPCM7XX_CLOCK_GFXM_DIVIDER] = {
703
+ .name = "gfxm-divider",
704
+ .src_type = CLKSRC_SEL,
705
+ .src_index = NPCM7XX_CLOCK_GFXMSEL,
706
+ .divide = divide_by_constant,
707
+ .divisor = 3,
708
+ .public_name = "gfxm-clock",
709
+ },
710
+ [NPCM7XX_CLOCK_UTMI_DIVIDER] = {
711
+ .name = "utmi-divider",
712
+ .src_type = CLKSRC_SEL,
713
+ .src_index = NPCM7XX_CLOCK_SUCKSEL,
714
+ .divide = divide_by_reg_divisor,
715
+ .reg = NPCM7XX_CLK_CLKDIV2,
716
+ .offset = 8,
717
+ .len = 5,
718
+ .public_name = "utmi-clock",
719
+ },
720
+};
721
+
722
+static void npcm7xx_clk_pll_init(Object *obj)
723
+{
724
+ NPCM7xxClockPLLState *pll = NPCM7XX_CLOCK_PLL(obj);
725
+
726
+ pll->clock_in = qdev_init_clock_in(DEVICE(pll), "clock-in",
727
+ npcm7xx_clk_update_pll, pll);
728
+ pll->clock_out = qdev_init_clock_out(DEVICE(pll), "clock-out");
729
+}
730
+
731
+static void npcm7xx_clk_sel_init(Object *obj)
732
+{
733
+ int i;
734
+ NPCM7xxClockSELState *sel = NPCM7XX_CLOCK_SEL(obj);
735
+
736
+ for (i = 0; i < NPCM7XX_CLK_SEL_MAX_INPUT; ++i) {
737
+ sel->clock_in[i] = qdev_init_clock_in(DEVICE(sel),
738
+ g_strdup_printf("clock-in[%d]", i),
739
+ npcm7xx_clk_update_sel, sel);
740
+ }
741
+ sel->clock_out = qdev_init_clock_out(DEVICE(sel), "clock-out");
742
+}
743
+static void npcm7xx_clk_divider_init(Object *obj)
744
+{
745
+ NPCM7xxClockDividerState *div = NPCM7XX_CLOCK_DIVIDER(obj);
746
+
747
+ div->clock_in = qdev_init_clock_in(DEVICE(div), "clock-in",
748
+ npcm7xx_clk_update_divider, div);
749
+ div->clock_out = qdev_init_clock_out(DEVICE(div), "clock-out");
750
+}
751
+
752
+static void npcm7xx_init_clock_pll(NPCM7xxClockPLLState *pll,
753
+ NPCM7xxCLKState *clk, const PLLInitInfo *init_info)
754
+{
755
+ pll->name = init_info->name;
756
+ pll->clk = clk;
757
+ pll->reg = init_info->reg;
758
+ if (init_info->public_name != NULL) {
759
+ qdev_alias_clock(DEVICE(pll), "clock-out", DEVICE(clk),
760
+ init_info->public_name);
761
+ }
762
+}
763
+
764
+static void npcm7xx_init_clock_sel(NPCM7xxClockSELState *sel,
765
+ NPCM7xxCLKState *clk, const SELInitInfo *init_info)
766
+{
767
+ int input_size = init_info->input_size;
768
+
769
+ sel->name = init_info->name;
770
+ sel->clk = clk;
771
+ sel->input_size = init_info->input_size;
772
+ g_assert(input_size <= NPCM7XX_CLK_SEL_MAX_INPUT);
773
+ sel->offset = init_info->offset;
774
+ sel->len = init_info->len;
775
+ if (init_info->public_name != NULL) {
776
+ qdev_alias_clock(DEVICE(sel), "clock-out", DEVICE(clk),
777
+ init_info->public_name);
778
+ }
779
+}
780
+
781
+static void npcm7xx_init_clock_divider(NPCM7xxClockDividerState *div,
782
+ NPCM7xxCLKState *clk, const DividerInitInfo *init_info)
783
+{
784
+ div->name = init_info->name;
785
+ div->clk = clk;
786
+
787
+ div->divide = init_info->divide;
788
+ if (div->divide == divide_by_constant) {
789
+ div->divisor = init_info->divisor;
790
+ } else {
791
+ div->reg = init_info->reg;
792
+ div->offset = init_info->offset;
793
+ div->len = init_info->len;
794
+ }
795
+ if (init_info->public_name != NULL) {
796
+ qdev_alias_clock(DEVICE(div), "clock-out", DEVICE(clk),
797
+ init_info->public_name);
798
+ }
799
+}
800
+
801
+static Clock *npcm7xx_get_clock(NPCM7xxCLKState *clk, ClockSrcType type,
802
+ int index)
803
+{
804
+ switch (type) {
805
+ case CLKSRC_REF:
806
+ return clk->clkref;
807
+ case CLKSRC_PLL:
808
+ return clk->plls[index].clock_out;
809
+ case CLKSRC_SEL:
810
+ return clk->sels[index].clock_out;
811
+ case CLKSRC_DIV:
812
+ return clk->dividers[index].clock_out;
813
+ default:
814
+ g_assert_not_reached();
815
+ }
816
+}
817
+
818
+static void npcm7xx_connect_clocks(NPCM7xxCLKState *clk)
819
+{
820
+ int i, j;
821
+ Clock *src;
822
+
823
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
824
+ src = npcm7xx_get_clock(clk, pll_init_info_list[i].src_type,
825
+ pll_init_info_list[i].src_index);
826
+ clock_set_source(clk->plls[i].clock_in, src);
827
+ }
828
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
829
+ for (j = 0; j < sel_init_info_list[i].input_size; ++j) {
830
+ src = npcm7xx_get_clock(clk, sel_init_info_list[i].src_type[j],
831
+ sel_init_info_list[i].src_index[j]);
832
+ clock_set_source(clk->sels[i].clock_in[j], src);
833
+ }
834
+ }
835
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
836
+ src = npcm7xx_get_clock(clk, divider_init_info_list[i].src_type,
837
+ divider_init_info_list[i].src_index);
838
+ clock_set_source(clk->dividers[i].clock_in, src);
839
+ }
840
+}
841
+
842
static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size)
68
{
843
{
69
@@ -XXX,XX +XXX,XX @@ static uint64_t s1_512(uint64_t x)
844
uint32_t reg = offset / sizeof(uint32_t);
70
return ror64(x, 19) ^ ror64(x, 61) ^ (x >> 6);
845
@@ -XXX,XX +XXX,XX @@ static uint64_t npcm7xx_clk_read(void *opaque, hwaddr offset, unsigned size)
71
}
846
*
72
847
* The 4 LSBs are always zero: (1e9 / 640) << 4 = 25000000.
73
-void HELPER(crypto_sha512h)(void *vd, void *vn, void *vm)
848
*/
74
+void HELPER(crypto_sha512h)(void *vd, void *vn, void *vm, uint32_t desc)
849
- value = (((now_ns - s->ref_ns) / 640) << 4) % NPCM7XX_TIMER_REF_HZ;
75
{
850
+ value = (((now_ns - s->ref_ns) / 640) << 4) % NPCM7XX_CLOCK_REF_HZ;
76
uint64_t *rd = vd;
77
uint64_t *rn = vn;
78
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha512h)(void *vd, void *vn, void *vm)
79
80
rd[0] = d0;
81
rd[1] = d1;
82
+
83
+ clear_tail_16(vd, desc);
84
}
85
86
-void HELPER(crypto_sha512h2)(void *vd, void *vn, void *vm)
87
+void HELPER(crypto_sha512h2)(void *vd, void *vn, void *vm, uint32_t desc)
88
{
89
uint64_t *rd = vd;
90
uint64_t *rn = vn;
91
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha512h2)(void *vd, void *vn, void *vm)
92
93
rd[0] = d0;
94
rd[1] = d1;
95
+
96
+ clear_tail_16(vd, desc);
97
}
98
99
-void HELPER(crypto_sha512su0)(void *vd, void *vn)
100
+void HELPER(crypto_sha512su0)(void *vd, void *vn, uint32_t desc)
101
{
102
uint64_t *rd = vd;
103
uint64_t *rn = vn;
104
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha512su0)(void *vd, void *vn)
105
106
rd[0] = d0;
107
rd[1] = d1;
108
+
109
+ clear_tail_16(vd, desc);
110
}
111
112
-void HELPER(crypto_sha512su1)(void *vd, void *vn, void *vm)
113
+void HELPER(crypto_sha512su1)(void *vd, void *vn, void *vm, uint32_t desc)
114
{
115
uint64_t *rd = vd;
116
uint64_t *rn = vn;
117
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha512su1)(void *vd, void *vn, void *vm)
118
119
rd[0] += s1_512(rn[0]) + rm[0];
120
rd[1] += s1_512(rn[1]) + rm[1];
121
+
122
+ clear_tail_16(vd, desc);
123
}
124
125
-void HELPER(crypto_sm3partw1)(void *vd, void *vn, void *vm)
126
+void HELPER(crypto_sm3partw1)(void *vd, void *vn, void *vm, uint32_t desc)
127
{
128
uint64_t *rd = vd;
129
uint64_t *rn = vn;
130
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sm3partw1)(void *vd, void *vn, void *vm)
131
132
rd[0] = d.l[0];
133
rd[1] = d.l[1];
134
+
135
+ clear_tail_16(vd, desc);
136
}
137
138
-void HELPER(crypto_sm3partw2)(void *vd, void *vn, void *vm)
139
+void HELPER(crypto_sm3partw2)(void *vd, void *vn, void *vm, uint32_t desc)
140
{
141
uint64_t *rd = vd;
142
uint64_t *rn = vn;
143
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sm3partw2)(void *vd, void *vn, void *vm)
144
145
rd[0] = d.l[0];
146
rd[1] = d.l[1];
147
+
148
+ clear_tail_16(vd, desc);
149
}
150
151
void HELPER(crypto_sm3tt)(void *vd, void *vn, void *vm, uint32_t imm2,
152
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
153
index XXXXXXX..XXXXXXX 100644
154
--- a/target/arm/translate-a64.c
155
+++ b/target/arm/translate-a64.c
156
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
157
int rn = extract32(insn, 5, 5);
158
int rd = extract32(insn, 0, 5);
159
bool feature;
160
- CryptoThreeOpFn *genfn = NULL;
161
gen_helper_gvec_3 *oolfn = NULL;
162
GVecGen3Fn *gvecfn = NULL;
163
164
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
165
switch (opcode) {
166
case 0: /* SHA512H */
167
feature = dc_isar_feature(aa64_sha512, s);
168
- genfn = gen_helper_crypto_sha512h;
169
+ oolfn = gen_helper_crypto_sha512h;
170
break;
171
case 1: /* SHA512H2 */
172
feature = dc_isar_feature(aa64_sha512, s);
173
- genfn = gen_helper_crypto_sha512h2;
174
+ oolfn = gen_helper_crypto_sha512h2;
175
break;
176
case 2: /* SHA512SU1 */
177
feature = dc_isar_feature(aa64_sha512, s);
178
- genfn = gen_helper_crypto_sha512su1;
179
+ oolfn = gen_helper_crypto_sha512su1;
180
break;
181
case 3: /* RAX1 */
182
feature = dc_isar_feature(aa64_sha3, s);
183
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
184
switch (opcode) {
185
case 0: /* SM3PARTW1 */
186
feature = dc_isar_feature(aa64_sm3, s);
187
- genfn = gen_helper_crypto_sm3partw1;
188
+ oolfn = gen_helper_crypto_sm3partw1;
189
break;
190
case 1: /* SM3PARTW2 */
191
feature = dc_isar_feature(aa64_sm3, s);
192
- genfn = gen_helper_crypto_sm3partw2;
193
+ oolfn = gen_helper_crypto_sm3partw2;
194
break;
195
case 2: /* SM4EKEY */
196
feature = dc_isar_feature(aa64_sm4, s);
197
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
198
199
if (oolfn) {
200
gen_gvec_op3_ool(s, true, rd, rn, rm, 0, oolfn);
201
- } else if (gvecfn) {
202
- gen_gvec_fn3(s, true, rd, rn, rm, gvecfn, MO_64);
203
} else {
204
- TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
205
-
206
- tcg_rd_ptr = vec_full_reg_ptr(s, rd);
207
- tcg_rn_ptr = vec_full_reg_ptr(s, rn);
208
- tcg_rm_ptr = vec_full_reg_ptr(s, rm);
209
-
210
- genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr);
211
-
212
- tcg_temp_free_ptr(tcg_rd_ptr);
213
- tcg_temp_free_ptr(tcg_rn_ptr);
214
- tcg_temp_free_ptr(tcg_rm_ptr);
215
+ gen_gvec_fn3(s, true, rd, rn, rm, gvecfn, MO_64);
216
}
217
}
218
219
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha512(DisasContext *s, uint32_t insn)
220
int opcode = extract32(insn, 10, 2);
221
int rn = extract32(insn, 5, 5);
222
int rd = extract32(insn, 0, 5);
223
- TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
224
bool feature;
225
- CryptoTwoOpFn *genfn;
226
- gen_helper_gvec_3 *oolfn = NULL;
227
228
switch (opcode) {
229
case 0: /* SHA512SU0 */
230
feature = dc_isar_feature(aa64_sha512, s);
231
- genfn = gen_helper_crypto_sha512su0;
232
break;
851
break;
233
case 1: /* SM4E */
852
234
feature = dc_isar_feature(aa64_sm4, s);
853
default:
235
- oolfn = gen_helper_crypto_sm4e;
854
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_write(void *opaque, hwaddr offset,
855
value |= (value & PLLCON_LOKS);
856
}
857
}
858
+ /* Only update PLL when it is locked. */
859
+ if (value & PLLCON_LOKI) {
860
+ npcm7xx_clk_update_pll(&s->plls[find_pll_by_reg(reg)]);
861
+ }
862
+ break;
863
+
864
+ case NPCM7XX_CLK_CLKSEL:
865
+ npcm7xx_clk_update_all_sels(s);
866
+ break;
867
+
868
+ case NPCM7XX_CLK_CLKDIV1:
869
+ case NPCM7XX_CLK_CLKDIV2:
870
+ case NPCM7XX_CLK_CLKDIV3:
871
+ npcm7xx_clk_update_all_dividers(s);
236
break;
872
break;
237
default:
873
238
unallocated_encoding(s);
874
case NPCM7XX_CLK_CNTR25M:
239
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha512(DisasContext *s, uint32_t insn)
875
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_enter_reset(Object *obj, ResetType type)
876
case RESET_TYPE_COLD:
877
memcpy(s->regs, cold_reset_values, sizeof(cold_reset_values));
878
s->ref_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
879
+ npcm7xx_clk_update_all_clocks(s);
240
return;
880
return;
241
}
881
}
242
882
243
- if (oolfn) {
883
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_enter_reset(Object *obj, ResetType type)
244
- gen_gvec_op3_ool(s, true, rd, rd, rn, 0, oolfn);
884
__func__, type);
245
- return;
246
+ switch (opcode) {
247
+ case 0: /* SHA512SU0 */
248
+ gen_gvec_op2_ool(s, true, rd, rn, 0, gen_helper_crypto_sha512su0);
249
+ break;
250
+ case 1: /* SM4E */
251
+ gen_gvec_op3_ool(s, true, rd, rd, rn, 0, gen_helper_crypto_sm4e);
252
+ break;
253
+ default:
254
+ g_assert_not_reached();
255
}
256
-
257
- tcg_rd_ptr = vec_full_reg_ptr(s, rd);
258
- tcg_rn_ptr = vec_full_reg_ptr(s, rn);
259
-
260
- genfn(tcg_rd_ptr, tcg_rn_ptr);
261
-
262
- tcg_temp_free_ptr(tcg_rd_ptr);
263
- tcg_temp_free_ptr(tcg_rn_ptr);
264
}
885
}
265
886
266
/* Crypto four-register
887
+static void npcm7xx_clk_init_clock_hierarchy(NPCM7xxCLKState *s)
888
+{
889
+ int i;
890
+
891
+ s->clkref = qdev_init_clock_in(DEVICE(s), "clkref", NULL, NULL);
892
+
893
+ /* First pass: init all converter modules */
894
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(pll_init_info_list) != NPCM7XX_CLOCK_NR_PLLS);
895
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(sel_init_info_list) != NPCM7XX_CLOCK_NR_SELS);
896
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(divider_init_info_list)
897
+ != NPCM7XX_CLOCK_NR_DIVIDERS);
898
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
899
+ object_initialize_child(OBJECT(s), pll_init_info_list[i].name,
900
+ &s->plls[i], TYPE_NPCM7XX_CLOCK_PLL);
901
+ npcm7xx_init_clock_pll(&s->plls[i], s,
902
+ &pll_init_info_list[i]);
903
+ }
904
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
905
+ object_initialize_child(OBJECT(s), sel_init_info_list[i].name,
906
+ &s->sels[i], TYPE_NPCM7XX_CLOCK_SEL);
907
+ npcm7xx_init_clock_sel(&s->sels[i], s,
908
+ &sel_init_info_list[i]);
909
+ }
910
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
911
+ object_initialize_child(OBJECT(s), divider_init_info_list[i].name,
912
+ &s->dividers[i], TYPE_NPCM7XX_CLOCK_DIVIDER);
913
+ npcm7xx_init_clock_divider(&s->dividers[i], s,
914
+ &divider_init_info_list[i]);
915
+ }
916
+
917
+ /* Second pass: connect converter modules */
918
+ npcm7xx_connect_clocks(s);
919
+
920
+ clock_update_hz(s->clkref, NPCM7XX_CLOCK_REF_HZ);
921
+}
922
+
923
static void npcm7xx_clk_init(Object *obj)
924
{
925
NPCM7xxCLKState *s = NPCM7XX_CLK(obj);
926
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_init(Object *obj)
927
memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s,
928
TYPE_NPCM7XX_CLK, 4 * KiB);
929
sysbus_init_mmio(&s->parent, &s->iomem);
930
- qdev_init_gpio_in_named(DEVICE(s), npcm7xx_clk_perform_watchdog_reset,
931
- NPCM7XX_WATCHDOG_RESET_GPIO_IN, NPCM7XX_NR_WATCHDOGS);
932
}
933
934
-static const VMStateDescription vmstate_npcm7xx_clk = {
935
- .name = "npcm7xx-clk",
936
+static int npcm7xx_clk_post_load(void *opaque, int version_id)
937
+{
938
+ if (version_id >= 1) {
939
+ NPCM7xxCLKState *clk = opaque;
940
+
941
+ npcm7xx_clk_update_all_clocks(clk);
942
+ }
943
+
944
+ return 0;
945
+}
946
+
947
+static void npcm7xx_clk_realize(DeviceState *dev, Error **errp)
948
+{
949
+ int i;
950
+ NPCM7xxCLKState *s = NPCM7XX_CLK(dev);
951
+
952
+ qdev_init_gpio_in_named(DEVICE(s), npcm7xx_clk_perform_watchdog_reset,
953
+ NPCM7XX_WATCHDOG_RESET_GPIO_IN, NPCM7XX_NR_WATCHDOGS);
954
+ npcm7xx_clk_init_clock_hierarchy(s);
955
+
956
+ /* Realize child devices */
957
+ for (i = 0; i < NPCM7XX_CLOCK_NR_PLLS; ++i) {
958
+ if (!qdev_realize(DEVICE(&s->plls[i]), NULL, errp)) {
959
+ return;
960
+ }
961
+ }
962
+ for (i = 0; i < NPCM7XX_CLOCK_NR_SELS; ++i) {
963
+ if (!qdev_realize(DEVICE(&s->sels[i]), NULL, errp)) {
964
+ return;
965
+ }
966
+ }
967
+ for (i = 0; i < NPCM7XX_CLOCK_NR_DIVIDERS; ++i) {
968
+ if (!qdev_realize(DEVICE(&s->dividers[i]), NULL, errp)) {
969
+ return;
970
+ }
971
+ }
972
+}
973
+
974
+static const VMStateDescription vmstate_npcm7xx_clk_pll = {
975
+ .name = "npcm7xx-clock-pll",
976
.version_id = 0,
977
.minimum_version_id = 0,
978
- .fields = (VMStateField[]) {
979
- VMSTATE_UINT32_ARRAY(regs, NPCM7xxCLKState, NPCM7XX_CLK_NR_REGS),
980
- VMSTATE_INT64(ref_ns, NPCM7xxCLKState),
981
+ .fields = (VMStateField[]) {
982
+ VMSTATE_CLOCK(clock_in, NPCM7xxClockPLLState),
983
VMSTATE_END_OF_LIST(),
984
},
985
};
986
987
+static const VMStateDescription vmstate_npcm7xx_clk_sel = {
988
+ .name = "npcm7xx-clock-sel",
989
+ .version_id = 0,
990
+ .minimum_version_id = 0,
991
+ .fields = (VMStateField[]) {
992
+ VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(clock_in, NPCM7xxClockSELState,
993
+ NPCM7XX_CLK_SEL_MAX_INPUT, 0, vmstate_clock, Clock),
994
+ VMSTATE_END_OF_LIST(),
995
+ },
996
+};
997
+
998
+static const VMStateDescription vmstate_npcm7xx_clk_divider = {
999
+ .name = "npcm7xx-clock-divider",
1000
+ .version_id = 0,
1001
+ .minimum_version_id = 0,
1002
+ .fields = (VMStateField[]) {
1003
+ VMSTATE_CLOCK(clock_in, NPCM7xxClockDividerState),
1004
+ VMSTATE_END_OF_LIST(),
1005
+ },
1006
+};
1007
+
1008
+static const VMStateDescription vmstate_npcm7xx_clk = {
1009
+ .name = "npcm7xx-clk",
1010
+ .version_id = 1,
1011
+ .minimum_version_id = 1,
1012
+ .post_load = npcm7xx_clk_post_load,
1013
+ .fields = (VMStateField[]) {
1014
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxCLKState, NPCM7XX_CLK_NR_REGS),
1015
+ VMSTATE_INT64(ref_ns, NPCM7xxCLKState),
1016
+ VMSTATE_CLOCK(clkref, NPCM7xxCLKState),
1017
+ VMSTATE_END_OF_LIST(),
1018
+ },
1019
+};
1020
+
1021
+static void npcm7xx_clk_pll_class_init(ObjectClass *klass, void *data)
1022
+{
1023
+ DeviceClass *dc = DEVICE_CLASS(klass);
1024
+
1025
+ dc->desc = "NPCM7xx Clock PLL Module";
1026
+ dc->vmsd = &vmstate_npcm7xx_clk_pll;
1027
+}
1028
+
1029
+static void npcm7xx_clk_sel_class_init(ObjectClass *klass, void *data)
1030
+{
1031
+ DeviceClass *dc = DEVICE_CLASS(klass);
1032
+
1033
+ dc->desc = "NPCM7xx Clock SEL Module";
1034
+ dc->vmsd = &vmstate_npcm7xx_clk_sel;
1035
+}
1036
+
1037
+static void npcm7xx_clk_divider_class_init(ObjectClass *klass, void *data)
1038
+{
1039
+ DeviceClass *dc = DEVICE_CLASS(klass);
1040
+
1041
+ dc->desc = "NPCM7xx Clock Divider Module";
1042
+ dc->vmsd = &vmstate_npcm7xx_clk_divider;
1043
+}
1044
+
1045
static void npcm7xx_clk_class_init(ObjectClass *klass, void *data)
1046
{
1047
ResettableClass *rc = RESETTABLE_CLASS(klass);
1048
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_class_init(ObjectClass *klass, void *data)
1049
1050
dc->desc = "NPCM7xx Clock Control Registers";
1051
dc->vmsd = &vmstate_npcm7xx_clk;
1052
+ dc->realize = npcm7xx_clk_realize;
1053
rc->phases.enter = npcm7xx_clk_enter_reset;
1054
}
1055
1056
+static const TypeInfo npcm7xx_clk_pll_info = {
1057
+ .name = TYPE_NPCM7XX_CLOCK_PLL,
1058
+ .parent = TYPE_DEVICE,
1059
+ .instance_size = sizeof(NPCM7xxClockPLLState),
1060
+ .instance_init = npcm7xx_clk_pll_init,
1061
+ .class_init = npcm7xx_clk_pll_class_init,
1062
+};
1063
+
1064
+static const TypeInfo npcm7xx_clk_sel_info = {
1065
+ .name = TYPE_NPCM7XX_CLOCK_SEL,
1066
+ .parent = TYPE_DEVICE,
1067
+ .instance_size = sizeof(NPCM7xxClockSELState),
1068
+ .instance_init = npcm7xx_clk_sel_init,
1069
+ .class_init = npcm7xx_clk_sel_class_init,
1070
+};
1071
+
1072
+static const TypeInfo npcm7xx_clk_divider_info = {
1073
+ .name = TYPE_NPCM7XX_CLOCK_DIVIDER,
1074
+ .parent = TYPE_DEVICE,
1075
+ .instance_size = sizeof(NPCM7xxClockDividerState),
1076
+ .instance_init = npcm7xx_clk_divider_init,
1077
+ .class_init = npcm7xx_clk_divider_class_init,
1078
+};
1079
+
1080
static const TypeInfo npcm7xx_clk_info = {
1081
.name = TYPE_NPCM7XX_CLK,
1082
.parent = TYPE_SYS_BUS_DEVICE,
1083
@@ -XXX,XX +XXX,XX @@ static const TypeInfo npcm7xx_clk_info = {
1084
1085
static void npcm7xx_clk_register_type(void)
1086
{
1087
+ type_register_static(&npcm7xx_clk_pll_info);
1088
+ type_register_static(&npcm7xx_clk_sel_info);
1089
+ type_register_static(&npcm7xx_clk_divider_info);
1090
type_register_static(&npcm7xx_clk_info);
1091
}
1092
type_init(npcm7xx_clk_register_type);
267
--
1093
--
268
2.20.1
1094
2.20.1
269
1095
270
1096
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
Do not yet convert the helpers to loop over opr_sz, but the
3
This patch makes NPCM7XX Timer to use a the timer clock generated by the
4
descriptor allows the vector tail to be cleared. Which fixes
4
CLK module instead of the magic number TIMER_REF_HZ.
5
an existing bug vs SVE.
6
5
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
8
Message-id: 20200514212831.31248-5-richard.henderson@linaro.org
7
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
8
Signed-off-by: Hao Wu <wuhaotsh@google.com>
9
Message-id: 20210108190945.949196-3-wuhaotsh@google.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
target/arm/helper.h | 12 ++--
13
include/hw/misc/npcm7xx_clk.h | 6 -----
13
target/arm/neon-dp.decode | 12 ++--
14
include/hw/timer/npcm7xx_timer.h | 1 +
14
target/arm/crypto_helper.c | 24 +++++--
15
hw/arm/npcm7xx.c | 5 ++++
15
target/arm/translate-a64.c | 34 ++++-----
16
hw/timer/npcm7xx_timer.c | 39 +++++++++++++++-----------------
16
target/arm/translate-neon.inc.c | 124 +++++---------------------------
17
4 files changed, 24 insertions(+), 27 deletions(-)
17
target/arm/translate.c | 24 ++-----
18
6 files changed, 67 insertions(+), 163 deletions(-)
19
18
20
diff --git a/target/arm/helper.h b/target/arm/helper.h
19
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
21
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/helper.h
21
--- a/include/hw/misc/npcm7xx_clk.h
23
+++ b/target/arm/helper.h
22
+++ b/include/hw/misc/npcm7xx_clk.h
24
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(crypto_aese, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
23
@@ -XXX,XX +XXX,XX @@
25
DEF_HELPER_FLAGS_3(crypto_aesmc, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
24
#include "hw/clock.h"
26
25
#include "hw/sysbus.h"
27
DEF_HELPER_FLAGS_4(crypto_sha1_3reg, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
26
28
-DEF_HELPER_FLAGS_2(crypto_sha1h, TCG_CALL_NO_RWG, void, ptr, ptr)
27
-/*
29
-DEF_HELPER_FLAGS_2(crypto_sha1su1, TCG_CALL_NO_RWG, void, ptr, ptr)
28
- * The reference clock frequency for the timer modules, and the SECCNT and
30
+DEF_HELPER_FLAGS_3(crypto_sha1h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
29
- * CNTR25M registers in this module, is always 25 MHz.
31
+DEF_HELPER_FLAGS_3(crypto_sha1su1, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
30
- */
32
31
-#define NPCM7XX_TIMER_REF_HZ (25000000)
33
-DEF_HELPER_FLAGS_3(crypto_sha256h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
32
-
34
-DEF_HELPER_FLAGS_3(crypto_sha256h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
33
/*
35
-DEF_HELPER_FLAGS_2(crypto_sha256su0, TCG_CALL_NO_RWG, void, ptr, ptr)
34
* Number of registers in our device state structure. Don't change this without
36
-DEF_HELPER_FLAGS_3(crypto_sha256su1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
35
* incrementing the version_id in the vmstate.
37
+DEF_HELPER_FLAGS_4(crypto_sha256h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
36
diff --git a/include/hw/timer/npcm7xx_timer.h b/include/hw/timer/npcm7xx_timer.h
38
+DEF_HELPER_FLAGS_4(crypto_sha256h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
39
+DEF_HELPER_FLAGS_3(crypto_sha256su0, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
40
+DEF_HELPER_FLAGS_4(crypto_sha256su1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
41
42
DEF_HELPER_FLAGS_4(crypto_sha512h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
43
DEF_HELPER_FLAGS_4(crypto_sha512h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
44
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
45
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
46
--- a/target/arm/neon-dp.decode
38
--- a/include/hw/timer/npcm7xx_timer.h
47
+++ b/target/arm/neon-dp.decode
39
+++ b/include/hw/timer/npcm7xx_timer.h
48
@@ -XXX,XX +XXX,XX @@ VPADD_3s 1111 001 0 0 . .. .... .... 1011 . . . 1 .... @3same_q0
40
@@ -XXX,XX +XXX,XX @@ struct NPCM7xxTimerCtrlState {
49
41
50
VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same
42
uint32_t tisr;
51
43
52
+@3same_crypto .... .... .... .... .... .... .... .... \
44
+ Clock *clock;
53
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp size=0 q=1
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"));
54
+
67
+
55
SHA1_3s 1111 001 0 0 . optype:2 .... .... 1100 . 1 . 0 .... \
68
sysbus_realize(sbd, &error_abort);
56
vm=%vm_dp vn=%vn_dp vd=%vd_dp
69
sysbus_mmio_map(sbd, 0, npcm7xx_tim_addr[i]);
57
-SHA256H_3s 1111 001 1 0 . 00 .... .... 1100 . 1 . 0 .... \
70
58
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
71
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
59
-SHA256H2_3s 1111 001 1 0 . 01 .... .... 1100 . 1 . 0 .... \
60
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
61
-SHA256SU1_3s 1111 001 1 0 . 10 .... .... 1100 . 1 . 0 .... \
62
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
63
+SHA256H_3s 1111 001 1 0 . 00 .... .... 1100 . 1 . 0 .... @3same_crypto
64
+SHA256H2_3s 1111 001 1 0 . 01 .... .... 1100 . 1 . 0 .... @3same_crypto
65
+SHA256SU1_3s 1111 001 1 0 . 10 .... .... 1100 . 1 . 0 .... @3same_crypto
66
67
VFMA_fp_3s 1111 001 0 0 . 0 . .... .... 1100 ... 1 .... @3same_fp
68
VFMS_fp_3s 1111 001 0 0 . 1 . .... .... 1100 ... 1 .... @3same_fp
69
diff --git a/target/arm/crypto_helper.c b/target/arm/crypto_helper.c
70
index XXXXXXX..XXXXXXX 100644
72
index XXXXXXX..XXXXXXX 100644
71
--- a/target/arm/crypto_helper.c
73
--- a/hw/timer/npcm7xx_timer.c
72
+++ b/target/arm/crypto_helper.c
74
+++ b/hw/timer/npcm7xx_timer.c
73
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha1_3reg)(void *vd, void *vn, void *vm, uint32_t op)
75
@@ -XXX,XX +XXX,XX @@
74
rd[1] = d.l[1];
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);
75
}
98
}
76
99
77
-void HELPER(crypto_sha1h)(void *vd, void *vm)
100
/* Convert a time interval in nanoseconds to a timer cycle count. */
78
+void HELPER(crypto_sha1h)(void *vd, void *vm, uint32_t desc)
101
static uint32_t npcm7xx_timer_ns_to_count(NPCM7xxTimer *t, int64_t ns)
79
{
102
{
80
uint64_t *rd = vd;
103
- int64_t count;
81
uint64_t *rm = vm;
104
-
82
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha1h)(void *vd, void *vm)
105
- count = ns / (NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ);
83
106
- count /= npcm7xx_tcsr_prescaler(t->tcsr);
84
rd[0] = m.l[0];
107
-
85
rd[1] = m.l[1];
108
- return count;
86
+
109
+ return ns / clock_ticks_to_ns(t->ctrl->clock,
87
+ clear_tail_16(vd, desc);
110
+ npcm7xx_tcsr_prescaler(t->tcsr));
88
}
111
}
89
112
90
-void HELPER(crypto_sha1su1)(void *vd, void *vm)
113
static uint32_t npcm7xx_watchdog_timer_prescaler(const NPCM7xxWatchdogTimer *t)
91
+void HELPER(crypto_sha1su1)(void *vd, void *vm, uint32_t desc)
114
@@ -XXX,XX +XXX,XX @@ static uint32_t npcm7xx_watchdog_timer_prescaler(const NPCM7xxWatchdogTimer *t)
115
static void npcm7xx_watchdog_timer_reset_cycles(NPCM7xxWatchdogTimer *t,
116
int64_t cycles)
92
{
117
{
93
uint64_t *rd = vd;
118
- uint32_t prescaler = npcm7xx_watchdog_timer_prescaler(t);
94
uint64_t *rm = vm;
119
- int64_t ns = (NANOSECONDS_PER_SECOND / NPCM7XX_TIMER_REF_HZ) * cycles;
95
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha1su1)(void *vd, void *vm)
120
+ int64_t ticks = cycles * npcm7xx_watchdog_timer_prescaler(t);
96
121
+ int64_t ns = clock_ticks_to_ns(t->ctrl->clock, ticks);
97
rd[0] = d.l[0];
122
98
rd[1] = d.l[1];
123
/*
99
+
124
* The reset function always clears the current timer. The caller of the
100
+ clear_tail_16(vd, desc);
125
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_watchdog_timer_reset_cycles(NPCM7xxWatchdogTimer *t,
126
*/
127
npcm7xx_timer_clear(&t->base_timer);
128
129
- ns *= prescaler;
130
t->base_timer.remaining_ns = ns;
101
}
131
}
102
132
103
/*
133
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_hold_reset(Object *obj)
104
@@ -XXX,XX +XXX,XX @@ static uint32_t s1(uint32_t x)
134
qemu_irq_lower(s->watchdog_timer.irq);
105
return ror32(x, 17) ^ ror32(x, 19) ^ (x >> 10);
106
}
135
}
107
136
108
-void HELPER(crypto_sha256h)(void *vd, void *vn, void *vm)
137
-static void npcm7xx_timer_realize(DeviceState *dev, Error **errp)
109
+void HELPER(crypto_sha256h)(void *vd, void *vn, void *vm, uint32_t desc)
138
+static void npcm7xx_timer_init(Object *obj)
110
{
139
{
111
uint64_t *rd = vd;
140
- NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(dev);
112
uint64_t *rn = vn;
141
- SysBusDevice *sbd = &s->parent;
113
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha256h)(void *vd, void *vn, void *vm)
142
+ NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(obj);
114
143
+ DeviceState *dev = DEVICE(obj);
115
rd[0] = d.l[0];
144
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
116
rd[1] = d.l[1];
145
int i;
117
+
146
NPCM7xxWatchdogTimer *w;
118
+ clear_tail_16(vd, desc);
147
148
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_realize(DeviceState *dev, Error **errp)
149
npcm7xx_watchdog_timer_expired, w);
150
sysbus_init_irq(sbd, &w->irq);
151
152
- memory_region_init_io(&s->iomem, OBJECT(s), &npcm7xx_timer_ops, s,
153
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_timer_ops, s,
154
TYPE_NPCM7XX_TIMER, 4 * KiB);
155
sysbus_init_mmio(sbd, &s->iomem);
156
qdev_init_gpio_out_named(dev, &w->reset_signal,
157
NPCM7XX_WATCHDOG_RESET_GPIO_OUT, 1);
158
+ s->clock = qdev_init_clock_in(dev, "clock", NULL, NULL);
119
}
159
}
120
160
121
-void HELPER(crypto_sha256h2)(void *vd, void *vn, void *vm)
161
static const VMStateDescription vmstate_npcm7xx_base_timer = {
122
+void HELPER(crypto_sha256h2)(void *vd, void *vn, void *vm, uint32_t desc)
162
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_npcm7xx_watchdog_timer = {
123
{
163
124
uint64_t *rd = vd;
164
static const VMStateDescription vmstate_npcm7xx_timer_ctrl = {
125
uint64_t *rn = vn;
165
.name = "npcm7xx-timer-ctrl",
126
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha256h2)(void *vd, void *vn, void *vm)
166
- .version_id = 1,
127
167
- .minimum_version_id = 1,
128
rd[0] = d.l[0];
168
+ .version_id = 2,
129
rd[1] = d.l[1];
169
+ .minimum_version_id = 2,
130
+
170
.fields = (VMStateField[]) {
131
+ clear_tail_16(vd, desc);
171
VMSTATE_UINT32(tisr, NPCM7xxTimerCtrlState),
132
}
172
+ VMSTATE_CLOCK(clock, NPCM7xxTimerCtrlState),
133
173
VMSTATE_STRUCT_ARRAY(timer, NPCM7xxTimerCtrlState,
134
-void HELPER(crypto_sha256su0)(void *vd, void *vm)
174
NPCM7XX_TIMERS_PER_CTRL, 0, vmstate_npcm7xx_timer,
135
+void HELPER(crypto_sha256su0)(void *vd, void *vm, uint32_t desc)
175
NPCM7xxTimer),
136
{
176
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_timer_class_init(ObjectClass *klass, void *data)
137
uint64_t *rd = vd;
177
QEMU_BUILD_BUG_ON(NPCM7XX_TIMER_REGS_END > NPCM7XX_TIMER_NR_REGS);
138
uint64_t *rm = vm;
178
139
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha256su0)(void *vd, void *vm)
179
dc->desc = "NPCM7xx Timer Controller";
140
180
- dc->realize = npcm7xx_timer_realize;
141
rd[0] = d.l[0];
181
dc->vmsd = &vmstate_npcm7xx_timer_ctrl;
142
rd[1] = d.l[1];
182
rc->phases.enter = npcm7xx_timer_enter_reset;
143
+
183
rc->phases.hold = npcm7xx_timer_hold_reset;
144
+ clear_tail_16(vd, desc);
184
@@ -XXX,XX +XXX,XX @@ static const TypeInfo npcm7xx_timer_info = {
145
}
185
.parent = TYPE_SYS_BUS_DEVICE,
146
186
.instance_size = sizeof(NPCM7xxTimerCtrlState),
147
-void HELPER(crypto_sha256su1)(void *vd, void *vn, void *vm)
187
.class_init = npcm7xx_timer_class_init,
148
+void HELPER(crypto_sha256su1)(void *vd, void *vn, void *vm, uint32_t desc)
188
+ .instance_init = npcm7xx_timer_init,
149
{
189
};
150
uint64_t *rd = vd;
190
151
uint64_t *rn = vn;
191
static void npcm7xx_timer_register_type(void)
152
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha256su1)(void *vd, void *vn, void *vm)
153
154
rd[0] = d.l[0];
155
rd[1] = d.l[1];
156
+
157
+ clear_tail_16(vd, desc);
158
}
159
160
/*
161
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
162
index XXXXXXX..XXXXXXX 100644
163
--- a/target/arm/translate-a64.c
164
+++ b/target/arm/translate-a64.c
165
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
166
int rm = extract32(insn, 16, 5);
167
int rn = extract32(insn, 5, 5);
168
int rd = extract32(insn, 0, 5);
169
- CryptoThreeOpFn *genfn;
170
- TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
171
+ gen_helper_gvec_3 *genfn;
172
bool feature;
173
174
if (size != 0) {
175
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
176
return;
177
}
178
179
- tcg_rd_ptr = vec_full_reg_ptr(s, rd);
180
- tcg_rn_ptr = vec_full_reg_ptr(s, rn);
181
- tcg_rm_ptr = vec_full_reg_ptr(s, rm);
182
-
183
if (genfn) {
184
- genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr);
185
+ gen_gvec_op3_ool(s, true, rd, rn, rm, 0, genfn);
186
} else {
187
TCGv_i32 tcg_opcode = tcg_const_i32(opcode);
188
+ TCGv_ptr tcg_rd_ptr = vec_full_reg_ptr(s, rd);
189
+ TCGv_ptr tcg_rn_ptr = vec_full_reg_ptr(s, rn);
190
+ TCGv_ptr tcg_rm_ptr = vec_full_reg_ptr(s, rm);
191
192
gen_helper_crypto_sha1_3reg(tcg_rd_ptr, tcg_rn_ptr,
193
tcg_rm_ptr, tcg_opcode);
194
- tcg_temp_free_i32(tcg_opcode);
195
- }
196
197
- tcg_temp_free_ptr(tcg_rd_ptr);
198
- tcg_temp_free_ptr(tcg_rn_ptr);
199
- tcg_temp_free_ptr(tcg_rm_ptr);
200
+ tcg_temp_free_i32(tcg_opcode);
201
+ tcg_temp_free_ptr(tcg_rd_ptr);
202
+ tcg_temp_free_ptr(tcg_rn_ptr);
203
+ tcg_temp_free_ptr(tcg_rm_ptr);
204
+ }
205
}
206
207
/* Crypto two-reg SHA
208
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
209
int opcode = extract32(insn, 12, 5);
210
int rn = extract32(insn, 5, 5);
211
int rd = extract32(insn, 0, 5);
212
- CryptoTwoOpFn *genfn;
213
+ gen_helper_gvec_2 *genfn;
214
bool feature;
215
- TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
216
217
if (size != 0) {
218
unallocated_encoding(s);
219
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
220
if (!fp_access_check(s)) {
221
return;
222
}
223
-
224
- tcg_rd_ptr = vec_full_reg_ptr(s, rd);
225
- tcg_rn_ptr = vec_full_reg_ptr(s, rn);
226
-
227
- genfn(tcg_rd_ptr, tcg_rn_ptr);
228
-
229
- tcg_temp_free_ptr(tcg_rd_ptr);
230
- tcg_temp_free_ptr(tcg_rn_ptr);
231
+ gen_gvec_op2_ool(s, true, rd, rn, 0, genfn);
232
}
233
234
static void gen_rax1_i64(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m)
235
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
236
index XXXXXXX..XXXXXXX 100644
237
--- a/target/arm/translate-neon.inc.c
238
+++ b/target/arm/translate-neon.inc.c
239
@@ -XXX,XX +XXX,XX @@ DO_3SAME_CMP(VCGE_S, TCG_COND_GE)
240
DO_3SAME_CMP(VCGE_U, TCG_COND_GEU)
241
DO_3SAME_CMP(VCEQ, TCG_COND_EQ)
242
243
-static void gen_VMUL_p_3s(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
244
- uint32_t rm_ofs, uint32_t oprsz, uint32_t maxsz)
245
-{
246
- tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz,
247
- 0, gen_helper_gvec_pmul_b);
248
-}
249
+#define WRAP_OOL_FN(WRAPNAME, FUNC) \
250
+ static void WRAPNAME(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, \
251
+ uint32_t rm_ofs, uint32_t oprsz, uint32_t maxsz) \
252
+ { \
253
+ tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, 0, FUNC); \
254
+ }
255
+
256
+WRAP_OOL_FN(gen_VMUL_p_3s, gen_helper_gvec_pmul_b)
257
258
static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a)
259
{
260
@@ -XXX,XX +XXX,XX @@ static bool trans_SHA1_3s(DisasContext *s, arg_SHA1_3s *a)
261
return true;
262
}
263
264
-static bool trans_SHA256H_3s(DisasContext *s, arg_SHA256H_3s *a)
265
-{
266
- TCGv_ptr ptr1, ptr2, ptr3;
267
-
268
- if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
269
- !dc_isar_feature(aa32_sha2, s)) {
270
- return false;
271
+#define DO_SHA2(NAME, FUNC) \
272
+ WRAP_OOL_FN(gen_##NAME##_3s, FUNC) \
273
+ static bool trans_##NAME##_3s(DisasContext *s, arg_3same *a) \
274
+ { \
275
+ if (!dc_isar_feature(aa32_sha2, s)) { \
276
+ return false; \
277
+ } \
278
+ return do_3same(s, a, gen_##NAME##_3s); \
279
}
280
281
- /* UNDEF accesses to D16-D31 if they don't exist. */
282
- if (!dc_isar_feature(aa32_simd_r32, s) &&
283
- ((a->vd | a->vn | a->vm) & 0x10)) {
284
- return false;
285
- }
286
-
287
- if ((a->vn | a->vm | a->vd) & 1) {
288
- return false;
289
- }
290
-
291
- if (!vfp_access_check(s)) {
292
- return true;
293
- }
294
-
295
- ptr1 = vfp_reg_ptr(true, a->vd);
296
- ptr2 = vfp_reg_ptr(true, a->vn);
297
- ptr3 = vfp_reg_ptr(true, a->vm);
298
- gen_helper_crypto_sha256h(ptr1, ptr2, ptr3);
299
- tcg_temp_free_ptr(ptr1);
300
- tcg_temp_free_ptr(ptr2);
301
- tcg_temp_free_ptr(ptr3);
302
-
303
- return true;
304
-}
305
-
306
-static bool trans_SHA256H2_3s(DisasContext *s, arg_SHA256H2_3s *a)
307
-{
308
- TCGv_ptr ptr1, ptr2, ptr3;
309
-
310
- if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
311
- !dc_isar_feature(aa32_sha2, s)) {
312
- return false;
313
- }
314
-
315
- /* UNDEF accesses to D16-D31 if they don't exist. */
316
- if (!dc_isar_feature(aa32_simd_r32, s) &&
317
- ((a->vd | a->vn | a->vm) & 0x10)) {
318
- return false;
319
- }
320
-
321
- if ((a->vn | a->vm | a->vd) & 1) {
322
- return false;
323
- }
324
-
325
- if (!vfp_access_check(s)) {
326
- return true;
327
- }
328
-
329
- ptr1 = vfp_reg_ptr(true, a->vd);
330
- ptr2 = vfp_reg_ptr(true, a->vn);
331
- ptr3 = vfp_reg_ptr(true, a->vm);
332
- gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3);
333
- tcg_temp_free_ptr(ptr1);
334
- tcg_temp_free_ptr(ptr2);
335
- tcg_temp_free_ptr(ptr3);
336
-
337
- return true;
338
-}
339
-
340
-static bool trans_SHA256SU1_3s(DisasContext *s, arg_SHA256SU1_3s *a)
341
-{
342
- TCGv_ptr ptr1, ptr2, ptr3;
343
-
344
- if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
345
- !dc_isar_feature(aa32_sha2, s)) {
346
- return false;
347
- }
348
-
349
- /* UNDEF accesses to D16-D31 if they don't exist. */
350
- if (!dc_isar_feature(aa32_simd_r32, s) &&
351
- ((a->vd | a->vn | a->vm) & 0x10)) {
352
- return false;
353
- }
354
-
355
- if ((a->vn | a->vm | a->vd) & 1) {
356
- return false;
357
- }
358
-
359
- if (!vfp_access_check(s)) {
360
- return true;
361
- }
362
-
363
- ptr1 = vfp_reg_ptr(true, a->vd);
364
- ptr2 = vfp_reg_ptr(true, a->vn);
365
- ptr3 = vfp_reg_ptr(true, a->vm);
366
- gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3);
367
- tcg_temp_free_ptr(ptr1);
368
- tcg_temp_free_ptr(ptr2);
369
- tcg_temp_free_ptr(ptr3);
370
-
371
- return true;
372
-}
373
+DO_SHA2(SHA256H, gen_helper_crypto_sha256h)
374
+DO_SHA2(SHA256H2, gen_helper_crypto_sha256h2)
375
+DO_SHA2(SHA256SU1, gen_helper_crypto_sha256su1)
376
377
#define DO_3SAME_64(INSN, FUNC) \
378
static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
379
diff --git a/target/arm/translate.c b/target/arm/translate.c
380
index XXXXXXX..XXXXXXX 100644
381
--- a/target/arm/translate.c
382
+++ b/target/arm/translate.c
383
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
384
int vec_size;
385
uint32_t imm;
386
TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
387
- TCGv_ptr ptr1, ptr2;
388
+ TCGv_ptr ptr1;
389
TCGv_i64 tmp64;
390
391
if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
392
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
393
if (!dc_isar_feature(aa32_sha1, s) || ((rm | rd) & 1)) {
394
return 1;
395
}
396
- ptr1 = vfp_reg_ptr(true, rd);
397
- ptr2 = vfp_reg_ptr(true, rm);
398
-
399
- gen_helper_crypto_sha1h(ptr1, ptr2);
400
-
401
- tcg_temp_free_ptr(ptr1);
402
- tcg_temp_free_ptr(ptr2);
403
+ tcg_gen_gvec_2_ool(rd_ofs, rm_ofs, 16, 16, 0,
404
+ gen_helper_crypto_sha1h);
405
break;
406
case NEON_2RM_SHA1SU1:
407
if ((rm | rd) & 1) {
408
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
409
} else if (!dc_isar_feature(aa32_sha1, s)) {
410
return 1;
411
}
412
- ptr1 = vfp_reg_ptr(true, rd);
413
- ptr2 = vfp_reg_ptr(true, rm);
414
- if (q) {
415
- gen_helper_crypto_sha256su0(ptr1, ptr2);
416
- } else {
417
- gen_helper_crypto_sha1su1(ptr1, ptr2);
418
- }
419
- tcg_temp_free_ptr(ptr1);
420
- tcg_temp_free_ptr(ptr2);
421
+ tcg_gen_gvec_2_ool(rd_ofs, rm_ofs, 16, 16, 0,
422
+ q ? gen_helper_crypto_sha256su0
423
+ : gen_helper_crypto_sha1su1);
424
break;
425
-
426
case NEON_2RM_VMVN:
427
tcg_gen_gvec_not(0, rd_ofs, rm_ofs, vec_size, vec_size);
428
break;
429
--
192
--
430
2.20.1
193
2.20.1
431
194
432
195
diff view generated by jsdifflib
1
From: Paul Zimmerman <pauldzim@gmail.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
Add the dwc-hsotg (dwc2) USB host controller state definitions.
3
The ADC is part of NPCM7XX Module. Its behavior is controled by the
4
Mostly based on hw/usb/hcd-ehci.h.
4
ADC_CON register. It converts one of the eight analog inputs into a
5
digital input and stores it in the ADC_DATA register when enabled.
5
6
6
Signed-off-by: Paul Zimmerman <pauldzim@gmail.com>
7
Users can alter input value by using qom-set QMP command.
7
Message-id: 20200520235349.21215-4-pauldzim@gmail.com
8
9
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
10
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
11
Signed-off-by: Hao Wu <wuhaotsh@google.com>
12
Message-id: 20210108190945.949196-4-wuhaotsh@google.com
13
[PMM: Added missing hw/adc/trace.h file]
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
16
---
11
hw/usb/hcd-dwc2.h | 190 ++++++++++++++++++++++++++++++++++++++++++++++
17
docs/system/arm/nuvoton.rst | 2 +-
12
1 file changed, 190 insertions(+)
18
meson.build | 1 +
13
create mode 100644 hw/usb/hcd-dwc2.h
19
hw/adc/trace.h | 1 +
20
include/hw/adc/npcm7xx_adc.h | 69 ++++++
21
include/hw/arm/npcm7xx.h | 2 +
22
hw/adc/npcm7xx_adc.c | 301 ++++++++++++++++++++++++++
23
hw/arm/npcm7xx.c | 24 ++-
24
tests/qtest/npcm7xx_adc-test.c | 377 +++++++++++++++++++++++++++++++++
25
hw/adc/meson.build | 1 +
26
hw/adc/trace-events | 5 +
27
tests/qtest/meson.build | 3 +-
28
11 files changed, 783 insertions(+), 3 deletions(-)
29
create mode 100644 hw/adc/trace.h
30
create mode 100644 include/hw/adc/npcm7xx_adc.h
31
create mode 100644 hw/adc/npcm7xx_adc.c
32
create mode 100644 tests/qtest/npcm7xx_adc-test.c
33
create mode 100644 hw/adc/trace-events
14
34
15
diff --git a/hw/usb/hcd-dwc2.h b/hw/usb/hcd-dwc2.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
16
new file mode 100644
68
new file mode 100644
17
index XXXXXXX..XXXXXXX
69
index XXXXXXX..XXXXXXX
18
--- /dev/null
70
--- /dev/null
19
+++ b/hw/usb/hcd-dwc2.h
71
+++ b/hw/adc/trace.h
72
@@ -0,0 +1 @@
73
+#include "trace/trace-hw_adc.h"
74
diff --git a/include/hw/adc/npcm7xx_adc.h b/include/hw/adc/npcm7xx_adc.h
75
new file mode 100644
76
index XXXXXXX..XXXXXXX
77
--- /dev/null
78
+++ b/include/hw/adc/npcm7xx_adc.h
20
@@ -XXX,XX +XXX,XX @@
79
@@ -XXX,XX +XXX,XX @@
21
+/*
80
+/*
22
+ * dwc-hsotg (dwc2) USB host controller state definitions
81
+ * Nuvoton NPCM7xx ADC Module
23
+ *
82
+ *
24
+ * Based on hw/usb/hcd-ehci.h
83
+ * Copyright 2020 Google LLC
25
+ *
84
+ *
26
+ * Copyright (c) 2020 Paul Zimmerman <pauldzim@gmail.com>
85
+ * This program is free software; you can redistribute it and/or modify it
27
+ *
86
+ * under the terms of the GNU General Public License as published by the
28
+ * This program is free software; you can redistribute it and/or modify
87
+ * Free Software Foundation; either version 2 of the License, or
29
+ * it under the terms of the GNU General Public License as published by
30
+ * the Free Software Foundation; either version 2 of the License, or
31
+ * (at your option) any later version.
88
+ * (at your option) any later version.
32
+ *
89
+ *
33
+ * This program is distributed in the hope that it will be useful,
90
+ * This program is distributed in the hope that it will be useful, but WITHOUT
34
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
91
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
35
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
92
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
36
+ * GNU General Public License for more details.
93
+ * for more details.
37
+ */
94
+ */
38
+
95
+#ifndef NPCM7XX_ADC_H
39
+#ifndef HW_USB_DWC2_H
96
+#define NPCM7XX_ADC_H
40
+#define HW_USB_DWC2_H
97
+
41
+
98
+#include "hw/clock.h"
42
+#include "qemu/timer.h"
43
+#include "hw/irq.h"
99
+#include "hw/irq.h"
44
+#include "hw/sysbus.h"
100
+#include "hw/sysbus.h"
45
+#include "hw/usb.h"
101
+#include "qemu/timer.h"
46
+#include "sysemu/dma.h"
102
+
47
+
103
+#define NPCM7XX_ADC_NUM_INPUTS 8
48
+#define DWC2_MMIO_SIZE 0x11000
104
+/**
49
+
105
+ * This value should not be changed unless write_adc_calibration function in
50
+#define DWC2_NB_CHAN 8 /* Number of host channels */
106
+ * hw/arm/npcm7xx.c is also changed.
51
+#define DWC2_MAX_XFER_SIZE 65536 /* Max transfer size expected in HCTSIZ */
107
+ */
52
+
108
+#define NPCM7XX_ADC_NUM_CALIB 2
53
+typedef struct DWC2Packet DWC2Packet;
109
+
54
+typedef struct DWC2State DWC2State;
110
+/**
55
+typedef struct DWC2Class DWC2Class;
111
+ * struct NPCM7xxADCState - Analog to Digital Converter Module device state.
56
+
112
+ * @parent: System bus device.
57
+enum async_state {
113
+ * @iomem: Memory region through which registers are accessed.
58
+ DWC2_ASYNC_NONE = 0,
114
+ * @conv_timer: The timer counts down remaining cycles for the conversion.
59
+ DWC2_ASYNC_INITIALIZED,
115
+ * @irq: GIC interrupt line to fire on expiration (if enabled).
60
+ DWC2_ASYNC_INFLIGHT,
116
+ * @con: The Control Register.
61
+ DWC2_ASYNC_FINISHED,
117
+ * @data: The Data Buffer.
118
+ * @clock: The ADC Clock.
119
+ * @adci: The input voltage in units of uV. 1uv = 1e-6V.
120
+ * @vref: The external reference voltage.
121
+ * @iref: The internal reference voltage, initialized at launch time.
122
+ * @rv: The calibrated output values of 0.5V and 1.5V for the ADC.
123
+ */
124
+typedef struct {
125
+ SysBusDevice parent;
126
+
127
+ MemoryRegion iomem;
128
+
129
+ QEMUTimer conv_timer;
130
+
131
+ qemu_irq irq;
132
+ uint32_t con;
133
+ uint32_t data;
134
+ Clock *clock;
135
+
136
+ /* Voltages are in unit of uV. 1V = 1000000uV. */
137
+ uint32_t adci[NPCM7XX_ADC_NUM_INPUTS];
138
+ uint32_t vref;
139
+ uint32_t iref;
140
+
141
+ uint16_t calibration_r_values[NPCM7XX_ADC_NUM_CALIB];
142
+} NPCM7xxADCState;
143
+
144
+#define TYPE_NPCM7XX_ADC "npcm7xx-adc"
145
+#define NPCM7XX_ADC(obj) \
146
+ OBJECT_CHECK(NPCM7xxADCState, (obj), TYPE_NPCM7XX_ADC)
147
+
148
+#endif /* NPCM7XX_ADC_H */
149
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
150
index XXXXXXX..XXXXXXX 100644
151
--- a/include/hw/arm/npcm7xx.h
152
+++ b/include/hw/arm/npcm7xx.h
153
@@ -XXX,XX +XXX,XX @@
154
#define NPCM7XX_H
155
156
#include "hw/boards.h"
157
+#include "hw/adc/npcm7xx_adc.h"
158
#include "hw/cpu/a9mpcore.h"
159
#include "hw/gpio/npcm7xx_gpio.h"
160
#include "hw/mem/npcm7xx_mc.h"
161
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
162
NPCM7xxGCRState gcr;
163
NPCM7xxCLKState clk;
164
NPCM7xxTimerCtrlState tim[3];
165
+ NPCM7xxADCState adc;
166
NPCM7xxOTPState key_storage;
167
NPCM7xxOTPState fuse_array;
168
NPCM7xxMCState mc;
169
diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c
170
new file mode 100644
171
index XXXXXXX..XXXXXXX
172
--- /dev/null
173
+++ b/hw/adc/npcm7xx_adc.c
174
@@ -XXX,XX +XXX,XX @@
175
+/*
176
+ * Nuvoton NPCM7xx ADC Module
177
+ *
178
+ * Copyright 2020 Google LLC
179
+ *
180
+ * This program is free software; you can redistribute it and/or modify it
181
+ * under the terms of the GNU General Public License as published by the
182
+ * Free Software Foundation; either version 2 of the License, or
183
+ * (at your option) any later version.
184
+ *
185
+ * This program is distributed in the hope that it will be useful, but WITHOUT
186
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
187
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
188
+ * for more details.
189
+ */
190
+
191
+#include "qemu/osdep.h"
192
+#include "hw/adc/npcm7xx_adc.h"
193
+#include "hw/qdev-clock.h"
194
+#include "hw/qdev-properties.h"
195
+#include "hw/registerfields.h"
196
+#include "migration/vmstate.h"
197
+#include "qemu/log.h"
198
+#include "qemu/module.h"
199
+#include "qemu/timer.h"
200
+#include "qemu/units.h"
201
+#include "trace.h"
202
+
203
+REG32(NPCM7XX_ADC_CON, 0x0)
204
+REG32(NPCM7XX_ADC_DATA, 0x4)
205
+
206
+/* Register field definitions. */
207
+#define NPCM7XX_ADC_CON_MUX(rv) extract32(rv, 24, 4)
208
+#define NPCM7XX_ADC_CON_INT_EN BIT(21)
209
+#define NPCM7XX_ADC_CON_REFSEL BIT(19)
210
+#define NPCM7XX_ADC_CON_INT BIT(18)
211
+#define NPCM7XX_ADC_CON_EN BIT(17)
212
+#define NPCM7XX_ADC_CON_RST BIT(16)
213
+#define NPCM7XX_ADC_CON_CONV BIT(14)
214
+#define NPCM7XX_ADC_CON_DIV(rv) extract32(rv, 1, 8)
215
+
216
+#define NPCM7XX_ADC_MAX_RESULT 1023
217
+#define NPCM7XX_ADC_DEFAULT_IREF 2000000
218
+#define NPCM7XX_ADC_CONV_CYCLES 20
219
+#define NPCM7XX_ADC_RESET_CYCLES 10
220
+#define NPCM7XX_ADC_R0_INPUT 500000
221
+#define NPCM7XX_ADC_R1_INPUT 1500000
222
+
223
+static void npcm7xx_adc_reset(NPCM7xxADCState *s)
224
+{
225
+ timer_del(&s->conv_timer);
226
+ s->con = 0x000c0001;
227
+ s->data = 0x00000000;
228
+}
229
+
230
+static uint32_t npcm7xx_adc_convert(uint32_t input, uint32_t ref)
231
+{
232
+ uint32_t result;
233
+
234
+ result = input * (NPCM7XX_ADC_MAX_RESULT + 1) / ref;
235
+ if (result > NPCM7XX_ADC_MAX_RESULT) {
236
+ result = NPCM7XX_ADC_MAX_RESULT;
237
+ }
238
+
239
+ return result;
240
+}
241
+
242
+static uint32_t npcm7xx_adc_prescaler(NPCM7xxADCState *s)
243
+{
244
+ return 2 * (NPCM7XX_ADC_CON_DIV(s->con) + 1);
245
+}
246
+
247
+static void npcm7xx_adc_start_timer(Clock *clk, QEMUTimer *timer,
248
+ uint32_t cycles, uint32_t prescaler)
249
+{
250
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
251
+ int64_t ticks = cycles;
252
+ int64_t ns;
253
+
254
+ ticks *= prescaler;
255
+ ns = clock_ticks_to_ns(clk, ticks);
256
+ ns += now;
257
+ timer_mod(timer, ns);
258
+}
259
+
260
+static void npcm7xx_adc_start_convert(NPCM7xxADCState *s)
261
+{
262
+ uint32_t prescaler = npcm7xx_adc_prescaler(s);
263
+
264
+ npcm7xx_adc_start_timer(s->clock, &s->conv_timer, NPCM7XX_ADC_CONV_CYCLES,
265
+ prescaler);
266
+}
267
+
268
+static void npcm7xx_adc_convert_done(void *opaque)
269
+{
270
+ NPCM7xxADCState *s = opaque;
271
+ uint32_t input = NPCM7XX_ADC_CON_MUX(s->con);
272
+ uint32_t ref = (s->con & NPCM7XX_ADC_CON_REFSEL)
273
+ ? s->iref : s->vref;
274
+
275
+ if (input >= NPCM7XX_ADC_NUM_INPUTS) {
276
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid input: %u\n",
277
+ __func__, input);
278
+ return;
279
+ }
280
+ s->data = npcm7xx_adc_convert(s->adci[input], ref);
281
+ if (s->con & NPCM7XX_ADC_CON_INT_EN) {
282
+ s->con |= NPCM7XX_ADC_CON_INT;
283
+ qemu_irq_raise(s->irq);
284
+ }
285
+ s->con &= ~NPCM7XX_ADC_CON_CONV;
286
+}
287
+
288
+static void npcm7xx_adc_calibrate(NPCM7xxADCState *adc)
289
+{
290
+ adc->calibration_r_values[0] = npcm7xx_adc_convert(NPCM7XX_ADC_R0_INPUT,
291
+ adc->iref);
292
+ adc->calibration_r_values[1] = npcm7xx_adc_convert(NPCM7XX_ADC_R1_INPUT,
293
+ adc->iref);
294
+}
295
+
296
+static void npcm7xx_adc_write_con(NPCM7xxADCState *s, uint32_t new_con)
297
+{
298
+ uint32_t old_con = s->con;
299
+
300
+ /* Write ADC_INT to 1 to clear it */
301
+ if (new_con & NPCM7XX_ADC_CON_INT) {
302
+ new_con &= ~NPCM7XX_ADC_CON_INT;
303
+ qemu_irq_lower(s->irq);
304
+ } else if (old_con & NPCM7XX_ADC_CON_INT) {
305
+ new_con |= NPCM7XX_ADC_CON_INT;
306
+ }
307
+
308
+ s->con = new_con;
309
+
310
+ if (s->con & NPCM7XX_ADC_CON_RST) {
311
+ npcm7xx_adc_reset(s);
312
+ return;
313
+ }
314
+
315
+ if ((s->con & NPCM7XX_ADC_CON_EN)) {
316
+ if (s->con & NPCM7XX_ADC_CON_CONV) {
317
+ if (!(old_con & NPCM7XX_ADC_CON_CONV)) {
318
+ npcm7xx_adc_start_convert(s);
319
+ }
320
+ } else {
321
+ timer_del(&s->conv_timer);
322
+ }
323
+ }
324
+}
325
+
326
+static uint64_t npcm7xx_adc_read(void *opaque, hwaddr offset, unsigned size)
327
+{
328
+ uint64_t value = 0;
329
+ NPCM7xxADCState *s = opaque;
330
+
331
+ switch (offset) {
332
+ case A_NPCM7XX_ADC_CON:
333
+ value = s->con;
334
+ break;
335
+
336
+ case A_NPCM7XX_ADC_DATA:
337
+ value = s->data;
338
+ break;
339
+
340
+ default:
341
+ qemu_log_mask(LOG_GUEST_ERROR,
342
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
343
+ __func__, offset);
344
+ break;
345
+ }
346
+
347
+ trace_npcm7xx_adc_read(DEVICE(s)->canonical_path, offset, value);
348
+ return value;
349
+}
350
+
351
+static void npcm7xx_adc_write(void *opaque, hwaddr offset, uint64_t v,
352
+ unsigned size)
353
+{
354
+ NPCM7xxADCState *s = opaque;
355
+
356
+ trace_npcm7xx_adc_write(DEVICE(s)->canonical_path, offset, v);
357
+ switch (offset) {
358
+ case A_NPCM7XX_ADC_CON:
359
+ npcm7xx_adc_write_con(s, v);
360
+ break;
361
+
362
+ case A_NPCM7XX_ADC_DATA:
363
+ qemu_log_mask(LOG_GUEST_ERROR,
364
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
365
+ __func__, offset);
366
+ break;
367
+
368
+ default:
369
+ qemu_log_mask(LOG_GUEST_ERROR,
370
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
371
+ __func__, offset);
372
+ break;
373
+ }
374
+
375
+}
376
+
377
+static const struct MemoryRegionOps npcm7xx_adc_ops = {
378
+ .read = npcm7xx_adc_read,
379
+ .write = npcm7xx_adc_write,
380
+ .endianness = DEVICE_LITTLE_ENDIAN,
381
+ .valid = {
382
+ .min_access_size = 4,
383
+ .max_access_size = 4,
384
+ .unaligned = false,
385
+ },
62
+};
386
+};
63
+
387
+
64
+struct DWC2Packet {
388
+static void npcm7xx_adc_enter_reset(Object *obj, ResetType type)
65
+ USBPacket packet;
389
+{
66
+ uint32_t devadr;
390
+ NPCM7xxADCState *s = NPCM7XX_ADC(obj);
67
+ uint32_t epnum;
391
+
68
+ uint32_t epdir;
392
+ npcm7xx_adc_reset(s);
69
+ uint32_t mps;
393
+}
70
+ uint32_t pid;
394
+
71
+ uint32_t index;
395
+static void npcm7xx_adc_hold_reset(Object *obj)
72
+ uint32_t pcnt;
396
+{
73
+ uint32_t len;
397
+ NPCM7xxADCState *s = NPCM7XX_ADC(obj);
74
+ int32_t async;
398
+
75
+ bool small;
399
+ qemu_irq_lower(s->irq);
76
+ bool needs_service;
400
+}
401
+
402
+static void npcm7xx_adc_init(Object *obj)
403
+{
404
+ NPCM7xxADCState *s = NPCM7XX_ADC(obj);
405
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
406
+ int i;
407
+
408
+ sysbus_init_irq(sbd, &s->irq);
409
+
410
+ timer_init_ns(&s->conv_timer, QEMU_CLOCK_VIRTUAL,
411
+ npcm7xx_adc_convert_done, s);
412
+ memory_region_init_io(&s->iomem, obj, &npcm7xx_adc_ops, s,
413
+ TYPE_NPCM7XX_ADC, 4 * KiB);
414
+ sysbus_init_mmio(sbd, &s->iomem);
415
+ s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL);
416
+
417
+ for (i = 0; i < NPCM7XX_ADC_NUM_INPUTS; ++i) {
418
+ object_property_add_uint32_ptr(obj, "adci[*]",
419
+ &s->adci[i], OBJ_PROP_FLAG_WRITE);
420
+ }
421
+ object_property_add_uint32_ptr(obj, "vref",
422
+ &s->vref, OBJ_PROP_FLAG_WRITE);
423
+ npcm7xx_adc_calibrate(s);
424
+}
425
+
426
+static const VMStateDescription vmstate_npcm7xx_adc = {
427
+ .name = "npcm7xx-adc",
428
+ .version_id = 0,
429
+ .minimum_version_id = 0,
430
+ .fields = (VMStateField[]) {
431
+ VMSTATE_TIMER(conv_timer, NPCM7xxADCState),
432
+ VMSTATE_UINT32(con, NPCM7xxADCState),
433
+ VMSTATE_UINT32(data, NPCM7xxADCState),
434
+ VMSTATE_CLOCK(clock, NPCM7xxADCState),
435
+ VMSTATE_UINT32_ARRAY(adci, NPCM7xxADCState, NPCM7XX_ADC_NUM_INPUTS),
436
+ VMSTATE_UINT32(vref, NPCM7xxADCState),
437
+ VMSTATE_UINT32(iref, NPCM7xxADCState),
438
+ VMSTATE_UINT16_ARRAY(calibration_r_values, NPCM7xxADCState,
439
+ NPCM7XX_ADC_NUM_CALIB),
440
+ VMSTATE_END_OF_LIST(),
441
+ },
77
+};
442
+};
78
+
443
+
79
+struct DWC2State {
444
+static Property npcm7xx_timer_properties[] = {
80
+ /*< private >*/
445
+ DEFINE_PROP_UINT32("iref", NPCM7xxADCState, iref, NPCM7XX_ADC_DEFAULT_IREF),
81
+ SysBusDevice parent_obj;
446
+ DEFINE_PROP_END_OF_LIST(),
82
+
447
+};
83
+ /*< public >*/
448
+
84
+ USBBus bus;
449
+static void npcm7xx_adc_class_init(ObjectClass *klass, void *data)
85
+ qemu_irq irq;
450
+{
86
+ MemoryRegion *dma_mr;
451
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
87
+ AddressSpace dma_as;
452
+ DeviceClass *dc = DEVICE_CLASS(klass);
88
+ MemoryRegion container;
453
+
89
+ MemoryRegion hsotg;
454
+ dc->desc = "NPCM7xx ADC Module";
90
+ MemoryRegion fifos;
455
+ dc->vmsd = &vmstate_npcm7xx_adc;
91
+
456
+ rc->phases.enter = npcm7xx_adc_enter_reset;
92
+ union {
457
+ rc->phases.hold = npcm7xx_adc_hold_reset;
93
+#define DWC2_GLBREG_SIZE 0x70
458
+
94
+ uint32_t glbreg[DWC2_GLBREG_SIZE / sizeof(uint32_t)];
459
+ device_class_set_props(dc, npcm7xx_timer_properties);
95
+ struct {
460
+}
96
+ uint32_t gotgctl; /* 00 */
461
+
97
+ uint32_t gotgint; /* 04 */
462
+static const TypeInfo npcm7xx_adc_info = {
98
+ uint32_t gahbcfg; /* 08 */
463
+ .name = TYPE_NPCM7XX_ADC,
99
+ uint32_t gusbcfg; /* 0c */
464
+ .parent = TYPE_SYS_BUS_DEVICE,
100
+ uint32_t grstctl; /* 10 */
465
+ .instance_size = sizeof(NPCM7xxADCState),
101
+ uint32_t gintsts; /* 14 */
466
+ .class_init = npcm7xx_adc_class_init,
102
+ uint32_t gintmsk; /* 18 */
467
+ .instance_init = npcm7xx_adc_init,
103
+ uint32_t grxstsr; /* 1c */
468
+};
104
+ uint32_t grxstsp; /* 20 */
469
+
105
+ uint32_t grxfsiz; /* 24 */
470
+static void npcm7xx_adc_register_types(void)
106
+ uint32_t gnptxfsiz; /* 28 */
471
+{
107
+ uint32_t gnptxsts; /* 2c */
472
+ type_register_static(&npcm7xx_adc_info);
108
+ uint32_t gi2cctl; /* 30 */
473
+}
109
+ uint32_t gpvndctl; /* 34 */
474
+
110
+ uint32_t ggpio; /* 38 */
475
+type_init(npcm7xx_adc_register_types);
111
+ uint32_t guid; /* 3c */
476
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
112
+ uint32_t gsnpsid; /* 40 */
477
index XXXXXXX..XXXXXXX 100644
113
+ uint32_t ghwcfg1; /* 44 */
478
--- a/hw/arm/npcm7xx.c
114
+ uint32_t ghwcfg2; /* 48 */
479
+++ b/hw/arm/npcm7xx.c
115
+ uint32_t ghwcfg3; /* 4c */
480
@@ -XXX,XX +XXX,XX @@
116
+ uint32_t ghwcfg4; /* 50 */
481
#define NPCM7XX_EHCI_BA (0xf0806000)
117
+ uint32_t glpmcfg; /* 54 */
482
#define NPCM7XX_OHCI_BA (0xf0807000)
118
+ uint32_t gpwrdn; /* 58 */
483
119
+ uint32_t gdfifocfg; /* 5c */
484
+/* ADC Module */
120
+ uint32_t gadpctl; /* 60 */
485
+#define NPCM7XX_ADC_BA (0xf000c000)
121
+ uint32_t grefclk; /* 64 */
486
+
122
+ uint32_t gintmsk2; /* 68 */
487
/* Internal AHB SRAM */
123
+ uint32_t gintsts2; /* 6c */
488
#define NPCM7XX_RAM3_BA (0xc0008000)
489
#define NPCM7XX_RAM3_SZ (4 * KiB)
490
@@ -XXX,XX +XXX,XX @@
491
#define NPCM7XX_ROM_BA (0xffff0000)
492
#define NPCM7XX_ROM_SZ (64 * KiB)
493
494
+
495
/* Clock configuration values to be fixed up when bypassing bootloader */
496
497
/* Run PLL1 at 1600 MHz */
498
@@ -XXX,XX +XXX,XX @@
499
* interrupts.
500
*/
501
enum NPCM7xxInterrupt {
502
+ NPCM7XX_ADC_IRQ = 0,
503
NPCM7XX_UART0_IRQ = 2,
504
NPCM7XX_UART1_IRQ,
505
NPCM7XX_UART2_IRQ,
506
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init_fuses(NPCM7xxState *s)
507
sizeof(value));
508
}
509
510
+static void npcm7xx_write_adc_calibration(NPCM7xxState *s)
511
+{
512
+ /* Both ADC and the fuse array must have realized. */
513
+ QEMU_BUILD_BUG_ON(sizeof(s->adc.calibration_r_values) != 4);
514
+ npcm7xx_otp_array_write(&s->fuse_array, s->adc.calibration_r_values,
515
+ NPCM7XX_FUSE_ADC_CALIB, sizeof(s->adc.calibration_r_values));
516
+}
517
+
518
static qemu_irq npcm7xx_irq(NPCM7xxState *s, int n)
519
{
520
return qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
521
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
522
TYPE_NPCM7XX_FUSE_ARRAY);
523
object_initialize_child(obj, "mc", &s->mc, TYPE_NPCM7XX_MC);
524
object_initialize_child(obj, "rng", &s->rng, TYPE_NPCM7XX_RNG);
525
+ object_initialize_child(obj, "adc", &s->adc, TYPE_NPCM7XX_ADC);
526
527
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
528
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
529
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
530
sysbus_realize(SYS_BUS_DEVICE(&s->mc), &error_abort);
531
sysbus_mmio_map(SYS_BUS_DEVICE(&s->mc), 0, NPCM7XX_MC_BA);
532
533
+ /* ADC Modules. Cannot fail. */
534
+ qdev_connect_clock_in(DEVICE(&s->adc), "clock", qdev_get_clock_out(
535
+ DEVICE(&s->clk), "adc-clock"));
536
+ sysbus_realize(SYS_BUS_DEVICE(&s->adc), &error_abort);
537
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->adc), 0, NPCM7XX_ADC_BA);
538
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->adc), 0,
539
+ npcm7xx_irq(s, NPCM7XX_ADC_IRQ));
540
+ npcm7xx_write_adc_calibration(s);
541
+
542
/* Timer Modules (TIM). Cannot fail. */
543
QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
544
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
545
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
546
create_unimplemented_device("npcm7xx.vdmx", 0xe0800000, 4 * KiB);
547
create_unimplemented_device("npcm7xx.pcierc", 0xe1000000, 64 * KiB);
548
create_unimplemented_device("npcm7xx.kcs", 0xf0007000, 4 * KiB);
549
- create_unimplemented_device("npcm7xx.adc", 0xf000c000, 4 * KiB);
550
create_unimplemented_device("npcm7xx.gfxi", 0xf000e000, 4 * KiB);
551
create_unimplemented_device("npcm7xx.gpio[0]", 0xf0010000, 4 * KiB);
552
create_unimplemented_device("npcm7xx.gpio[1]", 0xf0011000, 4 * KiB);
553
diff --git a/tests/qtest/npcm7xx_adc-test.c b/tests/qtest/npcm7xx_adc-test.c
554
new file mode 100644
555
index XXXXXXX..XXXXXXX
556
--- /dev/null
557
+++ b/tests/qtest/npcm7xx_adc-test.c
558
@@ -XXX,XX +XXX,XX @@
559
+/*
560
+ * QTests for Nuvoton NPCM7xx ADCModules.
561
+ *
562
+ * Copyright 2020 Google LLC
563
+ *
564
+ * This program is free software; you can redistribute it and/or modify it
565
+ * under the terms of the GNU General Public License as published by the
566
+ * Free Software Foundation; either version 2 of the License, or
567
+ * (at your option) any later version.
568
+ *
569
+ * This program is distributed in the hope that it will be useful, but WITHOUT
570
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
571
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
572
+ * for more details.
573
+ */
574
+
575
+#include "qemu/osdep.h"
576
+#include "qemu/bitops.h"
577
+#include "qemu/timer.h"
578
+#include "libqos/libqtest.h"
579
+#include "qapi/qmp/qdict.h"
580
+
581
+#define REF_HZ (25000000)
582
+
583
+#define CON_OFFSET 0x0
584
+#define DATA_OFFSET 0x4
585
+
586
+#define NUM_INPUTS 8
587
+#define DEFAULT_IREF 2000000
588
+#define CONV_CYCLES 20
589
+#define RESET_CYCLES 10
590
+#define R0_INPUT 500000
591
+#define R1_INPUT 1500000
592
+#define MAX_RESULT 1023
593
+
594
+#define DEFAULT_CLKDIV 5
595
+
596
+#define FUSE_ARRAY_BA 0xf018a000
597
+#define FCTL_OFFSET 0x14
598
+#define FST_OFFSET 0x0
599
+#define FADDR_OFFSET 0x4
600
+#define FDATA_OFFSET 0x8
601
+#define ADC_CALIB_ADDR 24
602
+#define FUSE_READ 0x2
603
+
604
+/* Register field definitions. */
605
+#define CON_MUX(rv) ((rv) << 24)
606
+#define CON_INT_EN BIT(21)
607
+#define CON_REFSEL BIT(19)
608
+#define CON_INT BIT(18)
609
+#define CON_EN BIT(17)
610
+#define CON_RST BIT(16)
611
+#define CON_CONV BIT(14)
612
+#define CON_DIV(rv) extract32(rv, 1, 8)
613
+
614
+#define FST_RDST BIT(1)
615
+#define FDATA_MASK 0xff
616
+
617
+#define MAX_ERROR 10000
618
+#define MIN_CALIB_INPUT 100000
619
+#define MAX_CALIB_INPUT 1800000
620
+
621
+static const uint32_t input_list[] = {
622
+ 100000,
623
+ 500000,
624
+ 1000000,
625
+ 1500000,
626
+ 1800000,
627
+ 2000000,
628
+};
629
+
630
+static const uint32_t vref_list[] = {
631
+ 2000000,
632
+ 2200000,
633
+ 2500000,
634
+};
635
+
636
+static const uint32_t iref_list[] = {
637
+ 1800000,
638
+ 1900000,
639
+ 2000000,
640
+ 2100000,
641
+ 2200000,
642
+};
643
+
644
+static const uint32_t div_list[] = {0, 1, 3, 7, 15};
645
+
646
+typedef struct ADC {
647
+ int irq;
648
+ uint64_t base_addr;
649
+} ADC;
650
+
651
+ADC adc = {
652
+ .irq = 0,
653
+ .base_addr = 0xf000c000
654
+};
655
+
656
+static uint32_t adc_read_con(QTestState *qts, const ADC *adc)
657
+{
658
+ return qtest_readl(qts, adc->base_addr + CON_OFFSET);
659
+}
660
+
661
+static void adc_write_con(QTestState *qts, const ADC *adc, uint32_t value)
662
+{
663
+ qtest_writel(qts, adc->base_addr + CON_OFFSET, value);
664
+}
665
+
666
+static uint32_t adc_read_data(QTestState *qts, const ADC *adc)
667
+{
668
+ return qtest_readl(qts, adc->base_addr + DATA_OFFSET);
669
+}
670
+
671
+static uint32_t adc_calibrate(uint32_t measured, uint32_t *rv)
672
+{
673
+ return R0_INPUT + (R1_INPUT - R0_INPUT) * (int32_t)(measured - rv[0])
674
+ / (int32_t)(rv[1] - rv[0]);
675
+}
676
+
677
+static void adc_qom_set(QTestState *qts, const ADC *adc,
678
+ const char *name, uint32_t value)
679
+{
680
+ QDict *response;
681
+ const char *path = "/machine/soc/adc";
682
+
683
+ g_test_message("Setting properties %s of %s with value %u",
684
+ name, path, value);
685
+ response = qtest_qmp(qts, "{ 'execute': 'qom-set',"
686
+ " 'arguments': { 'path': %s, 'property': %s, 'value': %u}}",
687
+ path, name, value);
688
+ /* The qom set message returns successfully. */
689
+ g_assert_true(qdict_haskey(response, "return"));
690
+}
691
+
692
+static void adc_write_input(QTestState *qts, const ADC *adc,
693
+ uint32_t index, uint32_t value)
694
+{
695
+ char name[100];
696
+
697
+ sprintf(name, "adci[%u]", index);
698
+ adc_qom_set(qts, adc, name, value);
699
+}
700
+
701
+static void adc_write_vref(QTestState *qts, const ADC *adc, uint32_t value)
702
+{
703
+ adc_qom_set(qts, adc, "vref", value);
704
+}
705
+
706
+static uint32_t adc_calculate_output(uint32_t input, uint32_t ref)
707
+{
708
+ uint32_t output;
709
+
710
+ g_assert_cmpuint(input, <=, ref);
711
+ output = (input * (MAX_RESULT + 1)) / ref;
712
+ if (output > MAX_RESULT) {
713
+ output = MAX_RESULT;
714
+ }
715
+
716
+ return output;
717
+}
718
+
719
+static uint32_t adc_prescaler(QTestState *qts, const ADC *adc)
720
+{
721
+ uint32_t div = extract32(adc_read_con(qts, adc), 1, 8);
722
+
723
+ return 2 * (div + 1);
724
+}
725
+
726
+static int64_t adc_calculate_steps(uint32_t cycles, uint32_t prescale,
727
+ uint32_t clkdiv)
728
+{
729
+ return (NANOSECONDS_PER_SECOND / (REF_HZ >> clkdiv)) * cycles * prescale;
730
+}
731
+
732
+static void adc_wait_conv_finished(QTestState *qts, const ADC *adc,
733
+ uint32_t clkdiv)
734
+{
735
+ uint32_t prescaler = adc_prescaler(qts, adc);
736
+
737
+ /*
738
+ * ADC should takes roughly 20 cycles to convert one sample. So we assert it
739
+ * should take 10~30 cycles here.
740
+ */
741
+ qtest_clock_step(qts, adc_calculate_steps(CONV_CYCLES / 2, prescaler,
742
+ clkdiv));
743
+ /* ADC is still converting. */
744
+ g_assert_true(adc_read_con(qts, adc) & CON_CONV);
745
+ qtest_clock_step(qts, adc_calculate_steps(CONV_CYCLES, prescaler, clkdiv));
746
+ /* ADC has finished conversion. */
747
+ g_assert_false(adc_read_con(qts, adc) & CON_CONV);
748
+}
749
+
750
+/* Check ADC can be reset to default value. */
751
+static void test_init(gconstpointer adc_p)
752
+{
753
+ const ADC *adc = adc_p;
754
+
755
+ QTestState *qts = qtest_init("-machine quanta-gsj");
756
+ adc_write_con(qts, adc, CON_REFSEL | CON_INT);
757
+ g_assert_cmphex(adc_read_con(qts, adc), ==, CON_REFSEL);
758
+ qtest_quit(qts);
759
+}
760
+
761
+/* Check ADC can convert from an internal reference. */
762
+static void test_convert_internal(gconstpointer adc_p)
763
+{
764
+ const ADC *adc = adc_p;
765
+ uint32_t index, input, output, expected_output;
766
+ QTestState *qts = qtest_init("-machine quanta-gsj");
767
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
768
+
769
+ for (index = 0; index < NUM_INPUTS; ++index) {
770
+ for (size_t i = 0; i < ARRAY_SIZE(input_list); ++i) {
771
+ input = input_list[i];
772
+ expected_output = adc_calculate_output(input, DEFAULT_IREF);
773
+
774
+ adc_write_input(qts, adc, index, input);
775
+ adc_write_con(qts, adc, CON_MUX(index) | CON_REFSEL | CON_INT |
776
+ CON_EN | CON_CONV);
777
+ adc_wait_conv_finished(qts, adc, DEFAULT_CLKDIV);
778
+ g_assert_cmphex(adc_read_con(qts, adc), ==, CON_MUX(index) |
779
+ CON_REFSEL | CON_EN);
780
+ g_assert_false(qtest_get_irq(qts, adc->irq));
781
+ output = adc_read_data(qts, adc);
782
+ g_assert_cmpuint(output, ==, expected_output);
783
+ }
784
+ }
785
+
786
+ qtest_quit(qts);
787
+}
788
+
789
+/* Check ADC can convert from an external reference. */
790
+static void test_convert_external(gconstpointer adc_p)
791
+{
792
+ const ADC *adc = adc_p;
793
+ uint32_t index, input, vref, output, expected_output;
794
+ QTestState *qts = qtest_init("-machine quanta-gsj");
795
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
796
+
797
+ for (index = 0; index < NUM_INPUTS; ++index) {
798
+ for (size_t i = 0; i < ARRAY_SIZE(input_list); ++i) {
799
+ for (size_t j = 0; j < ARRAY_SIZE(vref_list); ++j) {
800
+ input = input_list[i];
801
+ vref = vref_list[j];
802
+ expected_output = adc_calculate_output(input, vref);
803
+
804
+ adc_write_input(qts, adc, index, input);
805
+ adc_write_vref(qts, adc, vref);
806
+ adc_write_con(qts, adc, CON_MUX(index) | CON_INT | CON_EN |
807
+ CON_CONV);
808
+ adc_wait_conv_finished(qts, adc, DEFAULT_CLKDIV);
809
+ g_assert_cmphex(adc_read_con(qts, adc), ==,
810
+ CON_MUX(index) | CON_EN);
811
+ g_assert_false(qtest_get_irq(qts, adc->irq));
812
+ output = adc_read_data(qts, adc);
813
+ g_assert_cmpuint(output, ==, expected_output);
814
+ }
815
+ }
816
+ }
817
+
818
+ qtest_quit(qts);
819
+}
820
+
821
+/* Check ADC interrupt files if and only if CON_INT_EN is set. */
822
+static void test_interrupt(gconstpointer adc_p)
823
+{
824
+ const ADC *adc = adc_p;
825
+ uint32_t index, input, output, expected_output;
826
+ QTestState *qts = qtest_init("-machine quanta-gsj");
827
+
828
+ index = 1;
829
+ input = input_list[1];
830
+ expected_output = adc_calculate_output(input, DEFAULT_IREF);
831
+
832
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
833
+ adc_write_input(qts, adc, index, input);
834
+ g_assert_false(qtest_get_irq(qts, adc->irq));
835
+ adc_write_con(qts, adc, CON_MUX(index) | CON_INT_EN | CON_REFSEL | CON_INT
836
+ | CON_EN | CON_CONV);
837
+ adc_wait_conv_finished(qts, adc, DEFAULT_CLKDIV);
838
+ g_assert_cmphex(adc_read_con(qts, adc), ==, CON_MUX(index) | CON_INT_EN
839
+ | CON_REFSEL | CON_INT | CON_EN);
840
+ g_assert_true(qtest_get_irq(qts, adc->irq));
841
+ output = adc_read_data(qts, adc);
842
+ g_assert_cmpuint(output, ==, expected_output);
843
+
844
+ qtest_quit(qts);
845
+}
846
+
847
+/* Check ADC is reset after setting ADC_RST for 10 ADC cycles. */
848
+static void test_reset(gconstpointer adc_p)
849
+{
850
+ const ADC *adc = adc_p;
851
+ QTestState *qts = qtest_init("-machine quanta-gsj");
852
+
853
+ for (size_t i = 0; i < ARRAY_SIZE(div_list); ++i) {
854
+ uint32_t div = div_list[i];
855
+
856
+ adc_write_con(qts, adc, CON_INT | CON_EN | CON_RST | CON_DIV(div));
857
+ qtest_clock_step(qts, adc_calculate_steps(RESET_CYCLES,
858
+ adc_prescaler(qts, adc), DEFAULT_CLKDIV));
859
+ g_assert_false(adc_read_con(qts, adc) & CON_EN);
860
+ }
861
+ qtest_quit(qts);
862
+}
863
+
864
+/* Check ADC Calibration works as desired. */
865
+static void test_calibrate(gconstpointer adc_p)
866
+{
867
+ int i, j;
868
+ const ADC *adc = adc_p;
869
+
870
+ for (j = 0; j < ARRAY_SIZE(iref_list); ++j) {
871
+ uint32_t iref = iref_list[j];
872
+ uint32_t expected_rv[] = {
873
+ adc_calculate_output(R0_INPUT, iref),
874
+ adc_calculate_output(R1_INPUT, iref),
124
+ };
875
+ };
125
+ };
876
+ char buf[100];
126
+
877
+ QTestState *qts;
127
+ union {
878
+
128
+#define DWC2_FSZREG_SIZE 0x04
879
+ sprintf(buf, "-machine quanta-gsj -global npcm7xx-adc.iref=%u", iref);
129
+ uint32_t fszreg[DWC2_FSZREG_SIZE / sizeof(uint32_t)];
880
+ qts = qtest_init(buf);
130
+ struct {
881
+
131
+ uint32_t hptxfsiz; /* 100 */
882
+ /* Check the converted value is correct using the calibration value. */
132
+ };
883
+ for (i = 0; i < ARRAY_SIZE(input_list); ++i) {
133
+ };
884
+ uint32_t input;
134
+
885
+ uint32_t output;
135
+ union {
886
+ uint32_t expected_output;
136
+#define DWC2_HREG0_SIZE 0x44
887
+ uint32_t calibrated_voltage;
137
+ uint32_t hreg0[DWC2_HREG0_SIZE / sizeof(uint32_t)];
888
+ uint32_t index = 0;
138
+ struct {
889
+
139
+ uint32_t hcfg; /* 400 */
890
+ input = input_list[i];
140
+ uint32_t hfir; /* 404 */
891
+ /* Calibration only works for input range 0.1V ~ 1.8V. */
141
+ uint32_t hfnum; /* 408 */
892
+ if (input < MIN_CALIB_INPUT || input > MAX_CALIB_INPUT) {
142
+ uint32_t rsvd0; /* 40c */
893
+ continue;
143
+ uint32_t hptxsts; /* 410 */
894
+ }
144
+ uint32_t haint; /* 414 */
895
+ expected_output = adc_calculate_output(input, iref);
145
+ uint32_t haintmsk; /* 418 */
896
+
146
+ uint32_t hflbaddr; /* 41c */
897
+ adc_write_input(qts, adc, index, input);
147
+ uint32_t rsvd1[8]; /* 420-43c */
898
+ adc_write_con(qts, adc, CON_MUX(index) | CON_REFSEL | CON_INT |
148
+ uint32_t hprt0; /* 440 */
899
+ CON_EN | CON_CONV);
149
+ };
900
+ adc_wait_conv_finished(qts, adc, DEFAULT_CLKDIV);
150
+ };
901
+ g_assert_cmphex(adc_read_con(qts, adc), ==,
151
+
902
+ CON_REFSEL | CON_MUX(index) | CON_EN);
152
+#define DWC2_HREG1_SIZE (0x20 * DWC2_NB_CHAN)
903
+ output = adc_read_data(qts, adc);
153
+ uint32_t hreg1[DWC2_HREG1_SIZE / sizeof(uint32_t)];
904
+ g_assert_cmpuint(output, ==, expected_output);
154
+
905
+
155
+#define hcchar(_ch) hreg1[((_ch) << 3) + 0] /* 500, 520, ... */
906
+ calibrated_voltage = adc_calibrate(output, expected_rv);
156
+#define hcsplt(_ch) hreg1[((_ch) << 3) + 1] /* 504, 524, ... */
907
+ g_assert_cmpuint(calibrated_voltage, >, input - MAX_ERROR);
157
+#define hcint(_ch) hreg1[((_ch) << 3) + 2] /* 508, 528, ... */
908
+ g_assert_cmpuint(calibrated_voltage, <, input + MAX_ERROR);
158
+#define hcintmsk(_ch) hreg1[((_ch) << 3) + 3] /* 50c, 52c, ... */
909
+ }
159
+#define hctsiz(_ch) hreg1[((_ch) << 3) + 4] /* 510, 530, ... */
910
+
160
+#define hcdma(_ch) hreg1[((_ch) << 3) + 5] /* 514, 534, ... */
911
+ qtest_quit(qts);
161
+#define hcdmab(_ch) hreg1[((_ch) << 3) + 7] /* 51c, 53c, ... */
912
+ }
162
+
913
+}
163
+ union {
914
+
164
+#define DWC2_PCGREG_SIZE 0x08
915
+static void adc_add_test(const char *name, const ADC* wd,
165
+ uint32_t pcgreg[DWC2_PCGREG_SIZE / sizeof(uint32_t)];
916
+ GTestDataFunc fn)
166
+ struct {
917
+{
167
+ uint32_t pcgctl; /* e00 */
918
+ g_autofree char *full_name = g_strdup_printf("npcm7xx_adc/%s", name);
168
+ uint32_t pcgcctl1; /* e04 */
919
+ qtest_add_data_func(full_name, wd, fn);
169
+ };
920
+}
170
+ };
921
+#define add_test(name, td) adc_add_test(#name, td, test_##name)
171
+
922
+
172
+ /* TODO - implement FIFO registers for slave mode */
923
+int main(int argc, char **argv)
173
+#define DWC2_HFIFO_SIZE (0x1000 * DWC2_NB_CHAN)
924
+{
174
+
925
+ g_test_init(&argc, &argv, NULL);
175
+ /*
926
+
176
+ * Internal state
927
+ add_test(init, &adc);
177
+ */
928
+ add_test(convert_internal, &adc);
178
+ QEMUTimer *eof_timer;
929
+ add_test(convert_external, &adc);
179
+ QEMUTimer *frame_timer;
930
+ add_test(interrupt, &adc);
180
+ QEMUBH *async_bh;
931
+ add_test(reset, &adc);
181
+ int64_t sof_time;
932
+ add_test(calibrate, &adc);
182
+ int64_t usb_frame_time;
933
+
183
+ int64_t usb_bit_time;
934
+ return g_test_run();
184
+ uint32_t usb_version;
935
+}
185
+ uint16_t frame_number;
936
diff --git a/hw/adc/meson.build b/hw/adc/meson.build
186
+ uint16_t fi;
937
index XXXXXXX..XXXXXXX 100644
187
+ uint16_t next_chan;
938
--- a/hw/adc/meson.build
188
+ bool working;
939
+++ b/hw/adc/meson.build
189
+ USBPort uport;
940
@@ -1 +1,2 @@
190
+ DWC2Packet packet[DWC2_NB_CHAN]; /* one packet per chan */
941
softmmu_ss.add(when: 'CONFIG_STM32F2XX_ADC', if_true: files('stm32f2xx_adc.c'))
191
+ uint8_t usb_buf[DWC2_NB_CHAN][DWC2_MAX_XFER_SIZE]; /* one buffer per chan */
942
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_adc.c'))
192
+};
943
diff --git a/hw/adc/trace-events b/hw/adc/trace-events
193
+
944
new file mode 100644
194
+struct DWC2Class {
945
index XXXXXXX..XXXXXXX
195
+ /*< private >*/
946
--- /dev/null
196
+ SysBusDeviceClass parent_class;
947
+++ b/hw/adc/trace-events
197
+ ResettablePhases parent_phases;
948
@@ -XXX,XX +XXX,XX @@
198
+
949
+# See docs/devel/tracing.txt for syntax documentation.
199
+ /*< public >*/
950
+
200
+};
951
+# npcm7xx_adc.c
201
+
952
+npcm7xx_adc_read(const char *id, uint64_t offset, uint32_t value) " %s offset: 0x%04" PRIx64 " value 0x%04" PRIx32
202
+#define TYPE_DWC2_USB "dwc2-usb"
953
+npcm7xx_adc_write(const char *id, uint64_t offset, uint32_t value) "%s offset: 0x%04" PRIx64 " value 0x%04" PRIx32
203
+#define DWC2_USB(obj) \
954
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
204
+ OBJECT_CHECK(DWC2State, (obj), TYPE_DWC2_USB)
955
index XXXXXXX..XXXXXXX 100644
205
+#define DWC2_CLASS(klass) \
956
--- a/tests/qtest/meson.build
206
+ OBJECT_CLASS_CHECK(DWC2Class, (klass), TYPE_DWC2_USB)
957
+++ b/tests/qtest/meson.build
207
+#define DWC2_GET_CLASS(obj) \
958
@@ -XXX,XX +XXX,XX @@ qtests_sparc64 = \
208
+ OBJECT_GET_CLASS(DWC2Class, (obj), TYPE_DWC2_USB)
959
['prom-env-test', 'boot-serial-test']
209
+
960
210
+#endif
961
qtests_npcm7xx = \
962
- ['npcm7xx_gpio-test',
963
+ ['npcm7xx_adc-test',
964
+ 'npcm7xx_gpio-test',
965
'npcm7xx_rng-test',
966
'npcm7xx_timer-test',
967
'npcm7xx_watchdog_timer-test']
211
--
968
--
212
2.20.1
969
2.20.1
213
970
214
971
diff view generated by jsdifflib
1
From: Paul Zimmerman <pauldzim@gmail.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
Add BCM2835 SOC MPHI (Message-based Parallel Host Interface)
3
The PWM module is part of NPCM7XX module. Each NPCM7XX module has two
4
emulation. It is very basic, only providing the FIQ interrupt
4
identical PWM modules. Each module contains 4 PWM entries. Each PWM has
5
needed to allow the dwc-otg USB host controller driver in the
5
two outputs: frequency and duty_cycle. Both are computed using inputs
6
Raspbian kernel to function.
6
from software side.
7
7
8
Signed-off-by: Paul Zimmerman <pauldzim@gmail.com>
8
This module does not model detail pulse signals since it is expensive.
9
Acked-by: Philippe Mathieu-Daude <f4bug@amsat.org>
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.
13
14
The user can read the duty cycle and frequency using qom-get command.
15
16
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
17
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
18
Signed-off-by: Hao Wu <wuhaotsh@google.com>
19
Message-id: 20210108190945.949196-5-wuhaotsh@google.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20200520235349.21215-2-pauldzim@gmail.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
22
---
14
include/hw/arm/bcm2835_peripherals.h | 2 +
23
docs/system/arm/nuvoton.rst | 2 +-
15
include/hw/misc/bcm2835_mphi.h | 44 ++++++
24
include/hw/arm/npcm7xx.h | 2 +
16
hw/arm/bcm2835_peripherals.c | 17 +++
25
include/hw/misc/npcm7xx_pwm.h | 105 +++++++
17
hw/misc/bcm2835_mphi.c | 191 +++++++++++++++++++++++++++
26
hw/arm/npcm7xx.c | 26 +-
18
hw/misc/Makefile.objs | 1 +
27
hw/misc/npcm7xx_pwm.c | 550 ++++++++++++++++++++++++++++++++++
19
5 files changed, 255 insertions(+)
28
hw/misc/meson.build | 1 +
20
create mode 100644 include/hw/misc/bcm2835_mphi.h
29
hw/misc/trace-events | 6 +
21
create mode 100644 hw/misc/bcm2835_mphi.c
30
7 files changed, 689 insertions(+), 3 deletions(-)
31
create mode 100644 include/hw/misc/npcm7xx_pwm.h
32
create mode 100644 hw/misc/npcm7xx_pwm.c
22
33
23
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
34
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
24
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/arm/bcm2835_peripherals.h
36
--- a/docs/system/arm/nuvoton.rst
26
+++ b/include/hw/arm/bcm2835_peripherals.h
37
+++ b/docs/system/arm/nuvoton.rst
38
@@ -XXX,XX +XXX,XX @@ Supported devices
39
* USB host (USBH)
40
* GPIO controller
41
* Analog to Digital Converter (ADC)
42
+ * Pulse Width Modulation (PWM)
43
44
Missing devices
45
---------------
46
@@ -XXX,XX +XXX,XX @@ Missing devices
47
* Peripheral SPI controller (PSPI)
48
* SD/MMC host
49
* PECI interface
50
- * Pulse Width Modulation (PWM)
51
* Tachometer
52
* PCI and PCIe root complex and bridges
53
* VDM and MCTP support
54
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
55
index XXXXXXX..XXXXXXX 100644
56
--- a/include/hw/arm/npcm7xx.h
57
+++ b/include/hw/arm/npcm7xx.h
27
@@ -XXX,XX +XXX,XX @@
58
@@ -XXX,XX +XXX,XX @@
28
#include "hw/misc/bcm2835_property.h"
59
#include "hw/mem/npcm7xx_mc.h"
29
#include "hw/misc/bcm2835_rng.h"
60
#include "hw/misc/npcm7xx_clk.h"
30
#include "hw/misc/bcm2835_mbox.h"
61
#include "hw/misc/npcm7xx_gcr.h"
31
+#include "hw/misc/bcm2835_mphi.h"
62
+#include "hw/misc/npcm7xx_pwm.h"
32
#include "hw/misc/bcm2835_thermal.h"
63
#include "hw/misc/npcm7xx_rng.h"
33
#include "hw/sd/sdhci.h"
64
#include "hw/nvram/npcm7xx_otp.h"
34
#include "hw/sd/bcm2835_sdhost.h"
65
#include "hw/timer/npcm7xx_timer.h"
35
@@ -XXX,XX +XXX,XX @@ typedef struct BCM2835PeripheralState {
66
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
36
qemu_irq irq, fiq;
67
NPCM7xxCLKState clk;
37
68
NPCM7xxTimerCtrlState tim[3];
38
BCM2835SystemTimerState systmr;
69
NPCM7xxADCState adc;
39
+ BCM2835MphiState mphi;
70
+ NPCM7xxPWMState pwm[2];
40
UnimplementedDeviceState armtmr;
71
NPCM7xxOTPState key_storage;
41
UnimplementedDeviceState cprman;
72
NPCM7xxOTPState fuse_array;
42
UnimplementedDeviceState a2w;
73
NPCM7xxMCState mc;
43
diff --git a/include/hw/misc/bcm2835_mphi.h b/include/hw/misc/bcm2835_mphi.h
74
diff --git a/include/hw/misc/npcm7xx_pwm.h b/include/hw/misc/npcm7xx_pwm.h
44
new file mode 100644
75
new file mode 100644
45
index XXXXXXX..XXXXXXX
76
index XXXXXXX..XXXXXXX
46
--- /dev/null
77
--- /dev/null
47
+++ b/include/hw/misc/bcm2835_mphi.h
78
+++ b/include/hw/misc/npcm7xx_pwm.h
48
@@ -XXX,XX +XXX,XX @@
79
@@ -XXX,XX +XXX,XX @@
49
+/*
80
+/*
50
+ * BCM2835 SOC MPHI state definitions
81
+ * Nuvoton NPCM7xx PWM Module
51
+ *
82
+ *
52
+ * Copyright (c) 2020 Paul Zimmerman <pauldzim@gmail.com>
83
+ * Copyright 2020 Google LLC
53
+ *
84
+ *
54
+ * This program is free software; you can redistribute it and/or modify
85
+ * This program is free software; you can redistribute it and/or modify it
55
+ * it under the terms of the GNU General Public License as published by
86
+ * under the terms of the GNU General Public License as published by the
56
+ * the Free Software Foundation; either version 2 of the License, or
87
+ * Free Software Foundation; either version 2 of the License, or
57
+ * (at your option) any later version.
88
+ * (at your option) any later version.
58
+ *
89
+ *
59
+ * This program is distributed in the hope that it will be useful,
90
+ * This program is distributed in the hope that it will be useful, but WITHOUT
60
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
91
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
61
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
92
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
62
+ * GNU General Public License for more details.
93
+ * for more details.
63
+ */
94
+ */
64
+
95
+#ifndef NPCM7XX_PWM_H
65
+#ifndef HW_MISC_BCM2835_MPHI_H
96
+#define NPCM7XX_PWM_H
66
+#define HW_MISC_BCM2835_MPHI_H
97
+
67
+
98
+#include "hw/clock.h"
99
+#include "hw/sysbus.h"
68
+#include "hw/irq.h"
100
+#include "hw/irq.h"
69
+#include "hw/sysbus.h"
101
+
70
+
102
+/* Each PWM module holds 4 PWM channels. */
71
+#define MPHI_MMIO_SIZE 0x1000
103
+#define NPCM7XX_PWM_PER_MODULE 4
72
+
104
+
73
+typedef struct BCM2835MphiState BCM2835MphiState;
105
+/*
74
+
106
+ * Number of registers in one pwm module. Don't change this without increasing
75
+struct BCM2835MphiState {
107
+ * the version_id in vmstate.
76
+ SysBusDevice parent_obj;
108
+ */
77
+ qemu_irq irq;
109
+#define NPCM7XX_PWM_NR_REGS (0x54 / sizeof(uint32_t))
110
+
111
+/*
112
+ * The maximum duty values. Each duty unit represents 1/NPCM7XX_PWM_MAX_DUTY
113
+ * cycles. For example, if NPCM7XX_PWM_MAX_DUTY=1,000,000 and a PWM has a duty
114
+ * value of 100,000 the duty cycle for that PWM is 10%.
115
+ */
116
+#define NPCM7XX_PWM_MAX_DUTY 1000000
117
+
118
+typedef struct NPCM7xxPWMState NPCM7xxPWMState;
119
+
120
+/**
121
+ * struct NPCM7xxPWM - The state of a single PWM channel.
122
+ * @module: The PWM module that contains this channel.
123
+ * @irq: GIC interrupt line to fire on expiration if enabled.
124
+ * @running: Whether this PWM channel is generating output.
125
+ * @inverted: Whether this PWM channel is inverted.
126
+ * @index: The index of this PWM channel.
127
+ * @cnr: The counter register.
128
+ * @cmr: The comparator register.
129
+ * @pdr: The data register.
130
+ * @pwdr: The watchdog register.
131
+ * @freq: The frequency of this PWM channel.
132
+ * @duty: The duty cycle of this PWM channel. One unit represents
133
+ * 1/NPCM7XX_MAX_DUTY cycles.
134
+ */
135
+typedef struct NPCM7xxPWM {
136
+ NPCM7xxPWMState *module;
137
+
138
+ qemu_irq irq;
139
+
140
+ bool running;
141
+ bool inverted;
142
+
143
+ uint8_t index;
144
+ uint32_t cnr;
145
+ uint32_t cmr;
146
+ uint32_t pdr;
147
+ uint32_t pwdr;
148
+
149
+ uint32_t freq;
150
+ uint32_t duty;
151
+} NPCM7xxPWM;
152
+
153
+/**
154
+ * struct NPCM7xxPWMState - Pulse Width Modulation device state.
155
+ * @parent: System bus device.
156
+ * @iomem: Memory region through which registers are accessed.
157
+ * @clock: The PWM clock.
158
+ * @pwm: The PWM channels owned by this module.
159
+ * @ppr: The prescaler register.
160
+ * @csr: The clock selector register.
161
+ * @pcr: The control register.
162
+ * @pier: The interrupt enable register.
163
+ * @piir: The interrupt indication register.
164
+ */
165
+struct NPCM7xxPWMState {
166
+ SysBusDevice parent;
167
+
78
+ MemoryRegion iomem;
168
+ MemoryRegion iomem;
79
+
169
+
80
+ uint32_t outdda;
170
+ Clock *clock;
81
+ uint32_t outddb;
171
+ NPCM7xxPWM pwm[NPCM7XX_PWM_PER_MODULE];
82
+ uint32_t ctrl;
172
+
83
+ uint32_t intstat;
173
+ uint32_t ppr;
84
+ uint32_t swirq;
174
+ uint32_t csr;
175
+ uint32_t pcr;
176
+ uint32_t pier;
177
+ uint32_t piir;
85
+};
178
+};
86
+
179
+
87
+#define TYPE_BCM2835_MPHI "bcm2835-mphi"
180
+#define TYPE_NPCM7XX_PWM "npcm7xx-pwm"
88
+
181
+#define NPCM7XX_PWM(obj) \
89
+#define BCM2835_MPHI(obj) \
182
+ OBJECT_CHECK(NPCM7xxPWMState, (obj), TYPE_NPCM7XX_PWM)
90
+ OBJECT_CHECK(BCM2835MphiState, (obj), TYPE_BCM2835_MPHI)
183
+
91
+
184
+#endif /* NPCM7XX_PWM_H */
92
+#endif
185
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
93
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
94
index XXXXXXX..XXXXXXX 100644
186
index XXXXXXX..XXXXXXX 100644
95
--- a/hw/arm/bcm2835_peripherals.c
187
--- a/hw/arm/npcm7xx.c
96
+++ b/hw/arm/bcm2835_peripherals.c
188
+++ b/hw/arm/npcm7xx.c
97
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
189
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
98
OBJECT(&s->sdhci.sdbus));
190
NPCM7XX_WDG2_IRQ, /* Timer Module 2 Watchdog */
99
object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhost",
191
NPCM7XX_EHCI_IRQ = 61,
100
OBJECT(&s->sdhost.sdbus));
192
NPCM7XX_OHCI_IRQ = 62,
101
+
193
+ NPCM7XX_PWM0_IRQ = 93, /* PWM module 0 */
102
+ /* Mphi */
194
+ NPCM7XX_PWM1_IRQ, /* PWM module 1 */
103
+ sysbus_init_child_obj(obj, "mphi", &s->mphi, sizeof(s->mphi),
195
NPCM7XX_GPIO0_IRQ = 116,
104
+ TYPE_BCM2835_MPHI);
196
NPCM7XX_GPIO1_IRQ,
197
NPCM7XX_GPIO2_IRQ,
198
@@ -XXX,XX +XXX,XX @@ static const hwaddr npcm7xx_fiu3_flash_addr[] = {
199
0xb8000000, /* CS3 */
200
};
201
202
+/* Register base address for each PWM Module */
203
+static const hwaddr npcm7xx_pwm_addr[] = {
204
+ 0xf0103000,
205
+ 0xf0104000,
206
+};
207
+
208
static const struct {
209
hwaddr regs_addr;
210
uint32_t unconnected_pins;
211
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
212
object_initialize_child(obj, npcm7xx_fiu[i].name, &s->fiu[i],
213
TYPE_NPCM7XX_FIU);
214
}
215
+
216
+ for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
217
+ object_initialize_child(obj, "pwm[*]", &s->pwm[i], TYPE_NPCM7XX_PWM);
218
+ }
105
}
219
}
106
220
107
static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
221
static void npcm7xx_realize(DeviceState *dev, Error **errp)
108
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
222
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
109
223
sysbus_connect_irq(SYS_BUS_DEVICE(&s->ohci), 0,
110
object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->gpio), "sd-bus");
224
npcm7xx_irq(s, NPCM7XX_OHCI_IRQ));
111
225
112
+ /* Mphi */
226
+ /* PWM Modules. Cannot fail. */
113
+ object_property_set_bool(OBJECT(&s->mphi), true, "realized", &err);
227
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_pwm_addr) != ARRAY_SIZE(s->pwm));
114
+ if (err) {
228
+ for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
115
+ error_propagate(errp, err);
229
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->pwm[i]);
116
+ return;
230
+
117
+ }
231
+ qdev_connect_clock_in(DEVICE(&s->pwm[i]), "clock", qdev_get_clock_out(
118
+
232
+ DEVICE(&s->clk), "apb3-clock"));
119
+ memory_region_add_subregion(&s->peri_mr, MPHI_OFFSET,
233
+ sysbus_realize(sbd, &error_abort);
120
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mphi), 0));
234
+ sysbus_mmio_map(sbd, 0, npcm7xx_pwm_addr[i]);
121
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->mphi), 0,
235
+ sysbus_connect_irq(sbd, i, npcm7xx_irq(s, NPCM7XX_PWM0_IRQ + i));
122
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
236
+ }
123
+ INTERRUPT_HOSTPORT));
237
+
124
+
238
/*
125
create_unimp(s, &s->armtmr, "bcm2835-sp804", ARMCTRL_TIMER0_1_OFFSET, 0x40);
239
* Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
126
create_unimp(s, &s->cprman, "bcm2835-cprman", CPRMAN_OFFSET, 0x1000);
240
* specified, but this is a programming error.
127
create_unimp(s, &s->a2w, "bcm2835-a2w", A2W_OFFSET, 0x1000);
241
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
128
diff --git a/hw/misc/bcm2835_mphi.c b/hw/misc/bcm2835_mphi.c
242
create_unimplemented_device("npcm7xx.peci", 0xf0100000, 4 * KiB);
243
create_unimplemented_device("npcm7xx.siox[1]", 0xf0101000, 4 * KiB);
244
create_unimplemented_device("npcm7xx.siox[2]", 0xf0102000, 4 * KiB);
245
- create_unimplemented_device("npcm7xx.pwm[0]", 0xf0103000, 4 * KiB);
246
- create_unimplemented_device("npcm7xx.pwm[1]", 0xf0104000, 4 * KiB);
247
create_unimplemented_device("npcm7xx.mft[0]", 0xf0180000, 4 * KiB);
248
create_unimplemented_device("npcm7xx.mft[1]", 0xf0181000, 4 * KiB);
249
create_unimplemented_device("npcm7xx.mft[2]", 0xf0182000, 4 * KiB);
250
diff --git a/hw/misc/npcm7xx_pwm.c b/hw/misc/npcm7xx_pwm.c
129
new file mode 100644
251
new file mode 100644
130
index XXXXXXX..XXXXXXX
252
index XXXXXXX..XXXXXXX
131
--- /dev/null
253
--- /dev/null
132
+++ b/hw/misc/bcm2835_mphi.c
254
+++ b/hw/misc/npcm7xx_pwm.c
133
@@ -XXX,XX +XXX,XX @@
255
@@ -XXX,XX +XXX,XX @@
134
+/*
256
+/*
135
+ * BCM2835 SOC MPHI emulation
257
+ * Nuvoton NPCM7xx PWM Module
136
+ *
258
+ *
137
+ * Very basic emulation, only providing the FIQ interrupt needed to
259
+ * Copyright 2020 Google LLC
138
+ * allow the dwc-otg USB host controller driver in the Raspbian kernel
139
+ * to function.
140
+ *
260
+ *
141
+ * Copyright (c) 2020 Paul Zimmerman <pauldzim@gmail.com>
261
+ * This program is free software; you can redistribute it and/or modify it
142
+ *
262
+ * under the terms of the GNU General Public License as published by the
143
+ * This program is free software; you can redistribute it and/or modify
263
+ * Free Software Foundation; either version 2 of the License, or
144
+ * it under the terms of the GNU General Public License as published by
145
+ * the Free Software Foundation; either version 2 of the License, or
146
+ * (at your option) any later version.
264
+ * (at your option) any later version.
147
+ *
265
+ *
148
+ * This program is distributed in the hope that it will be useful,
266
+ * This program is distributed in the hope that it will be useful, but WITHOUT
149
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
267
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
150
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
268
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
151
+ * GNU General Public License for more details.
269
+ * for more details.
152
+ */
270
+ */
153
+
271
+
154
+#include "qemu/osdep.h"
272
+#include "qemu/osdep.h"
155
+#include "qapi/error.h"
273
+#include "hw/irq.h"
156
+#include "hw/misc/bcm2835_mphi.h"
274
+#include "hw/qdev-clock.h"
275
+#include "hw/qdev-properties.h"
276
+#include "hw/misc/npcm7xx_pwm.h"
277
+#include "hw/registerfields.h"
157
+#include "migration/vmstate.h"
278
+#include "migration/vmstate.h"
279
+#include "qemu/bitops.h"
158
+#include "qemu/error-report.h"
280
+#include "qemu/error-report.h"
159
+#include "qemu/log.h"
281
+#include "qemu/log.h"
160
+#include "qemu/main-loop.h"
282
+#include "qemu/module.h"
161
+
283
+#include "qemu/units.h"
162
+static inline void mphi_raise_irq(BCM2835MphiState *s)
284
+#include "trace.h"
163
+{
285
+
164
+ qemu_set_irq(s->irq, 1);
286
+REG32(NPCM7XX_PWM_PPR, 0x00);
165
+}
287
+REG32(NPCM7XX_PWM_CSR, 0x04);
166
+
288
+REG32(NPCM7XX_PWM_PCR, 0x08);
167
+static inline void mphi_lower_irq(BCM2835MphiState *s)
289
+REG32(NPCM7XX_PWM_CNR0, 0x0c);
168
+{
290
+REG32(NPCM7XX_PWM_CMR0, 0x10);
169
+ qemu_set_irq(s->irq, 0);
291
+REG32(NPCM7XX_PWM_PDR0, 0x14);
170
+}
292
+REG32(NPCM7XX_PWM_CNR1, 0x18);
171
+
293
+REG32(NPCM7XX_PWM_CMR1, 0x1c);
172
+static uint64_t mphi_reg_read(void *ptr, hwaddr addr, unsigned size)
294
+REG32(NPCM7XX_PWM_PDR1, 0x20);
173
+{
295
+REG32(NPCM7XX_PWM_CNR2, 0x24);
174
+ BCM2835MphiState *s = ptr;
296
+REG32(NPCM7XX_PWM_CMR2, 0x28);
175
+ uint32_t val = 0;
297
+REG32(NPCM7XX_PWM_PDR2, 0x2c);
176
+
298
+REG32(NPCM7XX_PWM_CNR3, 0x30);
177
+ switch (addr) {
299
+REG32(NPCM7XX_PWM_CMR3, 0x34);
178
+ case 0x28: /* outdda */
300
+REG32(NPCM7XX_PWM_PDR3, 0x38);
179
+ val = s->outdda;
301
+REG32(NPCM7XX_PWM_PIER, 0x3c);
180
+ break;
302
+REG32(NPCM7XX_PWM_PIIR, 0x40);
181
+ case 0x2c: /* outddb */
303
+REG32(NPCM7XX_PWM_PWDR0, 0x44);
182
+ val = s->outddb;
304
+REG32(NPCM7XX_PWM_PWDR1, 0x48);
183
+ break;
305
+REG32(NPCM7XX_PWM_PWDR2, 0x4c);
184
+ case 0x4c: /* ctrl */
306
+REG32(NPCM7XX_PWM_PWDR3, 0x50);
185
+ val = s->ctrl;
307
+
186
+ val |= 1 << 17;
308
+/* Register field definitions. */
187
+ break;
309
+#define NPCM7XX_PPR(rv, index) extract32((rv), npcm7xx_ppr_base[index], 8)
188
+ case 0x50: /* intstat */
310
+#define NPCM7XX_CSR(rv, index) extract32((rv), npcm7xx_csr_base[index], 3)
189
+ val = s->intstat;
311
+#define NPCM7XX_CH(rv, index) extract32((rv), npcm7xx_ch_base[index], 4)
190
+ break;
312
+#define NPCM7XX_CH_EN BIT(0)
191
+ case 0x1f0: /* swirq_set */
313
+#define NPCM7XX_CH_INV BIT(2)
192
+ val = s->swirq;
314
+#define NPCM7XX_CH_MOD BIT(3)
193
+ break;
315
+
194
+ case 0x1f4: /* swirq_clr */
316
+/* Offset of each PWM channel's prescaler in the PPR register. */
195
+ val = s->swirq;
317
+static const int npcm7xx_ppr_base[] = { 0, 0, 8, 8 };
196
+ break;
318
+/* Offset of each PWM channel's clock selector in the CSR register. */
319
+static const int npcm7xx_csr_base[] = { 0, 4, 8, 12 };
320
+/* Offset of each PWM channel's control variable in the PCR register. */
321
+static const int npcm7xx_ch_base[] = { 0, 8, 12, 16 };
322
+
323
+static uint32_t npcm7xx_pwm_calculate_freq(NPCM7xxPWM *p)
324
+{
325
+ uint32_t ppr;
326
+ uint32_t csr;
327
+ uint32_t freq;
328
+
329
+ if (!p->running) {
330
+ return 0;
331
+ }
332
+
333
+ csr = NPCM7XX_CSR(p->module->csr, p->index);
334
+ ppr = NPCM7XX_PPR(p->module->ppr, p->index);
335
+ freq = clock_get_hz(p->module->clock);
336
+ freq /= ppr + 1;
337
+ /* csr can only be 0~4 */
338
+ if (csr > 4) {
339
+ qemu_log_mask(LOG_GUEST_ERROR,
340
+ "%s: invalid csr value %u\n",
341
+ __func__, csr);
342
+ csr = 4;
343
+ }
344
+ /* freq won't be changed if csr == 4. */
345
+ if (csr < 4) {
346
+ freq >>= csr + 1;
347
+ }
348
+
349
+ return freq / (p->cnr + 1);
350
+}
351
+
352
+static uint32_t npcm7xx_pwm_calculate_duty(NPCM7xxPWM *p)
353
+{
354
+ uint64_t duty;
355
+
356
+ if (p->running) {
357
+ if (p->cnr == 0) {
358
+ duty = 0;
359
+ } else if (p->cmr >= p->cnr) {
360
+ duty = NPCM7XX_PWM_MAX_DUTY;
361
+ } else {
362
+ duty = NPCM7XX_PWM_MAX_DUTY * (p->cmr + 1) / (p->cnr + 1);
363
+ }
364
+ } else {
365
+ duty = 0;
366
+ }
367
+
368
+ if (p->inverted) {
369
+ duty = NPCM7XX_PWM_MAX_DUTY - duty;
370
+ }
371
+
372
+ return duty;
373
+}
374
+
375
+static void npcm7xx_pwm_update_freq(NPCM7xxPWM *p)
376
+{
377
+ uint32_t freq = npcm7xx_pwm_calculate_freq(p);
378
+
379
+ if (freq != p->freq) {
380
+ trace_npcm7xx_pwm_update_freq(DEVICE(p->module)->canonical_path,
381
+ p->index, p->freq, freq);
382
+ p->freq = freq;
383
+ }
384
+}
385
+
386
+static void npcm7xx_pwm_update_duty(NPCM7xxPWM *p)
387
+{
388
+ uint32_t duty = npcm7xx_pwm_calculate_duty(p);
389
+
390
+ if (duty != p->duty) {
391
+ trace_npcm7xx_pwm_update_duty(DEVICE(p->module)->canonical_path,
392
+ p->index, p->duty, duty);
393
+ p->duty = duty;
394
+ }
395
+}
396
+
397
+static void npcm7xx_pwm_update_output(NPCM7xxPWM *p)
398
+{
399
+ npcm7xx_pwm_update_freq(p);
400
+ npcm7xx_pwm_update_duty(p);
401
+}
402
+
403
+static void npcm7xx_pwm_write_ppr(NPCM7xxPWMState *s, uint32_t new_ppr)
404
+{
405
+ int i;
406
+ uint32_t old_ppr = s->ppr;
407
+
408
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_ppr_base) != NPCM7XX_PWM_PER_MODULE);
409
+ s->ppr = new_ppr;
410
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
411
+ if (NPCM7XX_PPR(old_ppr, i) != NPCM7XX_PPR(new_ppr, i)) {
412
+ npcm7xx_pwm_update_freq(&s->pwm[i]);
413
+ }
414
+ }
415
+}
416
+
417
+static void npcm7xx_pwm_write_csr(NPCM7xxPWMState *s, uint32_t new_csr)
418
+{
419
+ int i;
420
+ uint32_t old_csr = s->csr;
421
+
422
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_csr_base) != NPCM7XX_PWM_PER_MODULE);
423
+ s->csr = new_csr;
424
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
425
+ if (NPCM7XX_CSR(old_csr, i) != NPCM7XX_CSR(new_csr, i)) {
426
+ npcm7xx_pwm_update_freq(&s->pwm[i]);
427
+ }
428
+ }
429
+}
430
+
431
+static void npcm7xx_pwm_write_pcr(NPCM7xxPWMState *s, uint32_t new_pcr)
432
+{
433
+ int i;
434
+ bool inverted;
435
+ uint32_t pcr;
436
+ NPCM7xxPWM *p;
437
+
438
+ s->pcr = new_pcr;
439
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_ch_base) != NPCM7XX_PWM_PER_MODULE);
440
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
441
+ p = &s->pwm[i];
442
+ pcr = NPCM7XX_CH(new_pcr, i);
443
+ inverted = pcr & NPCM7XX_CH_INV;
444
+
445
+ /*
446
+ * We only run a PWM channel with toggle mode. Single-shot mode does not
447
+ * generate frequency and duty-cycle values.
448
+ */
449
+ if ((pcr & NPCM7XX_CH_EN) && (pcr & NPCM7XX_CH_MOD)) {
450
+ if (p->running) {
451
+ /* Re-run this PWM channel if inverted changed. */
452
+ if (p->inverted ^ inverted) {
453
+ p->inverted = inverted;
454
+ npcm7xx_pwm_update_duty(p);
455
+ }
456
+ } else {
457
+ /* Run this PWM channel. */
458
+ p->running = true;
459
+ p->inverted = inverted;
460
+ npcm7xx_pwm_update_output(p);
461
+ }
462
+ } else {
463
+ /* Clear this PWM channel. */
464
+ p->running = false;
465
+ p->inverted = inverted;
466
+ npcm7xx_pwm_update_output(p);
467
+ }
468
+ }
469
+
470
+}
471
+
472
+static hwaddr npcm7xx_cnr_index(hwaddr offset)
473
+{
474
+ switch (offset) {
475
+ case A_NPCM7XX_PWM_CNR0:
476
+ return 0;
477
+ case A_NPCM7XX_PWM_CNR1:
478
+ return 1;
479
+ case A_NPCM7XX_PWM_CNR2:
480
+ return 2;
481
+ case A_NPCM7XX_PWM_CNR3:
482
+ return 3;
197
+ default:
483
+ default:
198
+ qemu_log_mask(LOG_UNIMP, "read from unknown register");
484
+ g_assert_not_reached();
199
+ break;
485
+ }
200
+ }
486
+}
201
+
487
+
202
+ return val;
488
+static hwaddr npcm7xx_cmr_index(hwaddr offset)
203
+}
489
+{
204
+
490
+ switch (offset) {
205
+static void mphi_reg_write(void *ptr, hwaddr addr, uint64_t val, unsigned size)
491
+ case A_NPCM7XX_PWM_CMR0:
206
+{
492
+ return 0;
207
+ BCM2835MphiState *s = ptr;
493
+ case A_NPCM7XX_PWM_CMR1:
208
+ int do_irq = 0;
494
+ return 1;
209
+
495
+ case A_NPCM7XX_PWM_CMR2:
210
+ switch (addr) {
496
+ return 2;
211
+ case 0x28: /* outdda */
497
+ case A_NPCM7XX_PWM_CMR3:
212
+ s->outdda = val;
498
+ return 3;
213
+ break;
214
+ case 0x2c: /* outddb */
215
+ s->outddb = val;
216
+ if (val & (1 << 29)) {
217
+ do_irq = 1;
218
+ }
219
+ break;
220
+ case 0x4c: /* ctrl */
221
+ s->ctrl = val;
222
+ if (val & (1 << 16)) {
223
+ do_irq = -1;
224
+ }
225
+ break;
226
+ case 0x50: /* intstat */
227
+ s->intstat = val;
228
+ if (val & ((1 << 16) | (1 << 29))) {
229
+ do_irq = -1;
230
+ }
231
+ break;
232
+ case 0x1f0: /* swirq_set */
233
+ s->swirq |= val;
234
+ do_irq = 1;
235
+ break;
236
+ case 0x1f4: /* swirq_clr */
237
+ s->swirq &= ~val;
238
+ do_irq = -1;
239
+ break;
240
+ default:
499
+ default:
241
+ qemu_log_mask(LOG_UNIMP, "write to unknown register");
500
+ g_assert_not_reached();
242
+ return;
501
+ }
243
+ }
502
+}
244
+
503
+
245
+ if (do_irq > 0) {
504
+static hwaddr npcm7xx_pdr_index(hwaddr offset)
246
+ mphi_raise_irq(s);
505
+{
247
+ } else if (do_irq < 0) {
506
+ switch (offset) {
248
+ mphi_lower_irq(s);
507
+ case A_NPCM7XX_PWM_PDR0:
249
+ }
508
+ return 0;
250
+}
509
+ case A_NPCM7XX_PWM_PDR1:
251
+
510
+ return 1;
252
+static const MemoryRegionOps mphi_mmio_ops = {
511
+ case A_NPCM7XX_PWM_PDR2:
253
+ .read = mphi_reg_read,
512
+ return 2;
254
+ .write = mphi_reg_write,
513
+ case A_NPCM7XX_PWM_PDR3:
255
+ .impl.min_access_size = 4,
514
+ return 3;
256
+ .impl.max_access_size = 4,
515
+ default:
516
+ g_assert_not_reached();
517
+ }
518
+}
519
+
520
+static hwaddr npcm7xx_pwdr_index(hwaddr offset)
521
+{
522
+ switch (offset) {
523
+ case A_NPCM7XX_PWM_PWDR0:
524
+ return 0;
525
+ case A_NPCM7XX_PWM_PWDR1:
526
+ return 1;
527
+ case A_NPCM7XX_PWM_PWDR2:
528
+ return 2;
529
+ case A_NPCM7XX_PWM_PWDR3:
530
+ return 3;
531
+ default:
532
+ g_assert_not_reached();
533
+ }
534
+}
535
+
536
+static uint64_t npcm7xx_pwm_read(void *opaque, hwaddr offset, unsigned size)
537
+{
538
+ NPCM7xxPWMState *s = opaque;
539
+ uint64_t value = 0;
540
+
541
+ switch (offset) {
542
+ case A_NPCM7XX_PWM_CNR0:
543
+ case A_NPCM7XX_PWM_CNR1:
544
+ case A_NPCM7XX_PWM_CNR2:
545
+ case A_NPCM7XX_PWM_CNR3:
546
+ value = s->pwm[npcm7xx_cnr_index(offset)].cnr;
547
+ break;
548
+
549
+ case A_NPCM7XX_PWM_CMR0:
550
+ case A_NPCM7XX_PWM_CMR1:
551
+ case A_NPCM7XX_PWM_CMR2:
552
+ case A_NPCM7XX_PWM_CMR3:
553
+ value = s->pwm[npcm7xx_cmr_index(offset)].cmr;
554
+ break;
555
+
556
+ case A_NPCM7XX_PWM_PDR0:
557
+ case A_NPCM7XX_PWM_PDR1:
558
+ case A_NPCM7XX_PWM_PDR2:
559
+ case A_NPCM7XX_PWM_PDR3:
560
+ value = s->pwm[npcm7xx_pdr_index(offset)].pdr;
561
+ break;
562
+
563
+ case A_NPCM7XX_PWM_PWDR0:
564
+ case A_NPCM7XX_PWM_PWDR1:
565
+ case A_NPCM7XX_PWM_PWDR2:
566
+ case A_NPCM7XX_PWM_PWDR3:
567
+ value = s->pwm[npcm7xx_pwdr_index(offset)].pwdr;
568
+ break;
569
+
570
+ case A_NPCM7XX_PWM_PPR:
571
+ value = s->ppr;
572
+ break;
573
+
574
+ case A_NPCM7XX_PWM_CSR:
575
+ value = s->csr;
576
+ break;
577
+
578
+ case A_NPCM7XX_PWM_PCR:
579
+ value = s->pcr;
580
+ break;
581
+
582
+ case A_NPCM7XX_PWM_PIER:
583
+ value = s->pier;
584
+ break;
585
+
586
+ case A_NPCM7XX_PWM_PIIR:
587
+ value = s->piir;
588
+ break;
589
+
590
+ default:
591
+ qemu_log_mask(LOG_GUEST_ERROR,
592
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
593
+ __func__, offset);
594
+ break;
595
+ }
596
+
597
+ trace_npcm7xx_pwm_read(DEVICE(s)->canonical_path, offset, value);
598
+ return value;
599
+}
600
+
601
+static void npcm7xx_pwm_write(void *opaque, hwaddr offset,
602
+ uint64_t v, unsigned size)
603
+{
604
+ NPCM7xxPWMState *s = opaque;
605
+ NPCM7xxPWM *p;
606
+ uint32_t value = v;
607
+
608
+ trace_npcm7xx_pwm_write(DEVICE(s)->canonical_path, offset, value);
609
+ switch (offset) {
610
+ case A_NPCM7XX_PWM_CNR0:
611
+ case A_NPCM7XX_PWM_CNR1:
612
+ case A_NPCM7XX_PWM_CNR2:
613
+ case A_NPCM7XX_PWM_CNR3:
614
+ p = &s->pwm[npcm7xx_cnr_index(offset)];
615
+ p->cnr = value;
616
+ npcm7xx_pwm_update_output(p);
617
+ break;
618
+
619
+ case A_NPCM7XX_PWM_CMR0:
620
+ case A_NPCM7XX_PWM_CMR1:
621
+ case A_NPCM7XX_PWM_CMR2:
622
+ case A_NPCM7XX_PWM_CMR3:
623
+ p = &s->pwm[npcm7xx_cmr_index(offset)];
624
+ p->cmr = value;
625
+ npcm7xx_pwm_update_output(p);
626
+ break;
627
+
628
+ case A_NPCM7XX_PWM_PDR0:
629
+ case A_NPCM7XX_PWM_PDR1:
630
+ case A_NPCM7XX_PWM_PDR2:
631
+ case A_NPCM7XX_PWM_PDR3:
632
+ qemu_log_mask(LOG_GUEST_ERROR,
633
+ "%s: register @ 0x%04" HWADDR_PRIx " is read-only\n",
634
+ __func__, offset);
635
+ break;
636
+
637
+ case A_NPCM7XX_PWM_PWDR0:
638
+ case A_NPCM7XX_PWM_PWDR1:
639
+ case A_NPCM7XX_PWM_PWDR2:
640
+ case A_NPCM7XX_PWM_PWDR3:
641
+ qemu_log_mask(LOG_UNIMP,
642
+ "%s: register @ 0x%04" HWADDR_PRIx " is not implemented\n",
643
+ __func__, offset);
644
+ break;
645
+
646
+ case A_NPCM7XX_PWM_PPR:
647
+ npcm7xx_pwm_write_ppr(s, value);
648
+ break;
649
+
650
+ case A_NPCM7XX_PWM_CSR:
651
+ npcm7xx_pwm_write_csr(s, value);
652
+ break;
653
+
654
+ case A_NPCM7XX_PWM_PCR:
655
+ npcm7xx_pwm_write_pcr(s, value);
656
+ break;
657
+
658
+ case A_NPCM7XX_PWM_PIER:
659
+ qemu_log_mask(LOG_UNIMP,
660
+ "%s: register @ 0x%04" HWADDR_PRIx " is not implemented\n",
661
+ __func__, offset);
662
+ break;
663
+
664
+ case A_NPCM7XX_PWM_PIIR:
665
+ qemu_log_mask(LOG_UNIMP,
666
+ "%s: register @ 0x%04" HWADDR_PRIx " is not implemented\n",
667
+ __func__, offset);
668
+ break;
669
+
670
+ default:
671
+ qemu_log_mask(LOG_GUEST_ERROR,
672
+ "%s: invalid offset 0x%04" HWADDR_PRIx "\n",
673
+ __func__, offset);
674
+ break;
675
+ }
676
+}
677
+
678
+static const struct MemoryRegionOps npcm7xx_pwm_ops = {
679
+ .read = npcm7xx_pwm_read,
680
+ .write = npcm7xx_pwm_write,
257
+ .endianness = DEVICE_LITTLE_ENDIAN,
681
+ .endianness = DEVICE_LITTLE_ENDIAN,
682
+ .valid = {
683
+ .min_access_size = 4,
684
+ .max_access_size = 4,
685
+ .unaligned = false,
686
+ },
258
+};
687
+};
259
+
688
+
260
+static void mphi_reset(DeviceState *dev)
689
+static void npcm7xx_pwm_enter_reset(Object *obj, ResetType type)
261
+{
690
+{
262
+ BCM2835MphiState *s = BCM2835_MPHI(dev);
691
+ NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
263
+
692
+ int i;
264
+ s->outdda = 0;
693
+
265
+ s->outddb = 0;
694
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; i++) {
266
+ s->ctrl = 0;
695
+ NPCM7xxPWM *p = &s->pwm[i];
267
+ s->intstat = 0;
696
+
268
+ s->swirq = 0;
697
+ p->cnr = 0x00000000;
269
+}
698
+ p->cmr = 0x00000000;
270
+
699
+ p->pdr = 0x00000000;
271
+static void mphi_realize(DeviceState *dev, Error **errp)
700
+ p->pwdr = 0x00000000;
272
+{
701
+ }
273
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
702
+
274
+ BCM2835MphiState *s = BCM2835_MPHI(dev);
703
+ s->ppr = 0x00000000;
275
+
704
+ s->csr = 0x00000000;
276
+ sysbus_init_irq(sbd, &s->irq);
705
+ s->pcr = 0x00000000;
277
+}
706
+ s->pier = 0x00000000;
278
+
707
+ s->piir = 0x00000000;
279
+static void mphi_init(Object *obj)
708
+}
280
+{
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);
281
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
723
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
282
+ BCM2835MphiState *s = BCM2835_MPHI(obj);
724
+ int i;
283
+
725
+
284
+ memory_region_init_io(&s->iomem, obj, &mphi_mmio_ops, s, "mphi", MPHI_MMIO_SIZE);
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);
285
+ sysbus_init_mmio(sbd, &s->iomem);
735
+ sysbus_init_mmio(sbd, &s->iomem);
286
+}
736
+ s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL);
287
+
737
+
288
+const VMStateDescription vmstate_mphi_state = {
738
+ for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
289
+ .name = "mphi",
739
+ object_property_add_uint32_ptr(obj, "freq[*]",
290
+ .version_id = 1,
740
+ &s->pwm[i].freq, OBJ_PROP_FLAG_READ);
291
+ .minimum_version_id = 1,
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,
292
+ .fields = (VMStateField[]) {
750
+ .fields = (VMStateField[]) {
293
+ VMSTATE_UINT32(outdda, BCM2835MphiState),
751
+ VMSTATE_BOOL(running, NPCM7xxPWM),
294
+ VMSTATE_UINT32(outddb, BCM2835MphiState),
752
+ VMSTATE_BOOL(inverted, NPCM7xxPWM),
295
+ VMSTATE_UINT32(ctrl, BCM2835MphiState),
753
+ VMSTATE_UINT8(index, NPCM7xxPWM),
296
+ VMSTATE_UINT32(intstat, BCM2835MphiState),
754
+ VMSTATE_UINT32(cnr, NPCM7xxPWM),
297
+ VMSTATE_UINT32(swirq, BCM2835MphiState),
755
+ VMSTATE_UINT32(cmr, NPCM7xxPWM),
298
+ VMSTATE_END_OF_LIST()
756
+ VMSTATE_UINT32(pdr, NPCM7xxPWM),
299
+ }
757
+ VMSTATE_UINT32(pwdr, NPCM7xxPWM),
758
+ VMSTATE_UINT32(freq, NPCM7xxPWM),
759
+ VMSTATE_UINT32(duty, NPCM7xxPWM),
760
+ VMSTATE_END_OF_LIST(),
761
+ },
300
+};
762
+};
301
+
763
+
302
+static void mphi_class_init(ObjectClass *klass, void *data)
764
+static const VMStateDescription vmstate_npcm7xx_pwm_module = {
303
+{
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);
304
+ DeviceClass *dc = DEVICE_CLASS(klass);
785
+ DeviceClass *dc = DEVICE_CLASS(klass);
305
+
786
+
306
+ dc->realize = mphi_realize;
787
+ dc->desc = "NPCM7xx PWM Controller";
307
+ dc->reset = mphi_reset;
788
+ dc->vmsd = &vmstate_npcm7xx_pwm_module;
308
+ dc->vmsd = &vmstate_mphi_state;
789
+ rc->phases.enter = npcm7xx_pwm_enter_reset;
309
+}
790
+ rc->phases.hold = npcm7xx_pwm_hold_reset;
310
+
791
+}
311
+static const TypeInfo bcm2835_mphi_type_info = {
792
+
312
+ .name = TYPE_BCM2835_MPHI,
793
+static const TypeInfo npcm7xx_pwm_info = {
313
+ .parent = TYPE_SYS_BUS_DEVICE,
794
+ .name = TYPE_NPCM7XX_PWM,
314
+ .instance_size = sizeof(BCM2835MphiState),
795
+ .parent = TYPE_SYS_BUS_DEVICE,
315
+ .instance_init = mphi_init,
796
+ .instance_size = sizeof(NPCM7xxPWMState),
316
+ .class_init = mphi_class_init,
797
+ .class_init = npcm7xx_pwm_class_init,
798
+ .instance_init = npcm7xx_pwm_init,
317
+};
799
+};
318
+
800
+
319
+static void bcm2835_mphi_register_types(void)
801
+static void npcm7xx_pwm_register_type(void)
320
+{
802
+{
321
+ type_register_static(&bcm2835_mphi_type_info);
803
+ type_register_static(&npcm7xx_pwm_info);
322
+}
804
+}
323
+
805
+type_init(npcm7xx_pwm_register_type);
324
+type_init(bcm2835_mphi_register_types)
806
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
325
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
326
index XXXXXXX..XXXXXXX 100644
807
index XXXXXXX..XXXXXXX 100644
327
--- a/hw/misc/Makefile.objs
808
--- a/hw/misc/meson.build
328
+++ b/hw/misc/Makefile.objs
809
+++ b/hw/misc/meson.build
329
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_OMAP) += omap_l4.o
810
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_MAINSTONE', if_true: files('mst_fpga.c'))
330
common-obj-$(CONFIG_OMAP) += omap_sdrc.o
811
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
331
common-obj-$(CONFIG_OMAP) += omap_tap.o
812
'npcm7xx_clk.c',
332
common-obj-$(CONFIG_RASPI) += bcm2835_mbox.o
813
'npcm7xx_gcr.c',
333
+common-obj-$(CONFIG_RASPI) += bcm2835_mphi.o
814
+ 'npcm7xx_pwm.c',
334
common-obj-$(CONFIG_RASPI) += bcm2835_property.o
815
'npcm7xx_rng.c',
335
common-obj-$(CONFIG_RASPI) += bcm2835_rng.o
816
))
336
common-obj-$(CONFIG_RASPI) += bcm2835_thermal.o
817
softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files(
818
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
819
index XXXXXXX..XXXXXXX 100644
820
--- a/hw/misc/trace-events
821
+++ b/hw/misc/trace-events
822
@@ -XXX,XX +XXX,XX @@ npcm7xx_gcr_write(uint64_t offset, uint32_t value) "offset: 0x%04" PRIx64 " valu
823
npcm7xx_rng_read(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
824
npcm7xx_rng_write(uint64_t offset, uint64_t value, unsigned size) "offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
825
826
+# npcm7xx_pwm.c
827
+npcm7xx_pwm_read(const char *id, uint64_t offset, uint32_t value) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
828
+npcm7xx_pwm_write(const char *id, uint64_t offset, uint32_t value) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
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"
337
--
835
--
338
2.20.1
836
2.20.1
339
837
340
838
diff view generated by jsdifflib
1
From: Paul Zimmerman <pauldzim@gmail.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
Add the dwc-hsotg (dwc2) USB host controller emulation code.
3
We add a qtest for the PWM in the previous patch. It proves it works as
4
Based on hw/usb/hcd-ehci.c and hw/usb/hcd-ohci.c.
4
expected.
5
5
6
Note that to use this with the dwc-otg driver in the Raspbian
6
Reviewed-by: Havard Skinnemoen <hskinnemoen@google.com>
7
kernel, you must pass the option "dwc_otg.fiq_fsm_enable=0" on
7
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
8
the kernel command line.
8
Signed-off-by: Hao Wu <wuhaotsh@google.com>
9
10
Emulation of slave mode and of descriptor-DMA mode has not been
11
implemented yet. These modes are seldom used.
12
13
I have used some on-line sources of information while developing
14
this emulation, including:
15
16
http://www.capital-micro.com/PDF/CME-M7_Family_User_Guide_EN.pdf
17
which has a pretty complete description of the controller starting
18
on page 370.
19
20
https://sourceforge.net/p/wive-ng/wive-ng-mt/ci/master/tree/docs/DataSheets/RT3050_5x_V2.0_081408_0902.pdf
21
which has a description of the controller registers starting on
22
page 130.
23
24
Thanks to Felippe Mathieu-Daude for providing a cleaner method
25
of implementing the memory regions for the controller registers.
26
27
Signed-off-by: Paul Zimmerman <pauldzim@gmail.com>
28
Message-id: 20200520235349.21215-5-pauldzim@gmail.com
29
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
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
31
---
12
---
32
hw/usb/hcd-dwc2.c | 1417 ++++++++++++++++++++++++++++++++++++++++++
13
tests/qtest/npcm7xx_pwm-test.c | 490 +++++++++++++++++++++++++++++++++
33
hw/usb/Kconfig | 5 +
14
tests/qtest/meson.build | 1 +
34
hw/usb/Makefile.objs | 1 +
15
2 files changed, 491 insertions(+)
35
hw/usb/trace-events | 50 ++
16
create mode 100644 tests/qtest/npcm7xx_pwm-test.c
36
4 files changed, 1473 insertions(+)
37
create mode 100644 hw/usb/hcd-dwc2.c
38
17
39
diff --git a/hw/usb/hcd-dwc2.c b/hw/usb/hcd-dwc2.c
18
diff --git a/tests/qtest/npcm7xx_pwm-test.c b/tests/qtest/npcm7xx_pwm-test.c
40
new file mode 100644
19
new file mode 100644
41
index XXXXXXX..XXXXXXX
20
index XXXXXXX..XXXXXXX
42
--- /dev/null
21
--- /dev/null
43
+++ b/hw/usb/hcd-dwc2.c
22
+++ b/tests/qtest/npcm7xx_pwm-test.c
44
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@
45
+/*
24
+/*
46
+ * dwc-hsotg (dwc2) USB host controller emulation
25
+ * QTests for Nuvoton NPCM7xx PWM Modules.
47
+ *
26
+ *
48
+ * Based on hw/usb/hcd-ehci.c and hw/usb/hcd-ohci.c
27
+ * Copyright 2020 Google LLC
49
+ *
28
+ *
50
+ * Note that to use this emulation with the dwc-otg driver in the
29
+ * This program is free software; you can redistribute it and/or modify it
51
+ * Raspbian kernel, you must pass the option "dwc_otg.fiq_fsm_enable=0"
30
+ * under the terms of the GNU General Public License as published by the
52
+ * on the kernel command line.
31
+ * Free Software Foundation; either version 2 of the License, or
53
+ *
54
+ * Some useful documentation used to develop this emulation can be
55
+ * found online (as of April 2020) at:
56
+ *
57
+ * http://www.capital-micro.com/PDF/CME-M7_Family_User_Guide_EN.pdf
58
+ * which has a pretty complete description of the controller starting
59
+ * on page 370.
60
+ *
61
+ * https://sourceforge.net/p/wive-ng/wive-ng-mt/ci/master/tree/docs/DataSheets/RT3050_5x_V2.0_081408_0902.pdf
62
+ * which has a description of the controller registers starting on
63
+ * page 130.
64
+ *
65
+ * Copyright (c) 2020 Paul Zimmerman <pauldzim@gmail.com>
66
+ *
67
+ * This program is free software; you can redistribute it and/or modify
68
+ * it under the terms of the GNU General Public License as published by
69
+ * the Free Software Foundation; either version 2 of the License, or
70
+ * (at your option) any later version.
32
+ * (at your option) any later version.
71
+ *
33
+ *
72
+ * This program is distributed in the hope that it will be useful,
34
+ * This program is distributed in the hope that it will be useful, but WITHOUT
73
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
35
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
74
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
75
+ * GNU General Public License for more details.
37
+ * for more details.
76
+ */
38
+ */
77
+
39
+
78
+#include "qemu/osdep.h"
40
+#include "qemu/osdep.h"
79
+#include "qemu/units.h"
41
+#include "qemu/bitops.h"
80
+#include "qapi/error.h"
42
+#include "libqos/libqtest.h"
81
+#include "hw/usb/dwc2-regs.h"
43
+#include "qapi/qmp/qdict.h"
82
+#include "hw/usb/hcd-dwc2.h"
44
+#include "qapi/qmp/qnum.h"
83
+#include "migration/vmstate.h"
45
+
84
+#include "trace.h"
46
+#define REF_HZ 25000000
85
+#include "qemu/log.h"
47
+
86
+#include "qemu/error-report.h"
48
+/* Register field definitions. */
87
+#include "qemu/main-loop.h"
49
+#define CH_EN BIT(0)
88
+#include "hw/qdev-properties.h"
50
+#define CH_INV BIT(2)
89
+
51
+#define CH_MOD BIT(3)
90
+#define USB_HZ_FS 12000000
52
+
91
+#define USB_HZ_HS 96000000
53
+/* Registers shared between all PWMs in a module */
92
+#define USB_FRMINTVL 12000
54
+#define PPR 0x00
93
+
55
+#define CSR 0x04
94
+/* nifty macros from Arnon's EHCI version */
56
+#define PCR 0x08
95
+#define get_field(data, field) \
57
+#define PIER 0x3c
96
+ (((data) & field##_MASK) >> field##_SHIFT)
58
+#define PIIR 0x40
97
+
59
+
98
+#define set_field(data, newval, field) do { \
60
+/* CLK module related */
99
+ uint32_t val = *(data); \
61
+#define CLK_BA 0xf0801000
100
+ val &= ~field##_MASK; \
62
+#define CLKSEL 0x04
101
+ val |= ((newval) << field##_SHIFT) & field##_MASK; \
63
+#define CLKDIV1 0x08
102
+ *(data) = val; \
64
+#define CLKDIV2 0x2c
103
+} while (0)
65
+#define PLLCON0 0x0c
104
+
66
+#define PLLCON1 0x10
105
+#define get_bit(data, bitmask) \
67
+#define PLL_INDV(rv) extract32((rv), 0, 6)
106
+ (!!((data) & (bitmask)))
68
+#define PLL_FBDV(rv) extract32((rv), 16, 12)
107
+
69
+#define PLL_OTDV1(rv) extract32((rv), 8, 3)
108
+/* update irq line */
70
+#define PLL_OTDV2(rv) extract32((rv), 13, 3)
109
+static inline void dwc2_update_irq(DWC2State *s)
71
+#define APB3CKDIV(rv) extract32((rv), 28, 2)
110
+{
72
+#define CLK2CKDIV(rv) extract32((rv), 0, 1)
111
+ static int oldlevel;
73
+#define CLK4CKDIV(rv) extract32((rv), 26, 2)
112
+ int level = 0;
74
+#define CPUCKSEL(rv) extract32((rv), 0, 2)
113
+
75
+
114
+ if ((s->gintsts & s->gintmsk) && (s->gahbcfg & GAHBCFG_GLBL_INTR_EN)) {
76
+#define MAX_DUTY 1000000
115
+ level = 1;
77
+
116
+ }
78
+typedef struct PWMModule {
117
+ if (level != oldlevel) {
79
+ int irq;
118
+ oldlevel = level;
80
+ uint64_t base_addr;
119
+ trace_usb_dwc2_update_irq(level);
81
+} PWMModule;
120
+ qemu_set_irq(s->irq, level);
82
+
121
+ }
83
+typedef struct PWM {
122
+}
84
+ uint32_t cnr_offset;
123
+
85
+ uint32_t cmr_offset;
124
+/* flag interrupt condition */
86
+ uint32_t pdr_offset;
125
+static inline void dwc2_raise_global_irq(DWC2State *s, uint32_t intr)
87
+ uint32_t pwdr_offset;
126
+{
88
+} PWM;
127
+ if (!(s->gintsts & intr)) {
89
+
128
+ s->gintsts |= intr;
90
+typedef struct TestData {
129
+ trace_usb_dwc2_raise_global_irq(intr);
91
+ const PWMModule *module;
130
+ dwc2_update_irq(s);
92
+ const PWM *pwm;
131
+ }
93
+} TestData;
132
+}
94
+
133
+
95
+static const PWMModule pwm_module_list[] = {
134
+static inline void dwc2_lower_global_irq(DWC2State *s, uint32_t intr)
96
+ {
135
+{
97
+ .irq = 93,
136
+ if (s->gintsts & intr) {
98
+ .base_addr = 0xf0103000
137
+ s->gintsts &= ~intr;
99
+ },
138
+ trace_usb_dwc2_lower_global_irq(intr);
100
+ {
139
+ dwc2_update_irq(s);
101
+ .irq = 94,
140
+ }
102
+ .base_addr = 0xf0104000
141
+}
103
+ }
142
+
143
+static inline void dwc2_raise_host_irq(DWC2State *s, uint32_t host_intr)
144
+{
145
+ if (!(s->haint & host_intr)) {
146
+ s->haint |= host_intr;
147
+ s->haint &= 0xffff;
148
+ trace_usb_dwc2_raise_host_irq(host_intr);
149
+ if (s->haint & s->haintmsk) {
150
+ dwc2_raise_global_irq(s, GINTSTS_HCHINT);
151
+ }
152
+ }
153
+}
154
+
155
+static inline void dwc2_lower_host_irq(DWC2State *s, uint32_t host_intr)
156
+{
157
+ if (s->haint & host_intr) {
158
+ s->haint &= ~host_intr;
159
+ trace_usb_dwc2_lower_host_irq(host_intr);
160
+ if (!(s->haint & s->haintmsk)) {
161
+ dwc2_lower_global_irq(s, GINTSTS_HCHINT);
162
+ }
163
+ }
164
+}
165
+
166
+static inline void dwc2_update_hc_irq(DWC2State *s, int index)
167
+{
168
+ uint32_t host_intr = 1 << (index >> 3);
169
+
170
+ if (s->hreg1[index + 2] & s->hreg1[index + 3]) {
171
+ dwc2_raise_host_irq(s, host_intr);
172
+ } else {
173
+ dwc2_lower_host_irq(s, host_intr);
174
+ }
175
+}
176
+
177
+/* set a timer for EOF */
178
+static void dwc2_eof_timer(DWC2State *s)
179
+{
180
+ timer_mod(s->eof_timer, s->sof_time + s->usb_frame_time);
181
+}
182
+
183
+/* Set a timer for EOF and generate SOF event */
184
+static void dwc2_sof(DWC2State *s)
185
+{
186
+ s->sof_time += s->usb_frame_time;
187
+ trace_usb_dwc2_sof(s->sof_time);
188
+ dwc2_eof_timer(s);
189
+ dwc2_raise_global_irq(s, GINTSTS_SOF);
190
+}
191
+
192
+/* Do frame processing on frame boundary */
193
+static void dwc2_frame_boundary(void *opaque)
194
+{
195
+ DWC2State *s = opaque;
196
+ int64_t now;
197
+ uint16_t frcnt;
198
+
199
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
200
+
201
+ /* Frame boundary, so do EOF stuff here */
202
+
203
+ /* Increment frame number */
204
+ frcnt = (uint16_t)((now - s->sof_time) / s->fi);
205
+ s->frame_number = (s->frame_number + frcnt) & 0xffff;
206
+ s->hfnum = s->frame_number & HFNUM_MAX_FRNUM;
207
+
208
+ /* Do SOF stuff here */
209
+ dwc2_sof(s);
210
+}
211
+
212
+/* Start sending SOF tokens on the USB bus */
213
+static void dwc2_bus_start(DWC2State *s)
214
+{
215
+ trace_usb_dwc2_bus_start();
216
+ s->sof_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
217
+ dwc2_eof_timer(s);
218
+}
219
+
220
+/* Stop sending SOF tokens on the USB bus */
221
+static void dwc2_bus_stop(DWC2State *s)
222
+{
223
+ trace_usb_dwc2_bus_stop();
224
+ timer_del(s->eof_timer);
225
+}
226
+
227
+static USBDevice *dwc2_find_device(DWC2State *s, uint8_t addr)
228
+{
229
+ USBDevice *dev;
230
+
231
+ trace_usb_dwc2_find_device(addr);
232
+
233
+ if (!(s->hprt0 & HPRT0_ENA)) {
234
+ trace_usb_dwc2_port_disabled(0);
235
+ } else {
236
+ dev = usb_find_device(&s->uport, addr);
237
+ if (dev != NULL) {
238
+ trace_usb_dwc2_device_found(0);
239
+ return dev;
240
+ }
241
+ }
242
+
243
+ trace_usb_dwc2_device_not_found();
244
+ return NULL;
245
+}
246
+
247
+static const char *pstatus[] = {
248
+ "USB_RET_SUCCESS", "USB_RET_NODEV", "USB_RET_NAK", "USB_RET_STALL",
249
+ "USB_RET_BABBLE", "USB_RET_IOERROR", "USB_RET_ASYNC",
250
+ "USB_RET_ADD_TO_QUEUE", "USB_RET_REMOVE_FROM_QUEUE"
251
+};
104
+};
252
+
105
+
253
+static uint32_t pintr[] = {
106
+static const PWM pwm_list[] = {
254
+ HCINTMSK_XFERCOMPL, HCINTMSK_XACTERR, HCINTMSK_NAK, HCINTMSK_STALL,
107
+ {
255
+ HCINTMSK_BBLERR, HCINTMSK_XACTERR, HCINTMSK_XACTERR, HCINTMSK_XACTERR,
108
+ .cnr_offset = 0x0c,
256
+ HCINTMSK_XACTERR
109
+ .cmr_offset = 0x10,
110
+ .pdr_offset = 0x14,
111
+ .pwdr_offset = 0x44,
112
+ },
113
+ {
114
+ .cnr_offset = 0x18,
115
+ .cmr_offset = 0x1c,
116
+ .pdr_offset = 0x20,
117
+ .pwdr_offset = 0x48,
118
+ },
119
+ {
120
+ .cnr_offset = 0x24,
121
+ .cmr_offset = 0x28,
122
+ .pdr_offset = 0x2c,
123
+ .pwdr_offset = 0x4c,
124
+ },
125
+ {
126
+ .cnr_offset = 0x30,
127
+ .cmr_offset = 0x34,
128
+ .pdr_offset = 0x38,
129
+ .pwdr_offset = 0x50,
130
+ },
257
+};
131
+};
258
+
132
+
259
+static const char *types[] = {
133
+static const int ppr_base[] = { 0, 0, 8, 8 };
260
+ "Ctrl", "Isoc", "Bulk", "Intr"
134
+static const int csr_base[] = { 0, 4, 8, 12 };
135
+static const int pcr_base[] = { 0, 8, 12, 16 };
136
+
137
+static const uint32_t ppr_list[] = {
138
+ 0,
139
+ 1,
140
+ 10,
141
+ 100,
142
+ 255, /* Max possible value. */
261
+};
143
+};
262
+
144
+
263
+static const char *dirs[] = {
145
+static const uint32_t csr_list[] = {
264
+ "Out", "In"
146
+ 0,
147
+ 1,
148
+ 2,
149
+ 3,
150
+ 4, /* Max possible value. */
265
+};
151
+};
266
+
152
+
267
+static void dwc2_handle_packet(DWC2State *s, uint32_t devadr, USBDevice *dev,
153
+static const uint32_t cnr_list[] = {
268
+ USBEndpoint *ep, uint32_t index, bool send)
154
+ 0,
269
+{
155
+ 1,
270
+ DWC2Packet *p;
156
+ 50,
271
+ uint32_t hcchar = s->hreg1[index];
157
+ 100,
272
+ uint32_t hctsiz = s->hreg1[index + 4];
158
+ 150,
273
+ uint32_t hcdma = s->hreg1[index + 5];
159
+ 200,
274
+ uint32_t chan, epnum, epdir, eptype, mps, pid, pcnt, len, tlen, intr = 0;
160
+ 1000,
275
+ uint32_t tpcnt, stsidx, actual = 0;
161
+ 10000,
276
+ bool do_intr = false, done = false;
162
+ 65535, /* Max possible value. */
277
+
278
+ epnum = get_field(hcchar, HCCHAR_EPNUM);
279
+ epdir = get_bit(hcchar, HCCHAR_EPDIR);
280
+ eptype = get_field(hcchar, HCCHAR_EPTYPE);
281
+ mps = get_field(hcchar, HCCHAR_MPS);
282
+ pid = get_field(hctsiz, TSIZ_SC_MC_PID);
283
+ pcnt = get_field(hctsiz, TSIZ_PKTCNT);
284
+ len = get_field(hctsiz, TSIZ_XFERSIZE);
285
+ assert(len <= DWC2_MAX_XFER_SIZE);
286
+ chan = index >> 3;
287
+ p = &s->packet[chan];
288
+
289
+ trace_usb_dwc2_handle_packet(chan, dev, &p->packet, epnum, types[eptype],
290
+ dirs[epdir], mps, len, pcnt);
291
+
292
+ if (eptype == USB_ENDPOINT_XFER_CONTROL && pid == TSIZ_SC_MC_PID_SETUP) {
293
+ pid = USB_TOKEN_SETUP;
294
+ } else {
295
+ pid = epdir ? USB_TOKEN_IN : USB_TOKEN_OUT;
296
+ }
297
+
298
+ if (send) {
299
+ tlen = len;
300
+ if (p->small) {
301
+ if (tlen > mps) {
302
+ tlen = mps;
303
+ }
304
+ }
305
+
306
+ if (pid != USB_TOKEN_IN) {
307
+ trace_usb_dwc2_memory_read(hcdma, tlen);
308
+ if (dma_memory_read(&s->dma_as, hcdma,
309
+ s->usb_buf[chan], tlen) != MEMTX_OK) {
310
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: dma_memory_read failed\n",
311
+ __func__);
312
+ }
313
+ }
314
+
315
+ usb_packet_init(&p->packet);
316
+ usb_packet_setup(&p->packet, pid, ep, 0, hcdma,
317
+ pid != USB_TOKEN_IN, true);
318
+ usb_packet_addbuf(&p->packet, s->usb_buf[chan], tlen);
319
+ p->async = DWC2_ASYNC_NONE;
320
+ usb_handle_packet(dev, &p->packet);
321
+ } else {
322
+ tlen = p->len;
323
+ }
324
+
325
+ stsidx = -p->packet.status;
326
+ assert(stsidx < sizeof(pstatus) / sizeof(*pstatus));
327
+ actual = p->packet.actual_length;
328
+ trace_usb_dwc2_packet_status(pstatus[stsidx], actual);
329
+
330
+babble:
331
+ if (p->packet.status != USB_RET_SUCCESS &&
332
+ p->packet.status != USB_RET_NAK &&
333
+ p->packet.status != USB_RET_STALL &&
334
+ p->packet.status != USB_RET_ASYNC) {
335
+ trace_usb_dwc2_packet_error(pstatus[stsidx]);
336
+ }
337
+
338
+ if (p->packet.status == USB_RET_ASYNC) {
339
+ trace_usb_dwc2_async_packet(&p->packet, chan, dev, epnum,
340
+ dirs[epdir], tlen);
341
+ usb_device_flush_ep_queue(dev, ep);
342
+ assert(p->async != DWC2_ASYNC_INFLIGHT);
343
+ p->devadr = devadr;
344
+ p->epnum = epnum;
345
+ p->epdir = epdir;
346
+ p->mps = mps;
347
+ p->pid = pid;
348
+ p->index = index;
349
+ p->pcnt = pcnt;
350
+ p->len = tlen;
351
+ p->async = DWC2_ASYNC_INFLIGHT;
352
+ p->needs_service = false;
353
+ return;
354
+ }
355
+
356
+ if (p->packet.status == USB_RET_SUCCESS) {
357
+ if (actual > tlen) {
358
+ p->packet.status = USB_RET_BABBLE;
359
+ goto babble;
360
+ }
361
+
362
+ if (pid == USB_TOKEN_IN) {
363
+ trace_usb_dwc2_memory_write(hcdma, actual);
364
+ if (dma_memory_write(&s->dma_as, hcdma, s->usb_buf[chan],
365
+ actual) != MEMTX_OK) {
366
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: dma_memory_write failed\n",
367
+ __func__);
368
+ }
369
+ }
370
+
371
+ tpcnt = actual / mps;
372
+ if (actual % mps) {
373
+ tpcnt++;
374
+ if (pid == USB_TOKEN_IN) {
375
+ done = true;
376
+ }
377
+ }
378
+
379
+ pcnt -= tpcnt < pcnt ? tpcnt : pcnt;
380
+ set_field(&hctsiz, pcnt, TSIZ_PKTCNT);
381
+ len -= actual < len ? actual : len;
382
+ set_field(&hctsiz, len, TSIZ_XFERSIZE);
383
+ s->hreg1[index + 4] = hctsiz;
384
+ hcdma += actual;
385
+ s->hreg1[index + 5] = hcdma;
386
+
387
+ if (!pcnt || len == 0 || actual == 0) {
388
+ done = true;
389
+ }
390
+ } else {
391
+ intr |= pintr[stsidx];
392
+ if (p->packet.status == USB_RET_NAK &&
393
+ (eptype == USB_ENDPOINT_XFER_CONTROL ||
394
+ eptype == USB_ENDPOINT_XFER_BULK)) {
395
+ /*
396
+ * for ctrl/bulk, automatically retry on NAK,
397
+ * but send the interrupt anyway
398
+ */
399
+ intr &= ~HCINTMSK_RESERVED14_31;
400
+ s->hreg1[index + 2] |= intr;
401
+ do_intr = true;
402
+ } else {
403
+ intr |= HCINTMSK_CHHLTD;
404
+ done = true;
405
+ }
406
+ }
407
+
408
+ usb_packet_cleanup(&p->packet);
409
+
410
+ if (done) {
411
+ hcchar &= ~HCCHAR_CHENA;
412
+ s->hreg1[index] = hcchar;
413
+ if (!(intr & HCINTMSK_CHHLTD)) {
414
+ intr |= HCINTMSK_CHHLTD | HCINTMSK_XFERCOMPL;
415
+ }
416
+ intr &= ~HCINTMSK_RESERVED14_31;
417
+ s->hreg1[index + 2] |= intr;
418
+ p->needs_service = false;
419
+ trace_usb_dwc2_packet_done(pstatus[stsidx], actual, len, pcnt);
420
+ dwc2_update_hc_irq(s, index);
421
+ return;
422
+ }
423
+
424
+ p->devadr = devadr;
425
+ p->epnum = epnum;
426
+ p->epdir = epdir;
427
+ p->mps = mps;
428
+ p->pid = pid;
429
+ p->index = index;
430
+ p->pcnt = pcnt;
431
+ p->len = len;
432
+ p->needs_service = true;
433
+ trace_usb_dwc2_packet_next(pstatus[stsidx], len, pcnt);
434
+ if (do_intr) {
435
+ dwc2_update_hc_irq(s, index);
436
+ }
437
+}
438
+
439
+/* Attach or detach a device on root hub */
440
+
441
+static const char *speeds[] = {
442
+ "low", "full", "high"
443
+};
163
+};
444
+
164
+
445
+static void dwc2_attach(USBPort *port)
165
+static const uint32_t cmr_list[] = {
446
+{
166
+ 0,
447
+ DWC2State *s = port->opaque;
167
+ 1,
448
+ int hispd = 0;
168
+ 10,
449
+
169
+ 50,
450
+ trace_usb_dwc2_attach(port);
170
+ 100,
451
+ assert(port->index == 0);
171
+ 150,
452
+
172
+ 200,
453
+ if (!port->dev || !port->dev->attached) {
173
+ 1000,
454
+ return;
174
+ 10000,
455
+ }
175
+ 65535, /* Max possible value. */
456
+
176
+};
457
+ assert(port->dev->speed <= USB_SPEED_HIGH);
177
+
458
+ trace_usb_dwc2_attach_speed(speeds[port->dev->speed]);
178
+/* Returns the index of the PWM module. */
459
+ s->hprt0 &= ~HPRT0_SPD_MASK;
179
+static int pwm_module_index(const PWMModule *module)
460
+
180
+{
461
+ switch (port->dev->speed) {
181
+ ptrdiff_t diff = module - pwm_module_list;
462
+ case USB_SPEED_LOW:
182
+
463
+ s->hprt0 |= HPRT0_SPD_LOW_SPEED << HPRT0_SPD_SHIFT;
183
+ g_assert_true(diff >= 0 && diff < ARRAY_SIZE(pwm_module_list));
184
+
185
+ return diff;
186
+}
187
+
188
+/* Returns the index of the PWM entry. */
189
+static int pwm_index(const PWM *pwm)
190
+{
191
+ ptrdiff_t diff = pwm - pwm_list;
192
+
193
+ g_assert_true(diff >= 0 && diff < ARRAY_SIZE(pwm_list));
194
+
195
+ return diff;
196
+}
197
+
198
+static uint64_t pwm_qom_get(QTestState *qts, const char *path, const char *name)
199
+{
200
+ QDict *response;
201
+
202
+ g_test_message("Getting properties %s from %s", name, path);
203
+ response = qtest_qmp(qts, "{ 'execute': 'qom-get',"
204
+ " 'arguments': { 'path': %s, 'property': %s}}",
205
+ path, name);
206
+ /* The qom set message returns successfully. */
207
+ g_assert_true(qdict_haskey(response, "return"));
208
+ return qnum_get_uint(qobject_to(QNum, qdict_get(response, "return")));
209
+}
210
+
211
+static uint64_t pwm_get_freq(QTestState *qts, int module_index, int pwm_index)
212
+{
213
+ char path[100];
214
+ char name[100];
215
+
216
+ sprintf(path, "/machine/soc/pwm[%d]", module_index);
217
+ sprintf(name, "freq[%d]", pwm_index);
218
+
219
+ return pwm_qom_get(qts, path, name);
220
+}
221
+
222
+static uint64_t pwm_get_duty(QTestState *qts, int module_index, int pwm_index)
223
+{
224
+ char path[100];
225
+ char name[100];
226
+
227
+ sprintf(path, "/machine/soc/pwm[%d]", module_index);
228
+ sprintf(name, "duty[%d]", pwm_index);
229
+
230
+ return pwm_qom_get(qts, path, name);
231
+}
232
+
233
+static uint32_t get_pll(uint32_t con)
234
+{
235
+ return REF_HZ * PLL_FBDV(con) / (PLL_INDV(con) * PLL_OTDV1(con)
236
+ * PLL_OTDV2(con));
237
+}
238
+
239
+static uint64_t read_pclk(QTestState *qts)
240
+{
241
+ uint64_t freq = REF_HZ;
242
+ uint32_t clksel = qtest_readl(qts, CLK_BA + CLKSEL);
243
+ uint32_t pllcon;
244
+ uint32_t clkdiv1 = qtest_readl(qts, CLK_BA + CLKDIV1);
245
+ uint32_t clkdiv2 = qtest_readl(qts, CLK_BA + CLKDIV2);
246
+
247
+ switch (CPUCKSEL(clksel)) {
248
+ case 0:
249
+ pllcon = qtest_readl(qts, CLK_BA + PLLCON0);
250
+ freq = get_pll(pllcon);
464
+ break;
251
+ break;
465
+ case USB_SPEED_FULL:
252
+ case 1:
466
+ s->hprt0 |= HPRT0_SPD_FULL_SPEED << HPRT0_SPD_SHIFT;
253
+ pllcon = qtest_readl(qts, CLK_BA + PLLCON1);
254
+ freq = get_pll(pllcon);
467
+ break;
255
+ break;
468
+ case USB_SPEED_HIGH:
256
+ case 2:
469
+ s->hprt0 |= HPRT0_SPD_HIGH_SPEED << HPRT0_SPD_SHIFT;
470
+ hispd = 1;
471
+ break;
257
+ break;
472
+ }
258
+ case 3:
473
+
474
+ if (hispd) {
475
+ s->usb_frame_time = NANOSECONDS_PER_SECOND / 8000; /* 125000 */
476
+ if (NANOSECONDS_PER_SECOND >= USB_HZ_HS) {
477
+ s->usb_bit_time = NANOSECONDS_PER_SECOND / USB_HZ_HS; /* 10.4 */
478
+ } else {
479
+ s->usb_bit_time = 1;
480
+ }
481
+ } else {
482
+ s->usb_frame_time = NANOSECONDS_PER_SECOND / 1000; /* 1000000 */
483
+ if (NANOSECONDS_PER_SECOND >= USB_HZ_FS) {
484
+ s->usb_bit_time = NANOSECONDS_PER_SECOND / USB_HZ_FS; /* 83.3 */
485
+ } else {
486
+ s->usb_bit_time = 1;
487
+ }
488
+ }
489
+
490
+ s->fi = USB_FRMINTVL - 1;
491
+ s->hprt0 |= HPRT0_CONNDET | HPRT0_CONNSTS;
492
+
493
+ dwc2_bus_start(s);
494
+ dwc2_raise_global_irq(s, GINTSTS_PRTINT);
495
+}
496
+
497
+static void dwc2_detach(USBPort *port)
498
+{
499
+ DWC2State *s = port->opaque;
500
+
501
+ trace_usb_dwc2_detach(port);
502
+ assert(port->index == 0);
503
+
504
+ dwc2_bus_stop(s);
505
+
506
+ s->hprt0 &= ~(HPRT0_SPD_MASK | HPRT0_SUSP | HPRT0_ENA | HPRT0_CONNSTS);
507
+ s->hprt0 |= HPRT0_CONNDET | HPRT0_ENACHG;
508
+
509
+ dwc2_raise_global_irq(s, GINTSTS_PRTINT);
510
+}
511
+
512
+static void dwc2_child_detach(USBPort *port, USBDevice *child)
513
+{
514
+ trace_usb_dwc2_child_detach(port, child);
515
+ assert(port->index == 0);
516
+}
517
+
518
+static void dwc2_wakeup(USBPort *port)
519
+{
520
+ DWC2State *s = port->opaque;
521
+
522
+ trace_usb_dwc2_wakeup(port);
523
+ assert(port->index == 0);
524
+
525
+ if (s->hprt0 & HPRT0_SUSP) {
526
+ s->hprt0 |= HPRT0_RES;
527
+ dwc2_raise_global_irq(s, GINTSTS_PRTINT);
528
+ }
529
+
530
+ qemu_bh_schedule(s->async_bh);
531
+}
532
+
533
+static void dwc2_async_packet_complete(USBPort *port, USBPacket *packet)
534
+{
535
+ DWC2State *s = port->opaque;
536
+ DWC2Packet *p;
537
+ USBDevice *dev;
538
+ USBEndpoint *ep;
539
+
540
+ assert(port->index == 0);
541
+ p = container_of(packet, DWC2Packet, packet);
542
+ dev = dwc2_find_device(s, p->devadr);
543
+ ep = usb_ep_get(dev, p->pid, p->epnum);
544
+ trace_usb_dwc2_async_packet_complete(port, packet, p->index >> 3, dev,
545
+ p->epnum, dirs[p->epdir], p->len);
546
+ assert(p->async == DWC2_ASYNC_INFLIGHT);
547
+
548
+ if (packet->status == USB_RET_REMOVE_FROM_QUEUE) {
549
+ usb_cancel_packet(packet);
550
+ usb_packet_cleanup(packet);
551
+ return;
552
+ }
553
+
554
+ dwc2_handle_packet(s, p->devadr, dev, ep, p->index, false);
555
+
556
+ p->async = DWC2_ASYNC_FINISHED;
557
+ qemu_bh_schedule(s->async_bh);
558
+}
559
+
560
+static USBPortOps dwc2_port_ops = {
561
+ .attach = dwc2_attach,
562
+ .detach = dwc2_detach,
563
+ .child_detach = dwc2_child_detach,
564
+ .wakeup = dwc2_wakeup,
565
+ .complete = dwc2_async_packet_complete,
566
+};
567
+
568
+static uint32_t dwc2_get_frame_remaining(DWC2State *s)
569
+{
570
+ uint32_t fr = 0;
571
+ int64_t tks;
572
+
573
+ tks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->sof_time;
574
+ if (tks < 0) {
575
+ tks = 0;
576
+ }
577
+
578
+ /* avoid muldiv if possible */
579
+ if (tks >= s->usb_frame_time) {
580
+ goto out;
581
+ }
582
+ if (tks < s->usb_bit_time) {
583
+ fr = s->fi;
584
+ goto out;
585
+ }
586
+
587
+ /* tks = number of ns since SOF, divided by 83 (fs) or 10 (hs) */
588
+ tks = tks / s->usb_bit_time;
589
+ if (tks >= (int64_t)s->fi) {
590
+ goto out;
591
+ }
592
+
593
+ /* remaining = frame interval minus tks */
594
+ fr = (uint32_t)((int64_t)s->fi - tks);
595
+
596
+out:
597
+ return fr;
598
+}
599
+
600
+static void dwc2_work_bh(void *opaque)
601
+{
602
+ DWC2State *s = opaque;
603
+ DWC2Packet *p;
604
+ USBDevice *dev;
605
+ USBEndpoint *ep;
606
+ int64_t t_now, expire_time;
607
+ int chan;
608
+ bool found = false;
609
+
610
+ trace_usb_dwc2_work_bh();
611
+ if (s->working) {
612
+ return;
613
+ }
614
+ s->working = true;
615
+
616
+ t_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
617
+ chan = s->next_chan;
618
+
619
+ do {
620
+ p = &s->packet[chan];
621
+ if (p->needs_service) {
622
+ dev = dwc2_find_device(s, p->devadr);
623
+ ep = usb_ep_get(dev, p->pid, p->epnum);
624
+ trace_usb_dwc2_work_bh_service(s->next_chan, chan, dev, p->epnum);
625
+ dwc2_handle_packet(s, p->devadr, dev, ep, p->index, true);
626
+ found = true;
627
+ }
628
+ if (++chan == DWC2_NB_CHAN) {
629
+ chan = 0;
630
+ }
631
+ if (found) {
632
+ s->next_chan = chan;
633
+ trace_usb_dwc2_work_bh_next(chan);
634
+ }
635
+ } while (chan != s->next_chan);
636
+
637
+ if (found) {
638
+ expire_time = t_now + NANOSECONDS_PER_SECOND / 4000;
639
+ timer_mod(s->frame_timer, expire_time);
640
+ }
641
+ s->working = false;
642
+}
643
+
644
+static void dwc2_enable_chan(DWC2State *s, uint32_t index)
645
+{
646
+ USBDevice *dev;
647
+ USBEndpoint *ep;
648
+ uint32_t hcchar;
649
+ uint32_t hctsiz;
650
+ uint32_t devadr, epnum, epdir, eptype, pid, len;
651
+ DWC2Packet *p;
652
+
653
+ assert((index >> 3) < DWC2_NB_CHAN);
654
+ p = &s->packet[index >> 3];
655
+ hcchar = s->hreg1[index];
656
+ hctsiz = s->hreg1[index + 4];
657
+ devadr = get_field(hcchar, HCCHAR_DEVADDR);
658
+ epnum = get_field(hcchar, HCCHAR_EPNUM);
659
+ epdir = get_bit(hcchar, HCCHAR_EPDIR);
660
+ eptype = get_field(hcchar, HCCHAR_EPTYPE);
661
+ pid = get_field(hctsiz, TSIZ_SC_MC_PID);
662
+ len = get_field(hctsiz, TSIZ_XFERSIZE);
663
+
664
+ dev = dwc2_find_device(s, devadr);
665
+
666
+ trace_usb_dwc2_enable_chan(index >> 3, dev, &p->packet, epnum);
667
+ if (dev == NULL) {
668
+ return;
669
+ }
670
+
671
+ if (eptype == USB_ENDPOINT_XFER_CONTROL && pid == TSIZ_SC_MC_PID_SETUP) {
672
+ pid = USB_TOKEN_SETUP;
673
+ } else {
674
+ pid = epdir ? USB_TOKEN_IN : USB_TOKEN_OUT;
675
+ }
676
+
677
+ ep = usb_ep_get(dev, pid, epnum);
678
+
679
+ /*
680
+ * Hack: Networking doesn't like us delivering large transfers, it kind
681
+ * of works but the latency is horrible. So if the transfer is <= the mtu
682
+ * size, we take that as a hint that this might be a network transfer,
683
+ * and do the transfer packet-by-packet.
684
+ */
685
+ if (len > 1536) {
686
+ p->small = false;
687
+ } else {
688
+ p->small = true;
689
+ }
690
+
691
+ dwc2_handle_packet(s, devadr, dev, ep, index, true);
692
+ qemu_bh_schedule(s->async_bh);
693
+}
694
+
695
+static const char *glbregnm[] = {
696
+ "GOTGCTL ", "GOTGINT ", "GAHBCFG ", "GUSBCFG ", "GRSTCTL ",
697
+ "GINTSTS ", "GINTMSK ", "GRXSTSR ", "GRXSTSP ", "GRXFSIZ ",
698
+ "GNPTXFSIZ", "GNPTXSTS ", "GI2CCTL ", "GPVNDCTL ", "GGPIO ",
699
+ "GUID ", "GSNPSID ", "GHWCFG1 ", "GHWCFG2 ", "GHWCFG3 ",
700
+ "GHWCFG4 ", "GLPMCFG ", "GPWRDN ", "GDFIFOCFG", "GADPCTL ",
701
+ "GREFCLK ", "GINTMSK2 ", "GINTSTS2 "
702
+};
703
+
704
+static uint64_t dwc2_glbreg_read(void *ptr, hwaddr addr, int index,
705
+ unsigned size)
706
+{
707
+ DWC2State *s = ptr;
708
+ uint32_t val;
709
+
710
+ assert(addr <= GINTSTS2);
711
+ val = s->glbreg[index];
712
+
713
+ switch (addr) {
714
+ case GRSTCTL:
715
+ /* clear any self-clearing bits that were set */
716
+ val &= ~(GRSTCTL_TXFFLSH | GRSTCTL_RXFFLSH | GRSTCTL_IN_TKNQ_FLSH |
717
+ GRSTCTL_FRMCNTRRST | GRSTCTL_HSFTRST | GRSTCTL_CSFTRST);
718
+ s->glbreg[index] = val;
719
+ break;
720
+ default:
721
+ break;
722
+ }
723
+
724
+ trace_usb_dwc2_glbreg_read(addr, glbregnm[index], val);
725
+ return val;
726
+}
727
+
728
+static void dwc2_glbreg_write(void *ptr, hwaddr addr, int index, uint64_t val,
729
+ unsigned size)
730
+{
731
+ DWC2State *s = ptr;
732
+ uint64_t orig = val;
733
+ uint32_t *mmio;
734
+ uint32_t old;
735
+ int iflg = 0;
736
+
737
+ assert(addr <= GINTSTS2);
738
+ mmio = &s->glbreg[index];
739
+ old = *mmio;
740
+
741
+ switch (addr) {
742
+ case GOTGCTL:
743
+ /* don't allow setting of read-only bits */
744
+ val &= ~(GOTGCTL_MULT_VALID_BC_MASK | GOTGCTL_BSESVLD |
745
+ GOTGCTL_ASESVLD | GOTGCTL_DBNC_SHORT | GOTGCTL_CONID_B |
746
+ GOTGCTL_HSTNEGSCS | GOTGCTL_SESREQSCS);
747
+ /* don't allow clearing of read-only bits */
748
+ val |= old & (GOTGCTL_MULT_VALID_BC_MASK | GOTGCTL_BSESVLD |
749
+ GOTGCTL_ASESVLD | GOTGCTL_DBNC_SHORT | GOTGCTL_CONID_B |
750
+ GOTGCTL_HSTNEGSCS | GOTGCTL_SESREQSCS);
751
+ break;
752
+ case GAHBCFG:
753
+ if ((val & GAHBCFG_GLBL_INTR_EN) && !(old & GAHBCFG_GLBL_INTR_EN)) {
754
+ iflg = 1;
755
+ }
756
+ break;
757
+ case GRSTCTL:
758
+ val |= GRSTCTL_AHBIDLE;
759
+ val &= ~GRSTCTL_DMAREQ;
760
+ if (!(old & GRSTCTL_TXFFLSH) && (val & GRSTCTL_TXFFLSH)) {
761
+ /* TODO - TX fifo flush */
762
+ qemu_log_mask(LOG_UNIMP, "Tx FIFO flush not implemented\n");
763
+ }
764
+ if (!(old & GRSTCTL_RXFFLSH) && (val & GRSTCTL_RXFFLSH)) {
765
+ /* TODO - RX fifo flush */
766
+ qemu_log_mask(LOG_UNIMP, "Rx FIFO flush not implemented\n");
767
+ }
768
+ if (!(old & GRSTCTL_IN_TKNQ_FLSH) && (val & GRSTCTL_IN_TKNQ_FLSH)) {
769
+ /* TODO - device IN token queue flush */
770
+ qemu_log_mask(LOG_UNIMP, "Token queue flush not implemented\n");
771
+ }
772
+ if (!(old & GRSTCTL_FRMCNTRRST) && (val & GRSTCTL_FRMCNTRRST)) {
773
+ /* TODO - host frame counter reset */
774
+ qemu_log_mask(LOG_UNIMP, "Frame counter reset not implemented\n");
775
+ }
776
+ if (!(old & GRSTCTL_HSFTRST) && (val & GRSTCTL_HSFTRST)) {
777
+ /* TODO - host soft reset */
778
+ qemu_log_mask(LOG_UNIMP, "Host soft reset not implemented\n");
779
+ }
780
+ if (!(old & GRSTCTL_CSFTRST) && (val & GRSTCTL_CSFTRST)) {
781
+ /* TODO - core soft reset */
782
+ qemu_log_mask(LOG_UNIMP, "Core soft reset not implemented\n");
783
+ }
784
+ /* don't allow clearing of self-clearing bits */
785
+ val |= old & (GRSTCTL_TXFFLSH | GRSTCTL_RXFFLSH |
786
+ GRSTCTL_IN_TKNQ_FLSH | GRSTCTL_FRMCNTRRST |
787
+ GRSTCTL_HSFTRST | GRSTCTL_CSFTRST);
788
+ break;
789
+ case GINTSTS:
790
+ /* clear the write-1-to-clear bits */
791
+ val |= ~old;
792
+ val = ~val;
793
+ /* don't allow clearing of read-only bits */
794
+ val |= old & (GINTSTS_PTXFEMP | GINTSTS_HCHINT | GINTSTS_PRTINT |
795
+ GINTSTS_OEPINT | GINTSTS_IEPINT | GINTSTS_GOUTNAKEFF |
796
+ GINTSTS_GINNAKEFF | GINTSTS_NPTXFEMP | GINTSTS_RXFLVL |
797
+ GINTSTS_OTGINT | GINTSTS_CURMODE_HOST);
798
+ iflg = 1;
799
+ break;
800
+ case GINTMSK:
801
+ iflg = 1;
802
+ break;
803
+ default:
804
+ break;
805
+ }
806
+
807
+ trace_usb_dwc2_glbreg_write(addr, glbregnm[index], orig, old, val);
808
+ *mmio = val;
809
+
810
+ if (iflg) {
811
+ dwc2_update_irq(s);
812
+ }
813
+}
814
+
815
+static uint64_t dwc2_fszreg_read(void *ptr, hwaddr addr, int index,
816
+ unsigned size)
817
+{
818
+ DWC2State *s = ptr;
819
+ uint32_t val;
820
+
821
+ assert(addr == HPTXFSIZ);
822
+ val = s->fszreg[index];
823
+
824
+ trace_usb_dwc2_fszreg_read(addr, val);
825
+ return val;
826
+}
827
+
828
+static void dwc2_fszreg_write(void *ptr, hwaddr addr, int index, uint64_t val,
829
+ unsigned size)
830
+{
831
+ DWC2State *s = ptr;
832
+ uint64_t orig = val;
833
+ uint32_t *mmio;
834
+ uint32_t old;
835
+
836
+ assert(addr == HPTXFSIZ);
837
+ mmio = &s->fszreg[index];
838
+ old = *mmio;
839
+
840
+ trace_usb_dwc2_fszreg_write(addr, orig, old, val);
841
+ *mmio = val;
842
+}
843
+
844
+static const char *hreg0nm[] = {
845
+ "HCFG ", "HFIR ", "HFNUM ", "<rsvd> ", "HPTXSTS ",
846
+ "HAINT ", "HAINTMSK ", "HFLBADDR ", "<rsvd> ", "<rsvd> ",
847
+ "<rsvd> ", "<rsvd> ", "<rsvd> ", "<rsvd> ", "<rsvd> ",
848
+ "<rsvd> ", "HPRT0 "
849
+};
850
+
851
+static uint64_t dwc2_hreg0_read(void *ptr, hwaddr addr, int index,
852
+ unsigned size)
853
+{
854
+ DWC2State *s = ptr;
855
+ uint32_t val;
856
+
857
+ assert(addr >= HCFG && addr <= HPRT0);
858
+ val = s->hreg0[index];
859
+
860
+ switch (addr) {
861
+ case HFNUM:
862
+ val = (dwc2_get_frame_remaining(s) << HFNUM_FRREM_SHIFT) |
863
+ (s->hfnum << HFNUM_FRNUM_SHIFT);
864
+ break;
865
+ default:
866
+ break;
867
+ }
868
+
869
+ trace_usb_dwc2_hreg0_read(addr, hreg0nm[index], val);
870
+ return val;
871
+}
872
+
873
+static void dwc2_hreg0_write(void *ptr, hwaddr addr, int index, uint64_t val,
874
+ unsigned size)
875
+{
876
+ DWC2State *s = ptr;
877
+ USBDevice *dev = s->uport.dev;
878
+ uint64_t orig = val;
879
+ uint32_t *mmio;
880
+ uint32_t tval, told, old;
881
+ int prst = 0;
882
+ int iflg = 0;
883
+
884
+ assert(addr >= HCFG && addr <= HPRT0);
885
+ mmio = &s->hreg0[index];
886
+ old = *mmio;
887
+
888
+ switch (addr) {
889
+ case HFIR:
890
+ break;
891
+ case HFNUM:
892
+ case HPTXSTS:
893
+ case HAINT:
894
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: write to read-only register\n",
895
+ __func__);
896
+ return;
897
+ case HAINTMSK:
898
+ val &= 0xffff;
899
+ break;
900
+ case HPRT0:
901
+ /* don't allow clearing of read-only bits */
902
+ val |= old & (HPRT0_SPD_MASK | HPRT0_LNSTS_MASK | HPRT0_OVRCURRACT |
903
+ HPRT0_CONNSTS);
904
+ /* don't allow clearing of self-clearing bits */
905
+ val |= old & (HPRT0_SUSP | HPRT0_RES);
906
+ /* don't allow setting of self-setting bits */
907
+ if (!(old & HPRT0_ENA) && (val & HPRT0_ENA)) {
908
+ val &= ~HPRT0_ENA;
909
+ }
910
+ /* clear the write-1-to-clear bits */
911
+ tval = val & (HPRT0_OVRCURRCHG | HPRT0_ENACHG | HPRT0_ENA |
912
+ HPRT0_CONNDET);
913
+ told = old & (HPRT0_OVRCURRCHG | HPRT0_ENACHG | HPRT0_ENA |
914
+ HPRT0_CONNDET);
915
+ tval |= ~told;
916
+ tval = ~tval;
917
+ tval &= (HPRT0_OVRCURRCHG | HPRT0_ENACHG | HPRT0_ENA |
918
+ HPRT0_CONNDET);
919
+ val &= ~(HPRT0_OVRCURRCHG | HPRT0_ENACHG | HPRT0_ENA |
920
+ HPRT0_CONNDET);
921
+ val |= tval;
922
+ if (!(val & HPRT0_RST) && (old & HPRT0_RST)) {
923
+ if (dev && dev->attached) {
924
+ val |= HPRT0_ENA | HPRT0_ENACHG;
925
+ prst = 1;
926
+ }
927
+ }
928
+ if (val & (HPRT0_OVRCURRCHG | HPRT0_ENACHG | HPRT0_CONNDET)) {
929
+ iflg = 1;
930
+ } else {
931
+ iflg = -1;
932
+ }
933
+ break;
934
+ default:
935
+ break;
936
+ }
937
+
938
+ if (prst) {
939
+ trace_usb_dwc2_hreg0_write(addr, hreg0nm[index], orig, old,
940
+ val & ~HPRT0_CONNDET);
941
+ trace_usb_dwc2_hreg0_action("call usb_port_reset");
942
+ usb_port_reset(&s->uport);
943
+ val &= ~HPRT0_CONNDET;
944
+ } else {
945
+ trace_usb_dwc2_hreg0_write(addr, hreg0nm[index], orig, old, val);
946
+ }
947
+
948
+ *mmio = val;
949
+
950
+ if (iflg > 0) {
951
+ trace_usb_dwc2_hreg0_action("enable PRTINT");
952
+ dwc2_raise_global_irq(s, GINTSTS_PRTINT);
953
+ } else if (iflg < 0) {
954
+ trace_usb_dwc2_hreg0_action("disable PRTINT");
955
+ dwc2_lower_global_irq(s, GINTSTS_PRTINT);
956
+ }
957
+}
958
+
959
+static const char *hreg1nm[] = {
960
+ "HCCHAR ", "HCSPLT ", "HCINT ", "HCINTMSK", "HCTSIZ ", "HCDMA ",
961
+ "<rsvd> ", "HCDMAB "
962
+};
963
+
964
+static uint64_t dwc2_hreg1_read(void *ptr, hwaddr addr, int index,
965
+ unsigned size)
966
+{
967
+ DWC2State *s = ptr;
968
+ uint32_t val;
969
+
970
+ assert(addr >= HCCHAR(0) && addr <= HCDMAB(DWC2_NB_CHAN - 1));
971
+ val = s->hreg1[index];
972
+
973
+ trace_usb_dwc2_hreg1_read(addr, hreg1nm[index & 7], addr >> 5, val);
974
+ return val;
975
+}
976
+
977
+static void dwc2_hreg1_write(void *ptr, hwaddr addr, int index, uint64_t val,
978
+ unsigned size)
979
+{
980
+ DWC2State *s = ptr;
981
+ uint64_t orig = val;
982
+ uint32_t *mmio;
983
+ uint32_t old;
984
+ int iflg = 0;
985
+ int enflg = 0;
986
+ int disflg = 0;
987
+
988
+ assert(addr >= HCCHAR(0) && addr <= HCDMAB(DWC2_NB_CHAN - 1));
989
+ mmio = &s->hreg1[index];
990
+ old = *mmio;
991
+
992
+ switch (HSOTG_REG(0x500) + (addr & 0x1c)) {
993
+ case HCCHAR(0):
994
+ if ((val & HCCHAR_CHDIS) && !(old & HCCHAR_CHDIS)) {
995
+ val &= ~(HCCHAR_CHENA | HCCHAR_CHDIS);
996
+ disflg = 1;
997
+ } else {
998
+ val |= old & HCCHAR_CHDIS;
999
+ if ((val & HCCHAR_CHENA) && !(old & HCCHAR_CHENA)) {
1000
+ val &= ~HCCHAR_CHDIS;
1001
+ enflg = 1;
1002
+ } else {
1003
+ val |= old & HCCHAR_CHENA;
1004
+ }
1005
+ }
1006
+ break;
1007
+ case HCINT(0):
1008
+ /* clear the write-1-to-clear bits */
1009
+ val |= ~old;
1010
+ val = ~val;
1011
+ val &= ~HCINTMSK_RESERVED14_31;
1012
+ iflg = 1;
1013
+ break;
1014
+ case HCINTMSK(0):
1015
+ val &= ~HCINTMSK_RESERVED14_31;
1016
+ iflg = 1;
1017
+ break;
1018
+ case HCDMAB(0):
1019
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: write to read-only register\n",
1020
+ __func__);
1021
+ return;
1022
+ default:
1023
+ break;
1024
+ }
1025
+
1026
+ trace_usb_dwc2_hreg1_write(addr, hreg1nm[index & 7], index >> 3, orig,
1027
+ old, val);
1028
+ *mmio = val;
1029
+
1030
+ if (disflg) {
1031
+ /* set ChHltd in HCINT */
1032
+ s->hreg1[(index & ~7) + 2] |= HCINTMSK_CHHLTD;
1033
+ iflg = 1;
1034
+ }
1035
+
1036
+ if (enflg) {
1037
+ dwc2_enable_chan(s, index & ~7);
1038
+ }
1039
+
1040
+ if (iflg) {
1041
+ dwc2_update_hc_irq(s, index & ~7);
1042
+ }
1043
+}
1044
+
1045
+static const char *pcgregnm[] = {
1046
+ "PCGCTL ", "PCGCCTL1 "
1047
+};
1048
+
1049
+static uint64_t dwc2_pcgreg_read(void *ptr, hwaddr addr, int index,
1050
+ unsigned size)
1051
+{
1052
+ DWC2State *s = ptr;
1053
+ uint32_t val;
1054
+
1055
+ assert(addr >= PCGCTL && addr <= PCGCCTL1);
1056
+ val = s->pcgreg[index];
1057
+
1058
+ trace_usb_dwc2_pcgreg_read(addr, pcgregnm[index], val);
1059
+ return val;
1060
+}
1061
+
1062
+static void dwc2_pcgreg_write(void *ptr, hwaddr addr, int index,
1063
+ uint64_t val, unsigned size)
1064
+{
1065
+ DWC2State *s = ptr;
1066
+ uint64_t orig = val;
1067
+ uint32_t *mmio;
1068
+ uint32_t old;
1069
+
1070
+ assert(addr >= PCGCTL && addr <= PCGCCTL1);
1071
+ mmio = &s->pcgreg[index];
1072
+ old = *mmio;
1073
+
1074
+ trace_usb_dwc2_pcgreg_write(addr, pcgregnm[index], orig, old, val);
1075
+ *mmio = val;
1076
+}
1077
+
1078
+static uint64_t dwc2_hsotg_read(void *ptr, hwaddr addr, unsigned size)
1079
+{
1080
+ uint64_t val;
1081
+
1082
+ switch (addr) {
1083
+ case HSOTG_REG(0x000) ... HSOTG_REG(0x0fc):
1084
+ val = dwc2_glbreg_read(ptr, addr, (addr - HSOTG_REG(0x000)) >> 2, size);
1085
+ break;
1086
+ case HSOTG_REG(0x100):
1087
+ val = dwc2_fszreg_read(ptr, addr, (addr - HSOTG_REG(0x100)) >> 2, size);
1088
+ break;
1089
+ case HSOTG_REG(0x104) ... HSOTG_REG(0x3fc):
1090
+ /* Gadget-mode registers, just return 0 for now */
1091
+ val = 0;
1092
+ break;
1093
+ case HSOTG_REG(0x400) ... HSOTG_REG(0x4fc):
1094
+ val = dwc2_hreg0_read(ptr, addr, (addr - HSOTG_REG(0x400)) >> 2, size);
1095
+ break;
1096
+ case HSOTG_REG(0x500) ... HSOTG_REG(0x7fc):
1097
+ val = dwc2_hreg1_read(ptr, addr, (addr - HSOTG_REG(0x500)) >> 2, size);
1098
+ break;
1099
+ case HSOTG_REG(0x800) ... HSOTG_REG(0xdfc):
1100
+ /* Gadget-mode registers, just return 0 for now */
1101
+ val = 0;
1102
+ break;
1103
+ case HSOTG_REG(0xe00) ... HSOTG_REG(0xffc):
1104
+ val = dwc2_pcgreg_read(ptr, addr, (addr - HSOTG_REG(0xe00)) >> 2, size);
1105
+ break;
259
+ break;
1106
+ default:
260
+ default:
1107
+ g_assert_not_reached();
261
+ g_assert_not_reached();
1108
+ }
262
+ }
1109
+
263
+
1110
+ return val;
264
+ freq >>= (CLK2CKDIV(clkdiv1) + CLK4CKDIV(clkdiv1) + APB3CKDIV(clkdiv2));
1111
+}
265
+
1112
+
266
+ return freq;
1113
+static void dwc2_hsotg_write(void *ptr, hwaddr addr, uint64_t val,
267
+}
1114
+ unsigned size)
268
+
1115
+{
269
+static uint32_t pwm_selector(uint32_t csr)
1116
+ switch (addr) {
270
+{
1117
+ case HSOTG_REG(0x000) ... HSOTG_REG(0x0fc):
271
+ switch (csr) {
1118
+ dwc2_glbreg_write(ptr, addr, (addr - HSOTG_REG(0x000)) >> 2, val, size);
272
+ case 0:
1119
+ break;
273
+ return 2;
1120
+ case HSOTG_REG(0x100):
274
+ case 1:
1121
+ dwc2_fszreg_write(ptr, addr, (addr - HSOTG_REG(0x100)) >> 2, val, size);
275
+ return 4;
1122
+ break;
276
+ case 2:
1123
+ case HSOTG_REG(0x104) ... HSOTG_REG(0x3fc):
277
+ return 8;
1124
+ /* Gadget-mode registers, do nothing for now */
278
+ case 3:
1125
+ break;
279
+ return 16;
1126
+ case HSOTG_REG(0x400) ... HSOTG_REG(0x4fc):
280
+ case 4:
1127
+ dwc2_hreg0_write(ptr, addr, (addr - HSOTG_REG(0x400)) >> 2, val, size);
281
+ return 1;
1128
+ break;
1129
+ case HSOTG_REG(0x500) ... HSOTG_REG(0x7fc):
1130
+ dwc2_hreg1_write(ptr, addr, (addr - HSOTG_REG(0x500)) >> 2, val, size);
1131
+ break;
1132
+ case HSOTG_REG(0x800) ... HSOTG_REG(0xdfc):
1133
+ /* Gadget-mode registers, do nothing for now */
1134
+ break;
1135
+ case HSOTG_REG(0xe00) ... HSOTG_REG(0xffc):
1136
+ dwc2_pcgreg_write(ptr, addr, (addr - HSOTG_REG(0xe00)) >> 2, val, size);
1137
+ break;
1138
+ default:
282
+ default:
1139
+ g_assert_not_reached();
283
+ g_assert_not_reached();
1140
+ }
284
+ }
1141
+}
285
+}
1142
+
286
+
1143
+static const MemoryRegionOps dwc2_mmio_hsotg_ops = {
287
+static uint64_t pwm_compute_freq(QTestState *qts, uint32_t ppr, uint32_t csr,
1144
+ .read = dwc2_hsotg_read,
288
+ uint32_t cnr)
1145
+ .write = dwc2_hsotg_write,
289
+{
1146
+ .impl.min_access_size = 4,
290
+ return read_pclk(qts) / ((ppr + 1) * pwm_selector(csr) * (cnr + 1));
1147
+ .impl.max_access_size = 4,
291
+}
1148
+ .endianness = DEVICE_LITTLE_ENDIAN,
292
+
1149
+};
293
+static uint64_t pwm_compute_duty(uint32_t cnr, uint32_t cmr, bool inverted)
1150
+
294
+{
1151
+static uint64_t dwc2_hreg2_read(void *ptr, hwaddr addr, unsigned size)
295
+ uint64_t duty;
1152
+{
296
+
1153
+ /* TODO - implement FIFOs to support slave mode */
297
+ if (cnr == 0) {
1154
+ trace_usb_dwc2_hreg2_read(addr, addr >> 12, 0);
298
+ /* PWM is stopped. */
1155
+ qemu_log_mask(LOG_UNIMP, "FIFO read not implemented\n");
299
+ duty = 0;
1156
+ return 0;
300
+ } else if (cmr >= cnr) {
1157
+}
301
+ duty = MAX_DUTY;
1158
+
1159
+static void dwc2_hreg2_write(void *ptr, hwaddr addr, uint64_t val,
1160
+ unsigned size)
1161
+{
1162
+ uint64_t orig = val;
1163
+
1164
+ /* TODO - implement FIFOs to support slave mode */
1165
+ trace_usb_dwc2_hreg2_write(addr, addr >> 12, orig, 0, val);
1166
+ qemu_log_mask(LOG_UNIMP, "FIFO write not implemented\n");
1167
+}
1168
+
1169
+static const MemoryRegionOps dwc2_mmio_hreg2_ops = {
1170
+ .read = dwc2_hreg2_read,
1171
+ .write = dwc2_hreg2_write,
1172
+ .impl.min_access_size = 4,
1173
+ .impl.max_access_size = 4,
1174
+ .endianness = DEVICE_LITTLE_ENDIAN,
1175
+};
1176
+
1177
+static void dwc2_wakeup_endpoint(USBBus *bus, USBEndpoint *ep,
1178
+ unsigned int stream)
1179
+{
1180
+ DWC2State *s = container_of(bus, DWC2State, bus);
1181
+
1182
+ trace_usb_dwc2_wakeup_endpoint(ep, stream);
1183
+
1184
+ /* TODO - do something here? */
1185
+ qemu_bh_schedule(s->async_bh);
1186
+}
1187
+
1188
+static USBBusOps dwc2_bus_ops = {
1189
+ .wakeup_endpoint = dwc2_wakeup_endpoint,
1190
+};
1191
+
1192
+static void dwc2_work_timer(void *opaque)
1193
+{
1194
+ DWC2State *s = opaque;
1195
+
1196
+ trace_usb_dwc2_work_timer();
1197
+ qemu_bh_schedule(s->async_bh);
1198
+}
1199
+
1200
+static void dwc2_reset_enter(Object *obj, ResetType type)
1201
+{
1202
+ DWC2Class *c = DWC2_GET_CLASS(obj);
1203
+ DWC2State *s = DWC2_USB(obj);
1204
+ int i;
1205
+
1206
+ trace_usb_dwc2_reset_enter();
1207
+
1208
+ if (c->parent_phases.enter) {
1209
+ c->parent_phases.enter(obj, type);
1210
+ }
1211
+
1212
+ timer_del(s->frame_timer);
1213
+ qemu_bh_cancel(s->async_bh);
1214
+
1215
+ if (s->uport.dev && s->uport.dev->attached) {
1216
+ usb_detach(&s->uport);
1217
+ }
1218
+
1219
+ dwc2_bus_stop(s);
1220
+
1221
+ s->gotgctl = GOTGCTL_BSESVLD | GOTGCTL_ASESVLD | GOTGCTL_CONID_B;
1222
+ s->gotgint = 0;
1223
+ s->gahbcfg = 0;
1224
+ s->gusbcfg = 5 << GUSBCFG_USBTRDTIM_SHIFT;
1225
+ s->grstctl = GRSTCTL_AHBIDLE;
1226
+ s->gintsts = GINTSTS_CONIDSTSCHNG | GINTSTS_PTXFEMP | GINTSTS_NPTXFEMP |
1227
+ GINTSTS_CURMODE_HOST;
1228
+ s->gintmsk = 0;
1229
+ s->grxstsr = 0;
1230
+ s->grxstsp = 0;
1231
+ s->grxfsiz = 1024;
1232
+ s->gnptxfsiz = 1024 << FIFOSIZE_DEPTH_SHIFT;
1233
+ s->gnptxsts = (4 << FIFOSIZE_DEPTH_SHIFT) | 1024;
1234
+ s->gi2cctl = GI2CCTL_I2CDATSE0 | GI2CCTL_ACK;
1235
+ s->gpvndctl = 0;
1236
+ s->ggpio = 0;
1237
+ s->guid = 0;
1238
+ s->gsnpsid = 0x4f54294a;
1239
+ s->ghwcfg1 = 0;
1240
+ s->ghwcfg2 = (8 << GHWCFG2_DEV_TOKEN_Q_DEPTH_SHIFT) |
1241
+ (4 << GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT) |
1242
+ (4 << GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT) |
1243
+ GHWCFG2_DYNAMIC_FIFO |
1244
+ GHWCFG2_PERIO_EP_SUPPORTED |
1245
+ ((DWC2_NB_CHAN - 1) << GHWCFG2_NUM_HOST_CHAN_SHIFT) |
1246
+ (GHWCFG2_INT_DMA_ARCH << GHWCFG2_ARCHITECTURE_SHIFT) |
1247
+ (GHWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST << GHWCFG2_OP_MODE_SHIFT);
1248
+ s->ghwcfg3 = (4096 << GHWCFG3_DFIFO_DEPTH_SHIFT) |
1249
+ (4 << GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT) |
1250
+ (4 << GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT);
1251
+ s->ghwcfg4 = 0;
1252
+ s->glpmcfg = 0;
1253
+ s->gpwrdn = GPWRDN_PWRDNRSTN;
1254
+ s->gdfifocfg = 0;
1255
+ s->gadpctl = 0;
1256
+ s->grefclk = 0;
1257
+ s->gintmsk2 = 0;
1258
+ s->gintsts2 = 0;
1259
+
1260
+ s->hptxfsiz = 500 << FIFOSIZE_DEPTH_SHIFT;
1261
+
1262
+ s->hcfg = 2 << HCFG_RESVALID_SHIFT;
1263
+ s->hfir = 60000;
1264
+ s->hfnum = 0x3fff;
1265
+ s->hptxsts = (16 << TXSTS_QSPCAVAIL_SHIFT) | 32768;
1266
+ s->haint = 0;
1267
+ s->haintmsk = 0;
1268
+ s->hprt0 = 0;
1269
+
1270
+ memset(s->hreg1, 0, sizeof(s->hreg1));
1271
+ memset(s->pcgreg, 0, sizeof(s->pcgreg));
1272
+
1273
+ s->sof_time = 0;
1274
+ s->frame_number = 0;
1275
+ s->fi = USB_FRMINTVL - 1;
1276
+ s->next_chan = 0;
1277
+ s->working = false;
1278
+
1279
+ for (i = 0; i < DWC2_NB_CHAN; i++) {
1280
+ s->packet[i].needs_service = false;
1281
+ }
1282
+}
1283
+
1284
+static void dwc2_reset_hold(Object *obj)
1285
+{
1286
+ DWC2Class *c = DWC2_GET_CLASS(obj);
1287
+ DWC2State *s = DWC2_USB(obj);
1288
+
1289
+ trace_usb_dwc2_reset_hold();
1290
+
1291
+ if (c->parent_phases.hold) {
1292
+ c->parent_phases.hold(obj);
1293
+ }
1294
+
1295
+ dwc2_update_irq(s);
1296
+}
1297
+
1298
+static void dwc2_reset_exit(Object *obj)
1299
+{
1300
+ DWC2Class *c = DWC2_GET_CLASS(obj);
1301
+ DWC2State *s = DWC2_USB(obj);
1302
+
1303
+ trace_usb_dwc2_reset_exit();
1304
+
1305
+ if (c->parent_phases.exit) {
1306
+ c->parent_phases.exit(obj);
1307
+ }
1308
+
1309
+ s->hprt0 = HPRT0_PWR;
1310
+ if (s->uport.dev && s->uport.dev->attached) {
1311
+ usb_attach(&s->uport);
1312
+ usb_device_reset(s->uport.dev);
1313
+ }
1314
+}
1315
+
1316
+static void dwc2_realize(DeviceState *dev, Error **errp)
1317
+{
1318
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
1319
+ DWC2State *s = DWC2_USB(dev);
1320
+ Object *obj;
1321
+ Error *err = NULL;
1322
+
1323
+ obj = object_property_get_link(OBJECT(dev), "dma-mr", &err);
1324
+ if (err) {
1325
+ error_setg(errp, "dwc2: required dma-mr link not found: %s",
1326
+ error_get_pretty(err));
1327
+ return;
1328
+ }
1329
+ assert(obj != NULL);
1330
+
1331
+ s->dma_mr = MEMORY_REGION(obj);
1332
+ address_space_init(&s->dma_as, s->dma_mr, "dwc2");
1333
+
1334
+ usb_bus_new(&s->bus, sizeof(s->bus), &dwc2_bus_ops, dev);
1335
+ usb_register_port(&s->bus, &s->uport, s, 0, &dwc2_port_ops,
1336
+ USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL |
1337
+ (s->usb_version == 2 ? USB_SPEED_MASK_HIGH : 0));
1338
+ s->uport.dev = 0;
1339
+
1340
+ s->usb_frame_time = NANOSECONDS_PER_SECOND / 1000; /* 1000000 */
1341
+ if (NANOSECONDS_PER_SECOND >= USB_HZ_FS) {
1342
+ s->usb_bit_time = NANOSECONDS_PER_SECOND / USB_HZ_FS; /* 83.3 */
1343
+ } else {
302
+ } else {
1344
+ s->usb_bit_time = 1;
303
+ duty = MAX_DUTY * (cmr + 1) / (cnr + 1);
1345
+ }
304
+ }
1346
+
305
+
1347
+ s->fi = USB_FRMINTVL - 1;
306
+ if (inverted) {
1348
+ s->eof_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, dwc2_frame_boundary, s);
307
+ duty = MAX_DUTY - duty;
1349
+ s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, dwc2_work_timer, s);
308
+ }
1350
+ s->async_bh = qemu_bh_new(dwc2_work_bh, s);
309
+
1351
+
310
+ return duty;
1352
+ sysbus_init_irq(sbd, &s->irq);
311
+}
1353
+}
312
+
1354
+
313
+static uint32_t pwm_read(QTestState *qts, const TestData *td, unsigned offset)
1355
+static void dwc2_init(Object *obj)
314
+{
1356
+{
315
+ return qtest_readl(qts, td->module->base_addr + offset);
1357
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
316
+}
1358
+ DWC2State *s = DWC2_USB(obj);
317
+
1359
+
318
+static void pwm_write(QTestState *qts, const TestData *td, unsigned offset,
1360
+ memory_region_init(&s->container, obj, "dwc2", DWC2_MMIO_SIZE);
319
+ uint32_t value)
1361
+ sysbus_init_mmio(sbd, &s->container);
320
+{
1362
+
321
+ qtest_writel(qts, td->module->base_addr + offset, value);
1363
+ memory_region_init_io(&s->hsotg, obj, &dwc2_mmio_hsotg_ops, s,
322
+}
1364
+ "dwc2-io", 4 * KiB);
323
+
1365
+ memory_region_add_subregion(&s->container, 0x0000, &s->hsotg);
324
+static uint32_t pwm_read_ppr(QTestState *qts, const TestData *td)
1366
+
325
+{
1367
+ memory_region_init_io(&s->fifos, obj, &dwc2_mmio_hreg2_ops, s,
326
+ return extract32(pwm_read(qts, td, PPR), ppr_base[pwm_index(td->pwm)], 8);
1368
+ "dwc2-fifo", 64 * KiB);
327
+}
1369
+ memory_region_add_subregion(&s->container, 0x1000, &s->fifos);
328
+
1370
+}
329
+static void pwm_write_ppr(QTestState *qts, const TestData *td, uint32_t value)
1371
+
330
+{
1372
+static const VMStateDescription vmstate_dwc2_state_packet = {
331
+ pwm_write(qts, td, PPR, value << ppr_base[pwm_index(td->pwm)]);
1373
+ .name = "dwc2/packet",
332
+}
1374
+ .version_id = 1,
333
+
1375
+ .minimum_version_id = 1,
334
+static uint32_t pwm_read_csr(QTestState *qts, const TestData *td)
1376
+ .fields = (VMStateField[]) {
335
+{
1377
+ VMSTATE_UINT32(devadr, DWC2Packet),
336
+ return extract32(pwm_read(qts, td, CSR), csr_base[pwm_index(td->pwm)], 3);
1378
+ VMSTATE_UINT32(epnum, DWC2Packet),
337
+}
1379
+ VMSTATE_UINT32(epdir, DWC2Packet),
338
+
1380
+ VMSTATE_UINT32(mps, DWC2Packet),
339
+static void pwm_write_csr(QTestState *qts, const TestData *td, uint32_t value)
1381
+ VMSTATE_UINT32(pid, DWC2Packet),
340
+{
1382
+ VMSTATE_UINT32(index, DWC2Packet),
341
+ pwm_write(qts, td, CSR, value << csr_base[pwm_index(td->pwm)]);
1383
+ VMSTATE_UINT32(pcnt, DWC2Packet),
342
+}
1384
+ VMSTATE_UINT32(len, DWC2Packet),
343
+
1385
+ VMSTATE_INT32(async, DWC2Packet),
344
+static uint32_t pwm_read_pcr(QTestState *qts, const TestData *td)
1386
+ VMSTATE_BOOL(small, DWC2Packet),
345
+{
1387
+ VMSTATE_BOOL(needs_service, DWC2Packet),
346
+ return extract32(pwm_read(qts, td, PCR), pcr_base[pwm_index(td->pwm)], 4);
1388
+ VMSTATE_END_OF_LIST()
347
+}
1389
+ },
348
+
1390
+};
349
+static void pwm_write_pcr(QTestState *qts, const TestData *td, uint32_t value)
1391
+
350
+{
1392
+const VMStateDescription vmstate_dwc2_state = {
351
+ pwm_write(qts, td, PCR, value << pcr_base[pwm_index(td->pwm)]);
1393
+ .name = "dwc2",
352
+}
1394
+ .version_id = 1,
353
+
1395
+ .minimum_version_id = 1,
354
+static uint32_t pwm_read_cnr(QTestState *qts, const TestData *td)
1396
+ .fields = (VMStateField[]) {
355
+{
1397
+ VMSTATE_UINT32_ARRAY(glbreg, DWC2State,
356
+ return pwm_read(qts, td, td->pwm->cnr_offset);
1398
+ DWC2_GLBREG_SIZE / sizeof(uint32_t)),
357
+}
1399
+ VMSTATE_UINT32_ARRAY(fszreg, DWC2State,
358
+
1400
+ DWC2_FSZREG_SIZE / sizeof(uint32_t)),
359
+static void pwm_write_cnr(QTestState *qts, const TestData *td, uint32_t value)
1401
+ VMSTATE_UINT32_ARRAY(hreg0, DWC2State,
360
+{
1402
+ DWC2_HREG0_SIZE / sizeof(uint32_t)),
361
+ pwm_write(qts, td, td->pwm->cnr_offset, value);
1403
+ VMSTATE_UINT32_ARRAY(hreg1, DWC2State,
362
+}
1404
+ DWC2_HREG1_SIZE / sizeof(uint32_t)),
363
+
1405
+ VMSTATE_UINT32_ARRAY(pcgreg, DWC2State,
364
+static uint32_t pwm_read_cmr(QTestState *qts, const TestData *td)
1406
+ DWC2_PCGREG_SIZE / sizeof(uint32_t)),
365
+{
1407
+
366
+ return pwm_read(qts, td, td->pwm->cmr_offset);
1408
+ VMSTATE_TIMER_PTR(eof_timer, DWC2State),
367
+}
1409
+ VMSTATE_TIMER_PTR(frame_timer, DWC2State),
368
+
1410
+ VMSTATE_INT64(sof_time, DWC2State),
369
+static void pwm_write_cmr(QTestState *qts, const TestData *td, uint32_t value)
1411
+ VMSTATE_INT64(usb_frame_time, DWC2State),
370
+{
1412
+ VMSTATE_INT64(usb_bit_time, DWC2State),
371
+ pwm_write(qts, td, td->pwm->cmr_offset, value);
1413
+ VMSTATE_UINT32(usb_version, DWC2State),
372
+}
1414
+ VMSTATE_UINT16(frame_number, DWC2State),
373
+
1415
+ VMSTATE_UINT16(fi, DWC2State),
374
+/* Check pwm registers can be reset to default value */
1416
+ VMSTATE_UINT16(next_chan, DWC2State),
375
+static void test_init(gconstpointer test_data)
1417
+ VMSTATE_BOOL(working, DWC2State),
376
+{
1418
+
377
+ const TestData *td = test_data;
1419
+ VMSTATE_STRUCT_ARRAY(packet, DWC2State, DWC2_NB_CHAN, 1,
378
+ QTestState *qts = qtest_init("-machine quanta-gsj");
1420
+ vmstate_dwc2_state_packet, DWC2Packet),
379
+ int module = pwm_module_index(td->module);
1421
+ VMSTATE_UINT8_2DARRAY(usb_buf, DWC2State, DWC2_NB_CHAN,
380
+ int pwm = pwm_index(td->pwm);
1422
+ DWC2_MAX_XFER_SIZE),
381
+
1423
+
382
+ g_assert_cmpuint(pwm_get_freq(qts, module, pwm), ==, 0);
1424
+ VMSTATE_END_OF_LIST()
383
+ g_assert_cmpuint(pwm_get_duty(qts, module, pwm), ==, 0);
1425
+ }
384
+
1426
+};
385
+ qtest_quit(qts);
1427
+
386
+}
1428
+static Property dwc2_usb_properties[] = {
387
+
1429
+ DEFINE_PROP_UINT32("usb_version", DWC2State, usb_version, 2),
388
+/* One-shot mode should not change frequency and duty cycle. */
1430
+ DEFINE_PROP_END_OF_LIST(),
389
+static void test_oneshot(gconstpointer test_data)
1431
+};
390
+{
1432
+
391
+ const TestData *td = test_data;
1433
+static void dwc2_class_init(ObjectClass *klass, void *data)
392
+ QTestState *qts = qtest_init("-machine quanta-gsj");
1434
+{
393
+ int module = pwm_module_index(td->module);
1435
+ DeviceClass *dc = DEVICE_CLASS(klass);
394
+ int pwm = pwm_index(td->pwm);
1436
+ DWC2Class *c = DWC2_CLASS(klass);
395
+ uint32_t ppr, csr, pcr;
1437
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
396
+ int i, j;
1438
+
397
+
1439
+ dc->realize = dwc2_realize;
398
+ pcr = CH_EN;
1440
+ dc->vmsd = &vmstate_dwc2_state;
399
+ for (i = 0; i < ARRAY_SIZE(ppr_list); ++i) {
1441
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
400
+ ppr = ppr_list[i];
1442
+ device_class_set_props(dc, dwc2_usb_properties);
401
+ pwm_write_ppr(qts, td, ppr);
1443
+ resettable_class_set_parent_phases(rc, dwc2_reset_enter, dwc2_reset_hold,
402
+
1444
+ dwc2_reset_exit, &c->parent_phases);
403
+ for (j = 0; j < ARRAY_SIZE(csr_list); ++j) {
1445
+}
404
+ csr = csr_list[j];
1446
+
405
+ pwm_write_csr(qts, td, csr);
1447
+static const TypeInfo dwc2_usb_type_info = {
406
+ pwm_write_pcr(qts, td, pcr);
1448
+ .name = TYPE_DWC2_USB,
407
+
1449
+ .parent = TYPE_SYS_BUS_DEVICE,
408
+ g_assert_cmpuint(pwm_read_ppr(qts, td), ==, ppr);
1450
+ .instance_size = sizeof(DWC2State),
409
+ g_assert_cmpuint(pwm_read_csr(qts, td), ==, csr);
1451
+ .instance_init = dwc2_init,
410
+ g_assert_cmpuint(pwm_read_pcr(qts, td), ==, pcr);
1452
+ .class_size = sizeof(DWC2Class),
411
+ g_assert_cmpuint(pwm_get_freq(qts, module, pwm), ==, 0);
1453
+ .class_init = dwc2_class_init,
412
+ g_assert_cmpuint(pwm_get_duty(qts, module, pwm), ==, 0);
1454
+};
413
+ }
1455
+
414
+ }
1456
+static void dwc2_usb_register_types(void)
415
+
1457
+{
416
+ qtest_quit(qts);
1458
+ type_register_static(&dwc2_usb_type_info);
417
+}
1459
+}
418
+
1460
+
419
+/* In toggle mode, the PWM generates correct outputs. */
1461
+type_init(dwc2_usb_register_types)
420
+static void test_toggle(gconstpointer test_data)
1462
diff --git a/hw/usb/Kconfig b/hw/usb/Kconfig
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
1463
index XXXXXXX..XXXXXXX 100644
515
index XXXXXXX..XXXXXXX 100644
1464
--- a/hw/usb/Kconfig
516
--- a/tests/qtest/meson.build
1465
+++ b/hw/usb/Kconfig
517
+++ b/tests/qtest/meson.build
1466
@@ -XXX,XX +XXX,XX @@ config USB_MUSB
518
@@ -XXX,XX +XXX,XX @@ qtests_sparc64 = \
1467
bool
519
qtests_npcm7xx = \
1468
select USB
520
['npcm7xx_adc-test',
1469
521
'npcm7xx_gpio-test',
1470
+config USB_DWC2
522
+ 'npcm7xx_pwm-test',
1471
+ bool
523
'npcm7xx_rng-test',
1472
+ default y
524
'npcm7xx_timer-test',
1473
+ select USB
525
'npcm7xx_watchdog_timer-test']
1474
+
1475
config TUSB6010
1476
bool
1477
select USB_MUSB
1478
diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs
1479
index XXXXXXX..XXXXXXX 100644
1480
--- a/hw/usb/Makefile.objs
1481
+++ b/hw/usb/Makefile.objs
1482
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_USB_EHCI_SYSBUS) += hcd-ehci-sysbus.o
1483
common-obj-$(CONFIG_USB_XHCI) += hcd-xhci.o
1484
common-obj-$(CONFIG_USB_XHCI_NEC) += hcd-xhci-nec.o
1485
common-obj-$(CONFIG_USB_MUSB) += hcd-musb.o
1486
+common-obj-$(CONFIG_USB_DWC2) += hcd-dwc2.o
1487
1488
common-obj-$(CONFIG_TUSB6010) += tusb6010.o
1489
common-obj-$(CONFIG_IMX) += chipidea.o
1490
diff --git a/hw/usb/trace-events b/hw/usb/trace-events
1491
index XXXXXXX..XXXXXXX 100644
1492
--- a/hw/usb/trace-events
1493
+++ b/hw/usb/trace-events
1494
@@ -XXX,XX +XXX,XX @@ usb_xhci_xfer_error(void *xfer, uint32_t ret) "%p: ret %d"
1495
usb_xhci_unimplemented(const char *item, int nr) "%s (0x%x)"
1496
usb_xhci_enforced_limit(const char *item) "%s"
1497
1498
+# hcd-dwc2.c
1499
+usb_dwc2_update_irq(uint32_t level) "level=%d"
1500
+usb_dwc2_raise_global_irq(uint32_t intr) "0x%08x"
1501
+usb_dwc2_lower_global_irq(uint32_t intr) "0x%08x"
1502
+usb_dwc2_raise_host_irq(uint32_t intr) "0x%04x"
1503
+usb_dwc2_lower_host_irq(uint32_t intr) "0x%04x"
1504
+usb_dwc2_sof(int64_t next) "next SOF %" PRId64
1505
+usb_dwc2_bus_start(void) "start SOFs"
1506
+usb_dwc2_bus_stop(void) "stop SOFs"
1507
+usb_dwc2_find_device(uint8_t addr) "%d"
1508
+usb_dwc2_port_disabled(uint32_t pnum) "port %d disabled"
1509
+usb_dwc2_device_found(uint32_t pnum) "device found on port %d"
1510
+usb_dwc2_device_not_found(void) "device not found"
1511
+usb_dwc2_handle_packet(uint32_t chan, void *dev, void *pkt, uint32_t ep, const char *type, const char *dir, uint32_t mps, uint32_t len, uint32_t pcnt) "ch %d dev %p pkt %p ep %d type %s dir %s mps %d len %d pcnt %d"
1512
+usb_dwc2_memory_read(uint32_t addr, uint32_t len) "addr %d len %d"
1513
+usb_dwc2_packet_status(const char *status, uint32_t len) "status %s len %d"
1514
+usb_dwc2_packet_error(const char *status) "ERROR %s"
1515
+usb_dwc2_async_packet(void *pkt, uint32_t chan, void *dev, uint32_t ep, const char *dir, uint32_t len) "pkt %p ch %d dev %p ep %d %s len %d"
1516
+usb_dwc2_memory_write(uint32_t addr, uint32_t len) "addr %d len %d"
1517
+usb_dwc2_packet_done(const char *status, uint32_t actual, uint32_t len, uint32_t pcnt) "status %s actual %d len %d pcnt %d"
1518
+usb_dwc2_packet_next(const char *status, uint32_t len, uint32_t pcnt) "status %s len %d pcnt %d"
1519
+usb_dwc2_attach(void *port) "port %p"
1520
+usb_dwc2_attach_speed(const char *speed) "%s-speed device attached"
1521
+usb_dwc2_detach(void *port) "port %p"
1522
+usb_dwc2_child_detach(void *port, void *child) "port %p child %p"
1523
+usb_dwc2_wakeup(void *port) "port %p"
1524
+usb_dwc2_async_packet_complete(void *port, void *pkt, uint32_t chan, void *dev, uint32_t ep, const char *dir, uint32_t len) "port %p packet %p ch %d dev %p ep %d %s len %d"
1525
+usb_dwc2_work_bh(void) ""
1526
+usb_dwc2_work_bh_service(uint32_t first, uint32_t current, void *dev, uint32_t ep) "first %d servicing %d dev %p ep %d"
1527
+usb_dwc2_work_bh_next(uint32_t chan) "next %d"
1528
+usb_dwc2_enable_chan(uint32_t chan, void *dev, void *pkt, uint32_t ep) "ch %d dev %p pkt %p ep %d"
1529
+usb_dwc2_glbreg_read(uint64_t addr, const char *reg, uint32_t val) " 0x%04" PRIx64 " %s val 0x%08x"
1530
+usb_dwc2_glbreg_write(uint64_t addr, const char *reg, uint64_t val, uint32_t old, uint64_t result) "0x%04" PRIx64 " %s val 0x%08" PRIx64 " old 0x%08x result 0x%08" PRIx64
1531
+usb_dwc2_fszreg_read(uint64_t addr, uint32_t val) " 0x%04" PRIx64 " HPTXFSIZ val 0x%08x"
1532
+usb_dwc2_fszreg_write(uint64_t addr, uint64_t val, uint32_t old, uint64_t result) "0x%04" PRIx64 " HPTXFSIZ val 0x%08" PRIx64 " old 0x%08x result 0x%08" PRIx64
1533
+usb_dwc2_hreg0_read(uint64_t addr, const char *reg, uint32_t val) " 0x%04" PRIx64 " %s val 0x%08x"
1534
+usb_dwc2_hreg0_write(uint64_t addr, const char *reg, uint64_t val, uint32_t old, uint64_t result) " 0x%04" PRIx64 " %s val 0x%08" PRIx64 " old 0x%08x result 0x%08" PRIx64
1535
+usb_dwc2_hreg1_read(uint64_t addr, const char *reg, uint64_t chan, uint32_t val) " 0x%04" PRIx64 " %s%" PRId64 " val 0x%08x"
1536
+usb_dwc2_hreg1_write(uint64_t addr, const char *reg, uint64_t chan, uint64_t val, uint32_t old, uint64_t result) " 0x%04" PRIx64 " %s%" PRId64 " val 0x%08" PRIx64 " old 0x%08x result 0x%08" PRIx64
1537
+usb_dwc2_pcgreg_read(uint64_t addr, const char *reg, uint32_t val) " 0x%04" PRIx64 " %s val 0x%08x"
1538
+usb_dwc2_pcgreg_write(uint64_t addr, const char *reg, uint64_t val, uint32_t old, uint64_t result) "0x%04" PRIx64 " %s val 0x%08" PRIx64 " old 0x%08x result 0x%08" PRIx64
1539
+usb_dwc2_hreg2_read(uint64_t addr, uint64_t fifo, uint32_t val) " 0x%04" PRIx64 " FIFO%" PRId64 " val 0x%08x"
1540
+usb_dwc2_hreg2_write(uint64_t addr, uint64_t fifo, uint64_t val, uint32_t old, uint64_t result) " 0x%04" PRIx64 " FIFO%" PRId64 " val 0x%08" PRIx64 " old 0x%08x result 0x%08" PRIx64
1541
+usb_dwc2_hreg0_action(const char *s) "%s"
1542
+usb_dwc2_wakeup_endpoint(void *ep, uint32_t stream) "endp %p stream %d"
1543
+usb_dwc2_work_timer(void) ""
1544
+usb_dwc2_reset_enter(void) "=== RESET enter ==="
1545
+usb_dwc2_reset_hold(void) "=== RESET hold ==="
1546
+usb_dwc2_reset_exit(void) "=== RESET exit ==="
1547
+
1548
# desc.c
1549
usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d"
1550
usb_desc_device_qualifier(int addr, int len, int ret) "dev %d query device qualifier, len %d, ret %d"
1551
--
526
--
1552
2.20.1
527
2.20.1
1553
528
1554
529
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
With this conversion, we will be able to use the same helpers
3
A device shouldn't access its parent object which is QOM internal.
4
with sve. This also fixes a bug in which we failed to clear
4
Instead it should use type cast for this purporse. This patch fixes this
5
the high bits of the SVE register after an AdvSIMD operation.
5
issue for all NPCM7XX Devices.
6
6
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Hao Wu <wuhaotsh@google.com>
8
Message-id: 20200514212831.31248-3-richard.henderson@linaro.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20210108190945.949196-7-wuhaotsh@google.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
target/arm/helper.h | 2 ++
12
hw/arm/npcm7xx_boards.c | 2 +-
13
target/arm/translate-a64.h | 3 ++
13
hw/mem/npcm7xx_mc.c | 2 +-
14
target/arm/crypto_helper.c | 11 +++++++
14
hw/misc/npcm7xx_clk.c | 2 +-
15
target/arm/translate-a64.c | 59 ++++++++++++++++++++------------------
15
hw/misc/npcm7xx_gcr.c | 2 +-
16
4 files changed, 47 insertions(+), 28 deletions(-)
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
diff --git a/target/arm/helper.h b/target/arm/helper.h
21
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
19
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper.h
23
--- a/hw/arm/npcm7xx_boards.c
21
+++ b/target/arm/helper.h
24
+++ b/hw/arm/npcm7xx_boards.c
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(crypto_sm3partw2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
25
@@ -XXX,XX +XXX,XX @@ static NPCM7xxState *npcm7xx_create_soc(MachineState *machine,
23
DEF_HELPER_FLAGS_4(crypto_sm4e, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
26
uint32_t hw_straps)
24
DEF_HELPER_FLAGS_4(crypto_sm4ekey, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
27
{
25
28
NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_GET_CLASS(machine);
26
+DEF_HELPER_FLAGS_4(crypto_rax1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
29
- MachineClass *mc = &nmc->parent;
27
+
30
+ MachineClass *mc = MACHINE_CLASS(nmc);
28
DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
31
Object *obj;
29
DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
32
30
33
if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
31
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
34
diff --git a/hw/mem/npcm7xx_mc.c b/hw/mem/npcm7xx_mc.c
32
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/translate-a64.h
36
--- a/hw/mem/npcm7xx_mc.c
34
+++ b/target/arm/translate-a64.h
37
+++ b/hw/mem/npcm7xx_mc.c
35
@@ -XXX,XX +XXX,XX @@ static inline int vec_full_reg_size(DisasContext *s)
38
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_mc_realize(DeviceState *dev, Error **errp)
36
39
37
bool disas_sve(DisasContext *, uint32_t);
40
memory_region_init_io(&s->mmio, OBJECT(s), &npcm7xx_mc_ops, s, "regs",
38
41
NPCM7XX_MC_REGS_SIZE);
39
+void gen_gvec_rax1(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
42
- sysbus_init_mmio(&s->parent, &s->mmio);
40
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
43
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio);
41
+
44
}
42
#endif /* TARGET_ARM_TRANSLATE_A64_H */
45
43
diff --git a/target/arm/crypto_helper.c b/target/arm/crypto_helper.c
46
static void npcm7xx_mc_class_init(ObjectClass *klass, void *data)
47
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
44
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/crypto_helper.c
49
--- a/hw/misc/npcm7xx_clk.c
46
+++ b/target/arm/crypto_helper.c
50
+++ b/hw/misc/npcm7xx_clk.c
47
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sm4ekey)(void *vd, void *vn, void* vm, uint32_t desc)
51
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_clk_init(Object *obj)
48
}
52
49
clear_tail(vd, opr_sz, simd_maxsz(desc));
53
memory_region_init_io(&s->iomem, obj, &npcm7xx_clk_ops, s,
54
TYPE_NPCM7XX_CLK, 4 * KiB);
55
- sysbus_init_mmio(&s->parent, &s->iomem);
56
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
50
}
57
}
51
+
58
52
+void HELPER(crypto_rax1)(void *vd, void *vn, void *vm, uint32_t desc)
59
static int npcm7xx_clk_post_load(void *opaque, int version_id)
53
+{
60
diff --git a/hw/misc/npcm7xx_gcr.c b/hw/misc/npcm7xx_gcr.c
54
+ intptr_t i, opr_sz = simd_oprsz(desc);
55
+ uint64_t *d = vd, *n = vn, *m = vm;
56
+
57
+ for (i = 0; i < opr_sz / 8; ++i) {
58
+ d[i] = n[i] ^ rol64(m[i], 1);
59
+ }
60
+ clear_tail(vd, opr_sz, simd_maxsz(desc));
61
+}
62
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
63
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
64
--- a/target/arm/translate-a64.c
62
--- a/hw/misc/npcm7xx_gcr.c
65
+++ b/target/arm/translate-a64.c
63
+++ b/hw/misc/npcm7xx_gcr.c
66
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
64
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_gcr_init(Object *obj)
67
tcg_temp_free_ptr(tcg_rn_ptr);
65
66
memory_region_init_io(&s->iomem, obj, &npcm7xx_gcr_ops, s,
67
TYPE_NPCM7XX_GCR, 4 * KiB);
68
- sysbus_init_mmio(&s->parent, &s->iomem);
69
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
68
}
70
}
69
71
70
+static void gen_rax1_i64(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m)
72
static const VMStateDescription vmstate_npcm7xx_gcr = {
71
+{
73
diff --git a/hw/misc/npcm7xx_rng.c b/hw/misc/npcm7xx_rng.c
72
+ tcg_gen_rotli_i64(d, m, 1);
74
index XXXXXXX..XXXXXXX 100644
73
+ tcg_gen_xor_i64(d, d, n);
75
--- a/hw/misc/npcm7xx_rng.c
74
+}
76
+++ b/hw/misc/npcm7xx_rng.c
75
+
77
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_rng_init(Object *obj)
76
+static void gen_rax1_vec(unsigned vece, TCGv_vec d, TCGv_vec n, TCGv_vec m)
78
77
+{
79
memory_region_init_io(&s->iomem, obj, &npcm7xx_rng_ops, s, "regs",
78
+ tcg_gen_rotli_vec(vece, d, m, 1);
80
NPCM7XX_RNG_REGS_SIZE);
79
+ tcg_gen_xor_vec(vece, d, d, n);
81
- sysbus_init_mmio(&s->parent, &s->iomem);
80
+}
82
+ sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
81
+
82
+void gen_gvec_rax1(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
83
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
84
+{
85
+ static const TCGOpcode vecop_list[] = { INDEX_op_rotli_vec, 0 };
86
+ static const GVecGen3 op = {
87
+ .fni8 = gen_rax1_i64,
88
+ .fniv = gen_rax1_vec,
89
+ .opt_opc = vecop_list,
90
+ .fno = gen_helper_crypto_rax1,
91
+ .vece = MO_64,
92
+ };
93
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &op);
94
+}
95
+
96
/* Crypto three-reg SHA512
97
* 31 21 20 16 15 14 13 12 11 10 9 5 4 0
98
* +-----------------------+------+---+---+-----+--------+------+------+
99
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
100
bool feature;
101
CryptoThreeOpFn *genfn = NULL;
102
gen_helper_gvec_3 *oolfn = NULL;
103
+ GVecGen3Fn *gvecfn = NULL;
104
105
if (o == 0) {
106
switch (opcode) {
107
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
108
break;
109
case 3: /* RAX1 */
110
feature = dc_isar_feature(aa64_sha3, s);
111
- genfn = NULL;
112
+ gvecfn = gen_gvec_rax1;
113
break;
114
default:
115
g_assert_not_reached();
116
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
117
118
if (oolfn) {
119
gen_gvec_op3_ool(s, true, rd, rn, rm, 0, oolfn);
120
- return;
121
- }
122
-
123
- if (genfn) {
124
+ } else if (gvecfn) {
125
+ gen_gvec_fn3(s, true, rd, rn, rm, gvecfn, MO_64);
126
+ } else {
127
TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
128
129
tcg_rd_ptr = vec_full_reg_ptr(s, rd);
130
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
131
tcg_temp_free_ptr(tcg_rd_ptr);
132
tcg_temp_free_ptr(tcg_rn_ptr);
133
tcg_temp_free_ptr(tcg_rm_ptr);
134
- } else {
135
- TCGv_i64 tcg_op1, tcg_op2, tcg_res[2];
136
- int pass;
137
-
138
- tcg_op1 = tcg_temp_new_i64();
139
- tcg_op2 = tcg_temp_new_i64();
140
- tcg_res[0] = tcg_temp_new_i64();
141
- tcg_res[1] = tcg_temp_new_i64();
142
-
143
- for (pass = 0; pass < 2; pass++) {
144
- read_vec_element(s, tcg_op1, rn, pass, MO_64);
145
- read_vec_element(s, tcg_op2, rm, pass, MO_64);
146
-
147
- tcg_gen_rotli_i64(tcg_res[pass], tcg_op2, 1);
148
- tcg_gen_xor_i64(tcg_res[pass], tcg_res[pass], tcg_op1);
149
- }
150
- write_vec_element(s, tcg_res[0], rd, 0, MO_64);
151
- write_vec_element(s, tcg_res[1], rd, 1, MO_64);
152
-
153
- tcg_temp_free_i64(tcg_op1);
154
- tcg_temp_free_i64(tcg_op2);
155
- tcg_temp_free_i64(tcg_res[0]);
156
- tcg_temp_free_i64(tcg_res[1]);
157
}
158
}
83
}
159
84
85
static const VMStateDescription vmstate_npcm7xx_rng = {
86
diff --git a/hw/nvram/npcm7xx_otp.c b/hw/nvram/npcm7xx_otp.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/hw/nvram/npcm7xx_otp.c
89
+++ b/hw/nvram/npcm7xx_otp.c
90
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_otp_realize(DeviceState *dev, Error **errp)
91
{
92
NPCM7xxOTPClass *oc = NPCM7XX_OTP_GET_CLASS(dev);
93
NPCM7xxOTPState *s = NPCM7XX_OTP(dev);
94
- SysBusDevice *sbd = &s->parent;
95
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
96
97
memset(s->array, 0, sizeof(s->array));
98
99
diff --git a/hw/ssi/npcm7xx_fiu.c b/hw/ssi/npcm7xx_fiu.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/hw/ssi/npcm7xx_fiu.c
102
+++ b/hw/ssi/npcm7xx_fiu.c
103
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_fiu_hold_reset(Object *obj)
104
static void npcm7xx_fiu_realize(DeviceState *dev, Error **errp)
105
{
106
NPCM7xxFIUState *s = NPCM7XX_FIU(dev);
107
- SysBusDevice *sbd = &s->parent;
108
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
109
int i;
110
111
if (s->cs_count <= 0) {
160
--
112
--
161
2.20.1
113
2.20.1
162
114
163
115
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
The ADC region size is 256B, split as:
4
- [0x00 - 0x4f] defined
5
- [0x50 - 0xff] reserved
6
7
All registers are 32-bit (thus when the datasheet mentions the
8
last defined register is 0x4c, it means its address range is
9
0x4c .. 0x4f.
10
11
This model implementation is also 32-bit. Set MemoryRegionOps
12
'impl' fields.
13
14
See:
15
'RM0033 Reference manual Rev 8', Table 10.13.18 "ADC register map".
16
17
Reported-by: Seth Kintigh <skintigh@gmail.com>
18
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
19
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Message-id: 20200603055915.17678-1-f4bug@amsat.org
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
23
hw/adc/stm32f2xx_adc.c | 4 +++-
24
1 file changed, 3 insertions(+), 1 deletion(-)
25
26
diff --git a/hw/adc/stm32f2xx_adc.c b/hw/adc/stm32f2xx_adc.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/adc/stm32f2xx_adc.c
29
+++ b/hw/adc/stm32f2xx_adc.c
30
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps stm32f2xx_adc_ops = {
31
.read = stm32f2xx_adc_read,
32
.write = stm32f2xx_adc_write,
33
.endianness = DEVICE_NATIVE_ENDIAN,
34
+ .impl.min_access_size = 4,
35
+ .impl.max_access_size = 4,
36
};
37
38
static const VMStateDescription vmstate_stm32f2xx_adc = {
39
@@ -XXX,XX +XXX,XX @@ static void stm32f2xx_adc_init(Object *obj)
40
sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
41
42
memory_region_init_io(&s->mmio, obj, &stm32f2xx_adc_ops, s,
43
- TYPE_STM32F2XX_ADC, 0xFF);
44
+ TYPE_STM32F2XX_ADC, 0x100);
45
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
46
}
47
48
--
49
2.20.1
50
51
diff view generated by jsdifflib
1
From: Cédric Le Goater <clg@kaod.org>
1
From: Roman Bolshakov <r.bolshakov@yadro.com>
2
2
3
Signed-off-by: Cédric Le Goater <clg@kaod.org>
3
ui/cocoa.m:1188:44: warning: 'openFile:' is deprecated: first deprecated in macOS 11.0 - Use -[NSWorkspace openURL:] instead.
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
[-Wdeprecated-declarations]
5
Message-id: 20200602135050.593692-1-clg@kaod.org
5
if ([[NSWorkspace sharedWorkspace] openFile: full_file_path] == YES) {
6
^
7
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSWorkspace.h:350:1: note:
8
'openFile:' has been explicitly marked deprecated here
9
- (BOOL)openFile:(NSString *)fullPath API_DEPRECATED("Use -[NSWorkspace openURL:] instead.", macos(10.0, 11.0));
10
^
11
12
Signed-off-by: Roman Bolshakov <r.bolshakov@yadro.com>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20210102150718.47618-1-r.bolshakov@yadro.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
16
---
8
docs/system/arm/aspeed.rst | 85 ++++++++++++++++++++++++++++++++++++++
17
ui/cocoa.m | 5 ++++-
9
docs/system/target-arm.rst | 1 +
18
1 file changed, 4 insertions(+), 1 deletion(-)
10
2 files changed, 86 insertions(+)
11
create mode 100644 docs/system/arm/aspeed.rst
12
19
13
diff --git a/docs/system/arm/aspeed.rst b/docs/system/arm/aspeed.rst
20
diff --git a/ui/cocoa.m b/ui/cocoa.m
14
new file mode 100644
15
index XXXXXXX..XXXXXXX
16
--- /dev/null
17
+++ b/docs/system/arm/aspeed.rst
18
@@ -XXX,XX +XXX,XX @@
19
+Aspeed family boards (``*-bmc``, ``ast2500-evb``, ``ast2600-evb``)
20
+==================================================================
21
+
22
+The QEMU Aspeed machines model BMCs of various OpenPOWER systems and
23
+Aspeed evaluation boards. They are based on different releases of the
24
+Aspeed SoC : the AST2400 integrating an ARM926EJ-S CPU (400MHz), the
25
+AST2500 with an ARM1176JZS CPU (800MHz) and more recently the AST2600
26
+with dual cores ARM Cortex A7 CPUs (1.2GHz).
27
+
28
+The SoC comes with RAM, Gigabit ethernet, USB, SD/MMC, USB, SPI, I2C,
29
+etc.
30
+
31
+AST2400 SoC based machines :
32
+
33
+- ``palmetto-bmc`` OpenPOWER Palmetto POWER8 BMC
34
+
35
+AST2500 SoC based machines :
36
+
37
+- ``ast2500-evb`` Aspeed AST2500 Evaluation board
38
+- ``romulus-bmc`` OpenPOWER Romulus POWER9 BMC
39
+- ``witherspoon-bmc`` OpenPOWER Witherspoon POWER9 BMC
40
+- ``sonorapass-bmc`` OCP SonoraPass BMC
41
+- ``swift-bmc`` OpenPOWER Swift BMC POWER9
42
+
43
+AST2600 SoC based machines :
44
+
45
+- ``ast2600-evb`` Aspeed AST2600 Evaluation board (Cortex A7)
46
+- ``tacoma-bmc`` OpenPOWER Witherspoon POWER9 AST2600 BMC
47
+
48
+Supported devices
49
+-----------------
50
+
51
+ * SMP (for the AST2600 Cortex-A7)
52
+ * Interrupt Controller (VIC)
53
+ * Timer Controller
54
+ * RTC Controller
55
+ * I2C Controller
56
+ * System Control Unit (SCU)
57
+ * SRAM mapping
58
+ * X-DMA Controller (basic interface)
59
+ * Static Memory Controller (SMC or FMC) - Only SPI Flash support
60
+ * SPI Memory Controller
61
+ * USB 2.0 Controller
62
+ * SD/MMC storage controllers
63
+ * SDRAM controller (dummy interface for basic settings and training)
64
+ * Watchdog Controller
65
+ * GPIO Controller (Master only)
66
+ * UART
67
+ * Ethernet controllers
68
+
69
+
70
+Missing devices
71
+---------------
72
+
73
+ * Coprocessor support
74
+ * ADC (out of tree implementation)
75
+ * PWM and Fan Controller
76
+ * LPC Bus Controller
77
+ * Slave GPIO Controller
78
+ * Super I/O Controller
79
+ * Hash/Crypto Engine
80
+ * PCI-Express 1 Controller
81
+ * Graphic Display Controller
82
+ * PECI Controller
83
+ * MCTP Controller
84
+ * Mailbox Controller
85
+ * Virtual UART
86
+ * eSPI Controller
87
+ * I3C Controller
88
+
89
+Boot options
90
+------------
91
+
92
+The Aspeed machines can be started using the -kernel option to load a
93
+Linux kernel or from a firmare image which can be downloaded from the
94
+OpenPOWER jenkins :
95
+
96
+ https://openpower.xyz/
97
+
98
+The image should be attached as an MTD drive. Run :
99
+
100
+.. code-block:: bash
101
+
102
+ $ qemu-system-arm -M romulus-bmc -nic user \
103
+    -drive file=flash-romulus,format=raw,if=mtd -nographic
104
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
105
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
106
--- a/docs/system/target-arm.rst
22
--- a/ui/cocoa.m
107
+++ b/docs/system/target-arm.rst
23
+++ b/ui/cocoa.m
108
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
24
@@ -XXX,XX +XXX,XX @@ QemuCocoaView *cocoaView;
109
arm/realview
25
/* Where to look for local files */
110
arm/versatile
26
NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"docs/"};
111
arm/vexpress
27
NSString *full_file_path;
112
+ arm/aspeed
28
+ NSURL *full_file_url;
113
arm/musicpal
29
114
arm/nseries
30
/* iterate thru the possible paths until the file is found */
115
arm/orangepi
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;
41
}
42
}
116
--
43
--
117
2.20.1
44
2.20.1
118
45
119
46
diff view generated by jsdifflib
Deleted patch
1
Convert the VSHL and VSLI insns from the Neon 2-registers-and-a-shift
2
group to decodetree.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200522145520.6778-2-peter.maydell@linaro.org
7
---
8
target/arm/neon-dp.decode | 25 ++++++++++++++++++++++
9
target/arm/translate-neon.inc.c | 38 +++++++++++++++++++++++++++++++++
10
target/arm/translate.c | 18 +++++++---------
11
3 files changed, 71 insertions(+), 10 deletions(-)
12
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
16
+++ b/target/arm/neon-dp.decode
17
@@ -XXX,XX +XXX,XX @@ VRECPS_fp_3s 1111 001 0 0 . 0 . .... .... 1111 ... 1 .... @3same_fp
18
VRSQRTS_fp_3s 1111 001 0 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
19
VMAXNM_fp_3s 1111 001 1 0 . 0 . .... .... 1111 ... 1 .... @3same_fp
20
VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
21
+
22
+######################################################################
23
+# 2-reg-and-shift grouping:
24
+# 1111 001 U 1 D immH:3 immL:3 Vd:4 opc:4 L Q M 1 Vm:4
25
+######################################################################
26
+&2reg_shift vm vd q shift size
27
+
28
+@2reg_shl_d .... ... . . . shift:6 .... .... 1 q:1 . . .... \
29
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=3
30
+@2reg_shl_s .... ... . . . 1 shift:5 .... .... 0 q:1 . . .... \
31
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=2
32
+@2reg_shl_h .... ... . . . 01 shift:4 .... .... 0 q:1 . . .... \
33
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=1
34
+@2reg_shl_b .... ... . . . 001 shift:3 .... .... 0 q:1 . . .... \
35
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=0
36
+
37
+VSHL_2sh 1111 001 0 1 . ...... .... 0101 . . . 1 .... @2reg_shl_d
38
+VSHL_2sh 1111 001 0 1 . ...... .... 0101 . . . 1 .... @2reg_shl_s
39
+VSHL_2sh 1111 001 0 1 . ...... .... 0101 . . . 1 .... @2reg_shl_h
40
+VSHL_2sh 1111 001 0 1 . ...... .... 0101 . . . 1 .... @2reg_shl_b
41
+
42
+VSLI_2sh 1111 001 1 1 . ...... .... 0101 . . . 1 .... @2reg_shl_d
43
+VSLI_2sh 1111 001 1 1 . ...... .... 0101 . . . 1 .... @2reg_shl_s
44
+VSLI_2sh 1111 001 1 1 . ...... .... 0101 . . . 1 .... @2reg_shl_h
45
+VSLI_2sh 1111 001 1 1 . ...... .... 0101 . . . 1 .... @2reg_shl_b
46
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/translate-neon.inc.c
49
+++ b/target/arm/translate-neon.inc.c
50
@@ -XXX,XX +XXX,XX @@ static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn)
51
DO_3S_FP_PAIR(VPADD, gen_helper_vfp_adds)
52
DO_3S_FP_PAIR(VPMAX, gen_helper_vfp_maxs)
53
DO_3S_FP_PAIR(VPMIN, gen_helper_vfp_mins)
54
+
55
+static bool do_vector_2sh(DisasContext *s, arg_2reg_shift *a, GVecGen2iFn *fn)
56
+{
57
+ /* Handle a 2-reg-shift insn which can be vectorized. */
58
+ int vec_size = a->q ? 16 : 8;
59
+ int rd_ofs = neon_reg_offset(a->vd, 0);
60
+ int rm_ofs = neon_reg_offset(a->vm, 0);
61
+
62
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
63
+ return false;
64
+ }
65
+
66
+ /* UNDEF accesses to D16-D31 if they don't exist. */
67
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
68
+ ((a->vd | a->vm) & 0x10)) {
69
+ return false;
70
+ }
71
+
72
+ if ((a->vm | a->vd) & a->q) {
73
+ return false;
74
+ }
75
+
76
+ if (!vfp_access_check(s)) {
77
+ return true;
78
+ }
79
+
80
+ fn(a->size, rd_ofs, rm_ofs, a->shift, vec_size, vec_size);
81
+ return true;
82
+}
83
+
84
+#define DO_2SH(INSN, FUNC) \
85
+ static bool trans_##INSN##_2sh(DisasContext *s, arg_2reg_shift *a) \
86
+ { \
87
+ return do_vector_2sh(s, a, FUNC); \
88
+ } \
89
+
90
+DO_2SH(VSHL, tcg_gen_gvec_shli)
91
+DO_2SH(VSLI, gen_gvec_sli)
92
diff --git a/target/arm/translate.c b/target/arm/translate.c
93
index XXXXXXX..XXXXXXX 100644
94
--- a/target/arm/translate.c
95
+++ b/target/arm/translate.c
96
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
97
if ((insn & 0x00380080) != 0) {
98
/* Two registers and shift. */
99
op = (insn >> 8) & 0xf;
100
+
101
+ switch (op) {
102
+ case 5: /* VSHL, VSLI */
103
+ return 1; /* handled by decodetree */
104
+ default:
105
+ break;
106
+ }
107
+
108
if (insn & (1 << 7)) {
109
/* 64-bit shift. */
110
if (op > 7) {
111
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
112
gen_gvec_sri(size, rd_ofs, rm_ofs, shift,
113
vec_size, vec_size);
114
return 0;
115
-
116
- case 5: /* VSHL, VSLI */
117
- if (u) { /* VSLI */
118
- gen_gvec_sli(size, rd_ofs, rm_ofs, shift,
119
- vec_size, vec_size);
120
- } else { /* VSHL */
121
- tcg_gen_gvec_shli(size, rd_ofs, rm_ofs, shift,
122
- vec_size, vec_size);
123
- }
124
- return 0;
125
}
126
127
if (size == 3) {
128
--
129
2.20.1
130
131
diff view generated by jsdifflib
Deleted patch
1
Convert the VSHR 2-reg-shift insns to decodetree.
2
1
3
Note that unlike the legacy decoder, we present the right shift
4
amount to the trans_ function as a positive integer.
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200522145520.6778-3-peter.maydell@linaro.org
9
---
10
target/arm/neon-dp.decode | 25 ++++++++++++++++++++
11
target/arm/translate-neon.inc.c | 41 +++++++++++++++++++++++++++++++++
12
target/arm/translate.c | 21 +----------------
13
3 files changed, 67 insertions(+), 20 deletions(-)
14
15
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/neon-dp.decode
18
+++ b/target/arm/neon-dp.decode
19
@@ -XXX,XX +XXX,XX @@ VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
20
######################################################################
21
&2reg_shift vm vd q shift size
22
23
+# Right shifts are encoded as N - shift, where N is the element size in bits.
24
+%neon_rshift_i6 16:6 !function=rsub_64
25
+%neon_rshift_i5 16:5 !function=rsub_32
26
+%neon_rshift_i4 16:4 !function=rsub_16
27
+%neon_rshift_i3 16:3 !function=rsub_8
28
+
29
+@2reg_shr_d .... ... . . . ...... .... .... 1 q:1 . . .... \
30
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=3 shift=%neon_rshift_i6
31
+@2reg_shr_s .... ... . . . 1 ..... .... .... 0 q:1 . . .... \
32
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=2 shift=%neon_rshift_i5
33
+@2reg_shr_h .... ... . . . 01 .... .... .... 0 q:1 . . .... \
34
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=1 shift=%neon_rshift_i4
35
+@2reg_shr_b .... ... . . . 001 ... .... .... 0 q:1 . . .... \
36
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=0 shift=%neon_rshift_i3
37
+
38
@2reg_shl_d .... ... . . . shift:6 .... .... 1 q:1 . . .... \
39
&2reg_shift vm=%vm_dp vd=%vd_dp size=3
40
@2reg_shl_s .... ... . . . 1 shift:5 .... .... 0 q:1 . . .... \
41
@@ -XXX,XX +XXX,XX @@ VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
42
@2reg_shl_b .... ... . . . 001 shift:3 .... .... 0 q:1 . . .... \
43
&2reg_shift vm=%vm_dp vd=%vd_dp size=0
44
45
+VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_d
46
+VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_s
47
+VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_h
48
+VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_b
49
+
50
+VSHR_U_2sh 1111 001 1 1 . ...... .... 0000 . . . 1 .... @2reg_shr_d
51
+VSHR_U_2sh 1111 001 1 1 . ...... .... 0000 . . . 1 .... @2reg_shr_s
52
+VSHR_U_2sh 1111 001 1 1 . ...... .... 0000 . . . 1 .... @2reg_shr_h
53
+VSHR_U_2sh 1111 001 1 1 . ...... .... 0000 . . . 1 .... @2reg_shr_b
54
+
55
VSHL_2sh 1111 001 0 1 . ...... .... 0101 . . . 1 .... @2reg_shl_d
56
VSHL_2sh 1111 001 0 1 . ...... .... 0101 . . . 1 .... @2reg_shl_s
57
VSHL_2sh 1111 001 0 1 . ...... .... 0101 . . . 1 .... @2reg_shl_h
58
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/translate-neon.inc.c
61
+++ b/target/arm/translate-neon.inc.c
62
@@ -XXX,XX +XXX,XX @@ static inline int plus1(DisasContext *s, int x)
63
return x + 1;
64
}
65
66
+static inline int rsub_64(DisasContext *s, int x)
67
+{
68
+ return 64 - x;
69
+}
70
+
71
+static inline int rsub_32(DisasContext *s, int x)
72
+{
73
+ return 32 - x;
74
+}
75
+static inline int rsub_16(DisasContext *s, int x)
76
+{
77
+ return 16 - x;
78
+}
79
+static inline int rsub_8(DisasContext *s, int x)
80
+{
81
+ return 8 - x;
82
+}
83
+
84
/* Include the generated Neon decoder */
85
#include "decode-neon-dp.inc.c"
86
#include "decode-neon-ls.inc.c"
87
@@ -XXX,XX +XXX,XX @@ static bool do_vector_2sh(DisasContext *s, arg_2reg_shift *a, GVecGen2iFn *fn)
88
89
DO_2SH(VSHL, tcg_gen_gvec_shli)
90
DO_2SH(VSLI, gen_gvec_sli)
91
+
92
+static bool trans_VSHR_S_2sh(DisasContext *s, arg_2reg_shift *a)
93
+{
94
+ /* Signed shift out of range results in all-sign-bits */
95
+ a->shift = MIN(a->shift, (8 << a->size) - 1);
96
+ return do_vector_2sh(s, a, tcg_gen_gvec_sari);
97
+}
98
+
99
+static void gen_zero_rd_2sh(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
100
+ int64_t shift, uint32_t oprsz, uint32_t maxsz)
101
+{
102
+ tcg_gen_gvec_dup_imm(vece, rd_ofs, oprsz, maxsz, 0);
103
+}
104
+
105
+static bool trans_VSHR_U_2sh(DisasContext *s, arg_2reg_shift *a)
106
+{
107
+ /* Shift out of range is architecturally valid and results in zero. */
108
+ if (a->shift >= (8 << a->size)) {
109
+ return do_vector_2sh(s, a, gen_zero_rd_2sh);
110
+ } else {
111
+ return do_vector_2sh(s, a, tcg_gen_gvec_shri);
112
+ }
113
+}
114
diff --git a/target/arm/translate.c b/target/arm/translate.c
115
index XXXXXXX..XXXXXXX 100644
116
--- a/target/arm/translate.c
117
+++ b/target/arm/translate.c
118
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
119
op = (insn >> 8) & 0xf;
120
121
switch (op) {
122
+ case 0: /* VSHR */
123
case 5: /* VSHL, VSLI */
124
return 1; /* handled by decodetree */
125
default:
126
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
127
}
128
129
switch (op) {
130
- case 0: /* VSHR */
131
- /* Right shift comes here negative. */
132
- shift = -shift;
133
- /* Shifts larger than the element size are architecturally
134
- * valid. Unsigned results in all zeros; signed results
135
- * in all sign bits.
136
- */
137
- if (!u) {
138
- tcg_gen_gvec_sari(size, rd_ofs, rm_ofs,
139
- MIN(shift, (8 << size) - 1),
140
- vec_size, vec_size);
141
- } else if (shift >= 8 << size) {
142
- tcg_gen_gvec_dup_imm(MO_8, rd_ofs, vec_size,
143
- vec_size, 0);
144
- } else {
145
- tcg_gen_gvec_shri(size, rd_ofs, rm_ofs, shift,
146
- vec_size, vec_size);
147
- }
148
- return 0;
149
-
150
case 1: /* VSRA */
151
/* Right shift comes here negative. */
152
shift = -shift;
153
--
154
2.20.1
155
156
diff view generated by jsdifflib
Deleted patch
1
Convert the VSRA, VSRI, VRSHR, VRSRA 2-reg-shift insns to decodetree.
2
(These are the last instructions in the group that are vectorized;
3
the rest all require looping over each element.)
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200522145520.6778-4-peter.maydell@linaro.org
8
---
9
target/arm/neon-dp.decode | 35 ++++++++++++++++++++++
10
target/arm/translate-neon.inc.c | 7 +++++
11
target/arm/translate.c | 52 +++------------------------------
12
3 files changed, 46 insertions(+), 48 deletions(-)
13
14
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/neon-dp.decode
17
+++ b/target/arm/neon-dp.decode
18
@@ -XXX,XX +XXX,XX @@ VSHR_U_2sh 1111 001 1 1 . ...... .... 0000 . . . 1 .... @2reg_shr_s
19
VSHR_U_2sh 1111 001 1 1 . ...... .... 0000 . . . 1 .... @2reg_shr_h
20
VSHR_U_2sh 1111 001 1 1 . ...... .... 0000 . . . 1 .... @2reg_shr_b
21
22
+VSRA_S_2sh 1111 001 0 1 . ...... .... 0001 . . . 1 .... @2reg_shr_d
23
+VSRA_S_2sh 1111 001 0 1 . ...... .... 0001 . . . 1 .... @2reg_shr_s
24
+VSRA_S_2sh 1111 001 0 1 . ...... .... 0001 . . . 1 .... @2reg_shr_h
25
+VSRA_S_2sh 1111 001 0 1 . ...... .... 0001 . . . 1 .... @2reg_shr_b
26
+
27
+VSRA_U_2sh 1111 001 1 1 . ...... .... 0001 . . . 1 .... @2reg_shr_d
28
+VSRA_U_2sh 1111 001 1 1 . ...... .... 0001 . . . 1 .... @2reg_shr_s
29
+VSRA_U_2sh 1111 001 1 1 . ...... .... 0001 . . . 1 .... @2reg_shr_h
30
+VSRA_U_2sh 1111 001 1 1 . ...... .... 0001 . . . 1 .... @2reg_shr_b
31
+
32
+VRSHR_S_2sh 1111 001 0 1 . ...... .... 0010 . . . 1 .... @2reg_shr_d
33
+VRSHR_S_2sh 1111 001 0 1 . ...... .... 0010 . . . 1 .... @2reg_shr_s
34
+VRSHR_S_2sh 1111 001 0 1 . ...... .... 0010 . . . 1 .... @2reg_shr_h
35
+VRSHR_S_2sh 1111 001 0 1 . ...... .... 0010 . . . 1 .... @2reg_shr_b
36
+
37
+VRSHR_U_2sh 1111 001 1 1 . ...... .... 0010 . . . 1 .... @2reg_shr_d
38
+VRSHR_U_2sh 1111 001 1 1 . ...... .... 0010 . . . 1 .... @2reg_shr_s
39
+VRSHR_U_2sh 1111 001 1 1 . ...... .... 0010 . . . 1 .... @2reg_shr_h
40
+VRSHR_U_2sh 1111 001 1 1 . ...... .... 0010 . . . 1 .... @2reg_shr_b
41
+
42
+VRSRA_S_2sh 1111 001 0 1 . ...... .... 0011 . . . 1 .... @2reg_shr_d
43
+VRSRA_S_2sh 1111 001 0 1 . ...... .... 0011 . . . 1 .... @2reg_shr_s
44
+VRSRA_S_2sh 1111 001 0 1 . ...... .... 0011 . . . 1 .... @2reg_shr_h
45
+VRSRA_S_2sh 1111 001 0 1 . ...... .... 0011 . . . 1 .... @2reg_shr_b
46
+
47
+VRSRA_U_2sh 1111 001 1 1 . ...... .... 0011 . . . 1 .... @2reg_shr_d
48
+VRSRA_U_2sh 1111 001 1 1 . ...... .... 0011 . . . 1 .... @2reg_shr_s
49
+VRSRA_U_2sh 1111 001 1 1 . ...... .... 0011 . . . 1 .... @2reg_shr_h
50
+VRSRA_U_2sh 1111 001 1 1 . ...... .... 0011 . . . 1 .... @2reg_shr_b
51
+
52
+VSRI_2sh 1111 001 1 1 . ...... .... 0100 . . . 1 .... @2reg_shr_d
53
+VSRI_2sh 1111 001 1 1 . ...... .... 0100 . . . 1 .... @2reg_shr_s
54
+VSRI_2sh 1111 001 1 1 . ...... .... 0100 . . . 1 .... @2reg_shr_h
55
+VSRI_2sh 1111 001 1 1 . ...... .... 0100 . . . 1 .... @2reg_shr_b
56
+
57
VSHL_2sh 1111 001 0 1 . ...... .... 0101 . . . 1 .... @2reg_shl_d
58
VSHL_2sh 1111 001 0 1 . ...... .... 0101 . . . 1 .... @2reg_shl_s
59
VSHL_2sh 1111 001 0 1 . ...... .... 0101 . . . 1 .... @2reg_shl_h
60
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/translate-neon.inc.c
63
+++ b/target/arm/translate-neon.inc.c
64
@@ -XXX,XX +XXX,XX @@ static bool do_vector_2sh(DisasContext *s, arg_2reg_shift *a, GVecGen2iFn *fn)
65
66
DO_2SH(VSHL, tcg_gen_gvec_shli)
67
DO_2SH(VSLI, gen_gvec_sli)
68
+DO_2SH(VSRI, gen_gvec_sri)
69
+DO_2SH(VSRA_S, gen_gvec_ssra)
70
+DO_2SH(VSRA_U, gen_gvec_usra)
71
+DO_2SH(VRSHR_S, gen_gvec_srshr)
72
+DO_2SH(VRSHR_U, gen_gvec_urshr)
73
+DO_2SH(VRSRA_S, gen_gvec_srsra)
74
+DO_2SH(VRSRA_U, gen_gvec_ursra)
75
76
static bool trans_VSHR_S_2sh(DisasContext *s, arg_2reg_shift *a)
77
{
78
diff --git a/target/arm/translate.c b/target/arm/translate.c
79
index XXXXXXX..XXXXXXX 100644
80
--- a/target/arm/translate.c
81
+++ b/target/arm/translate.c
82
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
83
84
switch (op) {
85
case 0: /* VSHR */
86
+ case 1: /* VSRA */
87
+ case 2: /* VRSHR */
88
+ case 3: /* VRSRA */
89
+ case 4: /* VSRI */
90
case 5: /* VSHL, VSLI */
91
return 1; /* handled by decodetree */
92
default:
93
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
94
shift = shift - (1 << (size + 3));
95
}
96
97
- switch (op) {
98
- case 1: /* VSRA */
99
- /* Right shift comes here negative. */
100
- shift = -shift;
101
- if (u) {
102
- gen_gvec_usra(size, rd_ofs, rm_ofs, shift,
103
- vec_size, vec_size);
104
- } else {
105
- gen_gvec_ssra(size, rd_ofs, rm_ofs, shift,
106
- vec_size, vec_size);
107
- }
108
- return 0;
109
-
110
- case 2: /* VRSHR */
111
- /* Right shift comes here negative. */
112
- shift = -shift;
113
- if (u) {
114
- gen_gvec_urshr(size, rd_ofs, rm_ofs, shift,
115
- vec_size, vec_size);
116
- } else {
117
- gen_gvec_srshr(size, rd_ofs, rm_ofs, shift,
118
- vec_size, vec_size);
119
- }
120
- return 0;
121
-
122
- case 3: /* VRSRA */
123
- /* Right shift comes here negative. */
124
- shift = -shift;
125
- if (u) {
126
- gen_gvec_ursra(size, rd_ofs, rm_ofs, shift,
127
- vec_size, vec_size);
128
- } else {
129
- gen_gvec_srsra(size, rd_ofs, rm_ofs, shift,
130
- vec_size, vec_size);
131
- }
132
- return 0;
133
-
134
- case 4: /* VSRI */
135
- if (!u) {
136
- return 1;
137
- }
138
- /* Right shift comes here negative. */
139
- shift = -shift;
140
- gen_gvec_sri(size, rd_ofs, rm_ofs, shift,
141
- vec_size, vec_size);
142
- return 0;
143
- }
144
-
145
if (size == 3) {
146
count = q + 1;
147
} else {
148
--
149
2.20.1
150
151
diff view generated by jsdifflib
Deleted patch
1
Convert the VQSHLU and QVSHL 2-reg-shift insns to decodetree.
2
These are the last of the simple shift-by-immediate insns.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200522145520.6778-5-peter.maydell@linaro.org
7
---
8
target/arm/neon-dp.decode | 15 +++++
9
target/arm/translate-neon.inc.c | 108 +++++++++++++++++++++++++++++++
10
target/arm/translate.c | 110 +-------------------------------
11
3 files changed, 126 insertions(+), 107 deletions(-)
12
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
16
+++ b/target/arm/neon-dp.decode
17
@@ -XXX,XX +XXX,XX @@ VSLI_2sh 1111 001 1 1 . ...... .... 0101 . . . 1 .... @2reg_shl_d
18
VSLI_2sh 1111 001 1 1 . ...... .... 0101 . . . 1 .... @2reg_shl_s
19
VSLI_2sh 1111 001 1 1 . ...... .... 0101 . . . 1 .... @2reg_shl_h
20
VSLI_2sh 1111 001 1 1 . ...... .... 0101 . . . 1 .... @2reg_shl_b
21
+
22
+VQSHLU_64_2sh 1111 001 1 1 . ...... .... 0110 . . . 1 .... @2reg_shl_d
23
+VQSHLU_2sh 1111 001 1 1 . ...... .... 0110 . . . 1 .... @2reg_shl_s
24
+VQSHLU_2sh 1111 001 1 1 . ...... .... 0110 . . . 1 .... @2reg_shl_h
25
+VQSHLU_2sh 1111 001 1 1 . ...... .... 0110 . . . 1 .... @2reg_shl_b
26
+
27
+VQSHL_S_64_2sh 1111 001 0 1 . ...... .... 0111 . . . 1 .... @2reg_shl_d
28
+VQSHL_S_2sh 1111 001 0 1 . ...... .... 0111 . . . 1 .... @2reg_shl_s
29
+VQSHL_S_2sh 1111 001 0 1 . ...... .... 0111 . . . 1 .... @2reg_shl_h
30
+VQSHL_S_2sh 1111 001 0 1 . ...... .... 0111 . . . 1 .... @2reg_shl_b
31
+
32
+VQSHL_U_64_2sh 1111 001 1 1 . ...... .... 0111 . . . 1 .... @2reg_shl_d
33
+VQSHL_U_2sh 1111 001 1 1 . ...... .... 0111 . . . 1 .... @2reg_shl_s
34
+VQSHL_U_2sh 1111 001 1 1 . ...... .... 0111 . . . 1 .... @2reg_shl_h
35
+VQSHL_U_2sh 1111 001 1 1 . ...... .... 0111 . . . 1 .... @2reg_shl_b
36
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/translate-neon.inc.c
39
+++ b/target/arm/translate-neon.inc.c
40
@@ -XXX,XX +XXX,XX @@ static bool trans_VSHR_U_2sh(DisasContext *s, arg_2reg_shift *a)
41
return do_vector_2sh(s, a, tcg_gen_gvec_shri);
42
}
43
}
44
+
45
+static bool do_2shift_env_64(DisasContext *s, arg_2reg_shift *a,
46
+ NeonGenTwo64OpEnvFn *fn)
47
+{
48
+ /*
49
+ * 2-reg-and-shift operations, size == 3 case, where the
50
+ * function needs to be passed cpu_env.
51
+ */
52
+ TCGv_i64 constimm;
53
+ int pass;
54
+
55
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
56
+ return false;
57
+ }
58
+
59
+ /* UNDEF accesses to D16-D31 if they don't exist. */
60
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
61
+ ((a->vd | a->vm) & 0x10)) {
62
+ return false;
63
+ }
64
+
65
+ if ((a->vm | a->vd) & a->q) {
66
+ return false;
67
+ }
68
+
69
+ if (!vfp_access_check(s)) {
70
+ return true;
71
+ }
72
+
73
+ /*
74
+ * To avoid excessive duplication of ops we implement shift
75
+ * by immediate using the variable shift operations.
76
+ */
77
+ constimm = tcg_const_i64(dup_const(a->size, a->shift));
78
+
79
+ for (pass = 0; pass < a->q + 1; pass++) {
80
+ TCGv_i64 tmp = tcg_temp_new_i64();
81
+
82
+ neon_load_reg64(tmp, a->vm + pass);
83
+ fn(tmp, cpu_env, tmp, constimm);
84
+ neon_store_reg64(tmp, a->vd + pass);
85
+ }
86
+ tcg_temp_free_i64(constimm);
87
+ return true;
88
+}
89
+
90
+static bool do_2shift_env_32(DisasContext *s, arg_2reg_shift *a,
91
+ NeonGenTwoOpEnvFn *fn)
92
+{
93
+ /*
94
+ * 2-reg-and-shift operations, size < 3 case, where the
95
+ * helper needs to be passed cpu_env.
96
+ */
97
+ TCGv_i32 constimm;
98
+ int pass;
99
+
100
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
101
+ return false;
102
+ }
103
+
104
+ /* UNDEF accesses to D16-D31 if they don't exist. */
105
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
106
+ ((a->vd | a->vm) & 0x10)) {
107
+ return false;
108
+ }
109
+
110
+ if ((a->vm | a->vd) & a->q) {
111
+ return false;
112
+ }
113
+
114
+ if (!vfp_access_check(s)) {
115
+ return true;
116
+ }
117
+
118
+ /*
119
+ * To avoid excessive duplication of ops we implement shift
120
+ * by immediate using the variable shift operations.
121
+ */
122
+ constimm = tcg_const_i32(dup_const(a->size, a->shift));
123
+
124
+ for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
125
+ TCGv_i32 tmp = neon_load_reg(a->vm, pass);
126
+ fn(tmp, cpu_env, tmp, constimm);
127
+ neon_store_reg(a->vd, pass, tmp);
128
+ }
129
+ tcg_temp_free_i32(constimm);
130
+ return true;
131
+}
132
+
133
+#define DO_2SHIFT_ENV(INSN, FUNC) \
134
+ static bool trans_##INSN##_64_2sh(DisasContext *s, arg_2reg_shift *a) \
135
+ { \
136
+ return do_2shift_env_64(s, a, gen_helper_neon_##FUNC##64); \
137
+ } \
138
+ static bool trans_##INSN##_2sh(DisasContext *s, arg_2reg_shift *a) \
139
+ { \
140
+ static NeonGenTwoOpEnvFn * const fns[] = { \
141
+ gen_helper_neon_##FUNC##8, \
142
+ gen_helper_neon_##FUNC##16, \
143
+ gen_helper_neon_##FUNC##32, \
144
+ }; \
145
+ assert(a->size < ARRAY_SIZE(fns)); \
146
+ return do_2shift_env_32(s, a, fns[a->size]); \
147
+ }
148
+
149
+DO_2SHIFT_ENV(VQSHLU, qshlu_s)
150
+DO_2SHIFT_ENV(VQSHL_U, qshl_u)
151
+DO_2SHIFT_ENV(VQSHL_S, qshl_s)
152
diff --git a/target/arm/translate.c b/target/arm/translate.c
153
index XXXXXXX..XXXXXXX 100644
154
--- a/target/arm/translate.c
155
+++ b/target/arm/translate.c
156
@@ -XXX,XX +XXX,XX @@ static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
157
}
158
}
159
160
-#define GEN_NEON_INTEGER_OP_ENV(name) do { \
161
- switch ((size << 1) | u) { \
162
- case 0: \
163
- gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
164
- break; \
165
- case 1: \
166
- gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
167
- break; \
168
- case 2: \
169
- gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
170
- break; \
171
- case 3: \
172
- gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
173
- break; \
174
- case 4: \
175
- gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
176
- break; \
177
- case 5: \
178
- gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
179
- break; \
180
- default: return 1; \
181
- }} while (0)
182
-
183
static TCGv_i32 neon_load_scratch(int scratch)
184
{
185
TCGv_i32 tmp = tcg_temp_new_i32();
186
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
187
int size;
188
int shift;
189
int pass;
190
- int count;
191
int u;
192
int vec_size;
193
uint32_t imm;
194
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
195
case 3: /* VRSRA */
196
case 4: /* VSRI */
197
case 5: /* VSHL, VSLI */
198
+ case 6: /* VQSHLU */
199
+ case 7: /* VQSHL */
200
return 1; /* handled by decodetree */
201
default:
202
break;
203
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
204
size--;
205
}
206
shift = (insn >> 16) & ((1 << (3 + size)) - 1);
207
- if (op < 8) {
208
- /* Shift by immediate:
209
- VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
210
- if (q && ((rd | rm) & 1)) {
211
- return 1;
212
- }
213
- if (!u && (op == 4 || op == 6)) {
214
- return 1;
215
- }
216
- /* Right shifts are encoded as N - shift, where N is the
217
- element size in bits. */
218
- if (op <= 4) {
219
- shift = shift - (1 << (size + 3));
220
- }
221
-
222
- if (size == 3) {
223
- count = q + 1;
224
- } else {
225
- count = q ? 4: 2;
226
- }
227
-
228
- /* To avoid excessive duplication of ops we implement shift
229
- * by immediate using the variable shift operations.
230
- */
231
- imm = dup_const(size, shift);
232
-
233
- for (pass = 0; pass < count; pass++) {
234
- if (size == 3) {
235
- neon_load_reg64(cpu_V0, rm + pass);
236
- tcg_gen_movi_i64(cpu_V1, imm);
237
- switch (op) {
238
- case 6: /* VQSHLU */
239
- gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
240
- cpu_V0, cpu_V1);
241
- break;
242
- case 7: /* VQSHL */
243
- if (u) {
244
- gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
245
- cpu_V0, cpu_V1);
246
- } else {
247
- gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
248
- cpu_V0, cpu_V1);
249
- }
250
- break;
251
- default:
252
- g_assert_not_reached();
253
- }
254
- neon_store_reg64(cpu_V0, rd + pass);
255
- } else { /* size < 3 */
256
- /* Operands in T0 and T1. */
257
- tmp = neon_load_reg(rm, pass);
258
- tmp2 = tcg_temp_new_i32();
259
- tcg_gen_movi_i32(tmp2, imm);
260
- switch (op) {
261
- case 6: /* VQSHLU */
262
- switch (size) {
263
- case 0:
264
- gen_helper_neon_qshlu_s8(tmp, cpu_env,
265
- tmp, tmp2);
266
- break;
267
- case 1:
268
- gen_helper_neon_qshlu_s16(tmp, cpu_env,
269
- tmp, tmp2);
270
- break;
271
- case 2:
272
- gen_helper_neon_qshlu_s32(tmp, cpu_env,
273
- tmp, tmp2);
274
- break;
275
- default:
276
- abort();
277
- }
278
- break;
279
- case 7: /* VQSHL */
280
- GEN_NEON_INTEGER_OP_ENV(qshl);
281
- break;
282
- default:
283
- g_assert_not_reached();
284
- }
285
- tcg_temp_free_i32(tmp2);
286
- neon_store_reg(rd, pass, tmp);
287
- }
288
- } /* for pass */
289
- } else if (op < 10) {
290
+ if (op < 10) {
291
/* Shift by immediate and narrow:
292
VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
293
int input_unsigned = (op == 8) ? !u : u;
294
--
295
2.20.1
296
297
diff view generated by jsdifflib