master
c 226 lines 7.74 KB
Raw
1 /*
2 * QTest testcase for the K230 DDR controller and PHY
3 *
4 * Exercises register access, reset, PHY ownership, training mailbox, and DFI
5 * initialization.
6 *
7 * Copyright (c) 2026 Junze Cao <caojunze424@gmail.com>
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
12 #include "qemu/osdep.h"
13 #include "libqtest.h"
14
15 #define K230_DDRC_BASE UINT64_C(0x98000000)
16 #define K230_DDR_PHY_BASE UINT64_C(0x9a000000)
17
18 #define K230_DDRC_MSTR 0x000
19 #define K230_DDRC_STAT 0x004
20 #define K230_DDRC_DRAMTMG4 0x110
21 #define K230_DDRC_DFIMISC 0x1b0
22 #define K230_DDRC_DFISTAT 0x1bc
23 #define K230_DDRC_SWCTL 0x320
24 #define K230_DDRC_SWSTAT 0x324
25
26 #define K230_DDRC_STAT_OPERATING_MODE_MASK 0x7
27 #define K230_DDRC_DFISTAT_DFI_INIT_COMPLETE_MASK 0x1
28
29 #define K230_DDR_PHY_CSR(index) \
30 (K230_DDR_PHY_BASE + (uint64_t)(index) * sizeof(uint32_t))
31
32 #define K230_DDR_PHY_ATX_IMPEDANCE 0x00043
33 #define K230_DDR_PHY_TX_IMPEDANCE_CTRL1 0x10049
34 #define K230_DDR_PHY_VREF_IN_GLOBAL 0x200b2
35 #define K230_DDR_PHY_MICRO_CONT_MUX_SEL 0xd0000
36 #define K230_DDR_PHY_TRAINING_STATUS 0xd0004
37 #define K230_DDR_PHY_TRAINING_ACK 0xd0031
38 #define K230_DDR_PHY_TRAINING_MESSAGE 0xd0032
39 #define K230_DDR_PHY_TRAINING_TRIGGER 0xd0099
40
41 static void complete_phy_training(QTestState *qts)
42 {
43 qtest_writel(qts,
44 K230_DDR_PHY_CSR(K230_DDR_PHY_MICRO_CONT_MUX_SEL), 1);
45 qtest_writel(qts, K230_DDR_PHY_CSR(K230_DDR_PHY_TRAINING_TRIGGER), 9);
46 qtest_writel(qts, K230_DDR_PHY_CSR(K230_DDR_PHY_TRAINING_TRIGGER), 1);
47 qtest_writel(qts, K230_DDR_PHY_CSR(K230_DDR_PHY_TRAINING_TRIGGER), 0);
48 }
49
50 static void test_reset_and_register_access(void)
51 {
52 QTestState *qts = qtest_init("-machine k230");
53
54 g_assert_cmphex(qtest_readl(qts, K230_DDRC_BASE + K230_DDRC_MSTR),
55 ==, 0x01040000);
56 g_assert_cmphex(qtest_readl(qts, K230_DDRC_BASE + K230_DDRC_STAT),
57 ==, 0x00000000);
58 g_assert_cmphex(qtest_readl(qts, K230_DDRC_BASE + K230_DDRC_DRAMTMG4),
59 ==, 0x05040405);
60 g_assert_cmphex(qtest_readl(qts, K230_DDRC_BASE + K230_DDRC_DFIMISC),
61 ==, 0x00000001);
62 g_assert_cmphex(qtest_readl(qts, K230_DDRC_BASE + K230_DDRC_SWCTL),
63 ==, 0x00000001);
64 g_assert_cmphex(qtest_readl(qts, K230_DDRC_BASE + K230_DDRC_SWSTAT),
65 ==, 0x00000001);
66
67 g_assert_cmphex(qtest_readl(qts,
68 K230_DDR_PHY_CSR(K230_DDR_PHY_ATX_IMPEDANCE)),
69 ==, 0x03ff);
70 g_assert_cmphex(qtest_readl(qts,
71 K230_DDR_PHY_CSR(K230_DDR_PHY_TX_IMPEDANCE_CTRL1)),
72 ==, 0x0fff);
73 g_assert_cmphex(qtest_readl(qts,
74 K230_DDR_PHY_CSR(K230_DDR_PHY_VREF_IN_GLOBAL)),
75 ==, 0x0200);
76
77 qtest_writel(qts, K230_DDRC_BASE + K230_DDRC_MSTR, 0x01040008);
78 g_assert_cmphex(qtest_readl(qts, K230_DDRC_BASE + K230_DDRC_MSTR),
79 ==, 0x01040008);
80
81 qtest_writel(qts, K230_DDRC_BASE + K230_DDRC_STAT, 0xffffffff);
82 g_assert_cmphex(qtest_readl(qts, K230_DDRC_BASE + K230_DDRC_STAT),
83 ==, 0x00000000);
84
85 qtest_writel(qts, K230_DDR_PHY_CSR(K230_DDR_PHY_VREF_IN_GLOBAL),
86 0xffffffff);
87 g_assert_cmphex(qtest_readl(qts,
88 K230_DDR_PHY_CSR(K230_DDR_PHY_VREF_IN_GLOBAL)),
89 ==, 0x7fff);
90
91 qtest_writel(qts, K230_DDRC_BASE + K230_DDRC_DRAMTMG4, 0);
92
93 qtest_system_reset(qts);
94 g_assert_cmphex(qtest_readl(qts, K230_DDRC_BASE + K230_DDRC_MSTR),
95 ==, 0x01040000);
96 g_assert_cmphex(qtest_readl(qts, K230_DDRC_BASE + K230_DDRC_DRAMTMG4),
97 ==, 0x05040405);
98 g_assert_cmphex(qtest_readl(qts,
99 K230_DDR_PHY_CSR(K230_DDR_PHY_VREF_IN_GLOBAL)),
100 ==, 0x0200);
101
102 qtest_quit(qts);
103 }
104
105 static void test_software_update_handshake(void)
106 {
107 QTestState *qts = qtest_init("-machine k230");
108
109 qtest_writel(qts, K230_DDRC_BASE + K230_DDRC_SWCTL, 0);
110 g_assert_cmphex(qtest_readl(qts, K230_DDRC_BASE + K230_DDRC_SWSTAT),
111 ==, 0);
112
113 qtest_writel(qts, K230_DDRC_BASE + K230_DDRC_SWCTL, 1);
114 g_assert_cmphex(qtest_readl(qts, K230_DDRC_BASE + K230_DDRC_SWSTAT),
115 ==, 1);
116
117 qtest_writel(qts, K230_DDRC_BASE + K230_DDRC_SWSTAT, 0);
118 g_assert_cmphex(qtest_readl(qts, K230_DDRC_BASE + K230_DDRC_SWSTAT),
119 ==, 1);
120
121 qtest_quit(qts);
122 }
123
124 static void test_phy_ownership(void)
125 {
126 QTestState *qts = qtest_init("-machine k230");
127 uint64_t atx = K230_DDR_PHY_CSR(K230_DDR_PHY_ATX_IMPEDANCE);
128 uint64_t mux = K230_DDR_PHY_CSR(K230_DDR_PHY_MICRO_CONT_MUX_SEL);
129
130 qtest_writel(qts, atx, 0x155);
131 g_assert_cmphex(qtest_readl(qts, atx), ==, 0x155);
132
133 qtest_writel(qts, mux, 1);
134 qtest_writel(qts, atx, 0x2aa);
135 g_assert_cmphex(qtest_readl(qts, atx), ==, 0x155);
136
137 qtest_writel(qts, mux, 0);
138 qtest_writel(qts, atx, 0x2aa);
139 g_assert_cmphex(qtest_readl(qts, atx), ==, 0x2aa);
140
141 qtest_quit(qts);
142 }
143
144 static void test_dfi_prerequisites(void)
145 {
146 QTestState *qts = qtest_init("-machine k230");
147
148 qtest_writel(qts, K230_DDRC_BASE + K230_DDRC_DFIMISC, 0x20);
149
150 g_assert_cmphex(qtest_readl(qts,
151 K230_DDRC_BASE + K230_DDRC_DFISTAT) &
152 K230_DDRC_DFISTAT_DFI_INIT_COMPLETE_MASK,
153 ==, 0);
154 g_assert_cmphex(qtest_readl(qts, K230_DDRC_BASE + K230_DDRC_STAT) &
155 K230_DDRC_STAT_OPERATING_MODE_MASK,
156 ==, 0);
157
158 qtest_quit(qts);
159 }
160
161 static void test_dfi_complete_enable(void)
162 {
163 QTestState *qts = qtest_init("-machine k230");
164
165 complete_phy_training(qts);
166 qtest_writel(qts, K230_DDRC_BASE + K230_DDRC_DFIMISC, 0x20);
167
168 g_assert_cmphex(qtest_readl(qts,
169 K230_DDRC_BASE + K230_DDRC_DFISTAT) &
170 K230_DDRC_DFISTAT_DFI_INIT_COMPLETE_MASK,
171 ==, 1);
172 g_assert_cmphex(qtest_readl(qts, K230_DDRC_BASE + K230_DDRC_STAT) &
173 K230_DDRC_STAT_OPERATING_MODE_MASK,
174 ==, 0);
175
176 qtest_quit(qts);
177 }
178
179 static void test_training_and_dfi_handshake(void)
180 {
181 QTestState *qts = qtest_init("-machine k230");
182
183 complete_phy_training(qts);
184
185 g_assert_cmphex(qtest_readl(qts,
186 K230_DDR_PHY_CSR(K230_DDR_PHY_TRAINING_STATUS)),
187 ==, 0);
188 g_assert_cmphex(qtest_readl(qts,
189 K230_DDR_PHY_CSR(K230_DDR_PHY_TRAINING_MESSAGE)),
190 ==, 0x07);
191
192 qtest_writel(qts, K230_DDR_PHY_CSR(K230_DDR_PHY_TRAINING_ACK), 0);
193 g_assert_cmphex(qtest_readl(qts,
194 K230_DDR_PHY_CSR(K230_DDR_PHY_TRAINING_STATUS)),
195 ==, 1);
196 qtest_writel(qts, K230_DDR_PHY_CSR(K230_DDR_PHY_TRAINING_ACK), 1);
197
198 qtest_writel(qts, K230_DDRC_BASE + K230_DDRC_DFIMISC, 0x20);
199 g_assert_cmphex(qtest_readl(qts, K230_DDRC_BASE + K230_DDRC_DFISTAT),
200 ==, 1);
201
202 qtest_writel(qts, K230_DDRC_BASE + K230_DDRC_DFIMISC, 0);
203 qtest_writel(qts, K230_DDRC_BASE + K230_DDRC_DFIMISC, 1);
204 g_assert_cmphex(qtest_readl(qts, K230_DDRC_BASE + K230_DDRC_STAT) & 0x7,
205 ==, 1);
206
207 qtest_quit(qts);
208 }
209
210 int main(int argc, char **argv)
211 {
212 g_test_init(&argc, &argv, NULL);
213
214 qtest_add_func("/k230-ddr/reset-and-register-access",
215 test_reset_and_register_access);
216 qtest_add_func("/k230-ddr/software-update-handshake",
217 test_software_update_handshake);
218 qtest_add_func("/k230-ddr/phy-ownership", test_phy_ownership);
219 qtest_add_func("/k230-ddr/dfi-prerequisites", test_dfi_prerequisites);
220 qtest_add_func("/k230-ddr/dfi-complete-enable",
221 test_dfi_complete_enable);
222 qtest_add_func("/k230-ddr/training-and-dfi-handshake",
223 test_training_and_dfi_handshake);
224
225 return g_test_run();
226 }