1*214652daSArnaud Minier /*
2*214652daSArnaud Minier  * QTest testcase for STML4X5_USART
3*214652daSArnaud Minier  *
4*214652daSArnaud Minier  * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
5*214652daSArnaud Minier  * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
6*214652daSArnaud Minier  *
7*214652daSArnaud Minier  * This work is licensed under the terms of the GNU GPL, version 2 or later.
8*214652daSArnaud Minier  * See the COPYING file in the top-level directory.
9*214652daSArnaud Minier  */
10*214652daSArnaud Minier 
11*214652daSArnaud Minier #include "qemu/osdep.h"
12*214652daSArnaud Minier #include "libqtest.h"
13*214652daSArnaud Minier #include "hw/misc/stm32l4x5_rcc_internals.h"
14*214652daSArnaud Minier #include "hw/registerfields.h"
15*214652daSArnaud Minier 
16*214652daSArnaud Minier #define RCC_BASE_ADDR 0x40021000
17*214652daSArnaud Minier /* Use USART 1 ADDR, assume the others work the same */
18*214652daSArnaud Minier #define USART1_BASE_ADDR 0x40013800
19*214652daSArnaud Minier 
20*214652daSArnaud Minier /* See stm32l4x5_usart for definitions */
21*214652daSArnaud Minier REG32(CR1, 0x00)
22*214652daSArnaud Minier     FIELD(CR1, M1, 28, 1)
23*214652daSArnaud Minier     FIELD(CR1, OVER8, 15, 1)
24*214652daSArnaud Minier     FIELD(CR1, M0, 12, 1)
25*214652daSArnaud Minier     FIELD(CR1, PCE, 10, 1)
26*214652daSArnaud Minier     FIELD(CR1, TXEIE, 7, 1)
27*214652daSArnaud Minier     FIELD(CR1, RXNEIE, 5, 1)
28*214652daSArnaud Minier     FIELD(CR1, TE, 3, 1)
29*214652daSArnaud Minier     FIELD(CR1, RE, 2, 1)
30*214652daSArnaud Minier     FIELD(CR1, UE, 0, 1)
31*214652daSArnaud Minier REG32(CR2, 0x04)
32*214652daSArnaud Minier REG32(CR3, 0x08)
33*214652daSArnaud Minier     FIELD(CR3, OVRDIS, 12, 1)
34*214652daSArnaud Minier REG32(BRR, 0x0C)
35*214652daSArnaud Minier REG32(GTPR, 0x10)
36*214652daSArnaud Minier REG32(RTOR, 0x14)
37*214652daSArnaud Minier REG32(RQR, 0x18)
38*214652daSArnaud Minier REG32(ISR, 0x1C)
39*214652daSArnaud Minier     FIELD(ISR, TXE, 7, 1)
40*214652daSArnaud Minier     FIELD(ISR, RXNE, 5, 1)
41*214652daSArnaud Minier     FIELD(ISR, ORE, 3, 1)
42*214652daSArnaud Minier REG32(ICR, 0x20)
43*214652daSArnaud Minier REG32(RDR, 0x24)
44*214652daSArnaud Minier REG32(TDR, 0x28)
45*214652daSArnaud Minier 
46*214652daSArnaud Minier #define NVIC_ISPR1 0XE000E204
47*214652daSArnaud Minier #define NVIC_ICPR1 0xE000E284
48*214652daSArnaud Minier #define USART1_IRQ 37
49*214652daSArnaud Minier 
check_nvic_pending(QTestState * qts,unsigned int n)50*214652daSArnaud Minier static bool check_nvic_pending(QTestState *qts, unsigned int n)
51*214652daSArnaud Minier {
52*214652daSArnaud Minier     /* No USART interrupts are less than 32 */
53*214652daSArnaud Minier     assert(n > 32);
54*214652daSArnaud Minier     n -= 32;
55*214652daSArnaud Minier     return qtest_readl(qts, NVIC_ISPR1) & (1 << n);
56*214652daSArnaud Minier }
57*214652daSArnaud Minier 
clear_nvic_pending(QTestState * qts,unsigned int n)58*214652daSArnaud Minier static bool clear_nvic_pending(QTestState *qts, unsigned int n)
59*214652daSArnaud Minier {
60*214652daSArnaud Minier     /* No USART interrupts are less than 32 */
61*214652daSArnaud Minier     assert(n > 32);
62*214652daSArnaud Minier     n -= 32;
63*214652daSArnaud Minier     qtest_writel(qts, NVIC_ICPR1, (1 << n));
64*214652daSArnaud Minier     return true;
65*214652daSArnaud Minier }
66*214652daSArnaud Minier 
67*214652daSArnaud Minier /*
68*214652daSArnaud Minier  * Wait indefinitely for the flag to be updated.
69*214652daSArnaud Minier  * If this is run on a slow CI runner,
70*214652daSArnaud Minier  * the meson harness will timeout after 10 minutes for us.
71*214652daSArnaud Minier  */
usart_wait_for_flag(QTestState * qts,uint32_t event_addr,uint32_t flag)72*214652daSArnaud Minier static bool usart_wait_for_flag(QTestState *qts, uint32_t event_addr,
73*214652daSArnaud Minier                                 uint32_t flag)
74*214652daSArnaud Minier {
75*214652daSArnaud Minier     while (true) {
76*214652daSArnaud Minier         if ((qtest_readl(qts, event_addr) & flag)) {
77*214652daSArnaud Minier             return true;
78*214652daSArnaud Minier         }
79*214652daSArnaud Minier         g_usleep(1000);
80*214652daSArnaud Minier     }
81*214652daSArnaud Minier 
82*214652daSArnaud Minier     return false;
83*214652daSArnaud Minier }
84*214652daSArnaud Minier 
usart_receive_string(QTestState * qts,int sock_fd,const char * in,char * out)85*214652daSArnaud Minier static void usart_receive_string(QTestState *qts, int sock_fd, const char *in,
86*214652daSArnaud Minier                                  char *out)
87*214652daSArnaud Minier {
88*214652daSArnaud Minier     int i, in_len = strlen(in);
89*214652daSArnaud Minier 
90*214652daSArnaud Minier     g_assert_true(send(sock_fd, in, in_len, 0) == in_len);
91*214652daSArnaud Minier     for (i = 0; i < in_len; i++) {
92*214652daSArnaud Minier         g_assert_true(usart_wait_for_flag(qts,
93*214652daSArnaud Minier             USART1_BASE_ADDR + A_ISR, R_ISR_RXNE_MASK));
94*214652daSArnaud Minier         out[i] = qtest_readl(qts, USART1_BASE_ADDR + A_RDR);
95*214652daSArnaud Minier     }
96*214652daSArnaud Minier     out[i] = '\0';
97*214652daSArnaud Minier }
98*214652daSArnaud Minier 
usart_send_string(QTestState * qts,const char * in)99*214652daSArnaud Minier static void usart_send_string(QTestState *qts, const char *in)
100*214652daSArnaud Minier {
101*214652daSArnaud Minier     int i, in_len = strlen(in);
102*214652daSArnaud Minier 
103*214652daSArnaud Minier     for (i = 0; i < in_len; i++) {
104*214652daSArnaud Minier         qtest_writel(qts, USART1_BASE_ADDR + A_TDR, in[i]);
105*214652daSArnaud Minier         g_assert_true(usart_wait_for_flag(qts,
106*214652daSArnaud Minier             USART1_BASE_ADDR + A_ISR, R_ISR_TXE_MASK));
107*214652daSArnaud Minier     }
108*214652daSArnaud Minier }
109*214652daSArnaud Minier 
110*214652daSArnaud Minier /* Init the RCC clocks to run at 80 MHz */
init_clocks(QTestState * qts)111*214652daSArnaud Minier static void init_clocks(QTestState *qts)
112*214652daSArnaud Minier {
113*214652daSArnaud Minier     uint32_t value;
114*214652daSArnaud Minier 
115*214652daSArnaud Minier     /* MSIRANGE can be set only when MSI is OFF or READY */
116*214652daSArnaud Minier     qtest_writel(qts, (RCC_BASE_ADDR + A_CR), R_CR_MSION_MASK);
117*214652daSArnaud Minier 
118*214652daSArnaud Minier     /* Clocking from MSI, in case MSI was not the default source */
119*214652daSArnaud Minier     qtest_writel(qts, (RCC_BASE_ADDR + A_CFGR), 0);
120*214652daSArnaud Minier 
121*214652daSArnaud Minier     /*
122*214652daSArnaud Minier      * Update PLL and set MSI as the source clock.
123*214652daSArnaud Minier      * PLLM = 1 --> 000
124*214652daSArnaud Minier      * PLLN = 40 --> 40
125*214652daSArnaud Minier      * PPLLR = 2 --> 00
126*214652daSArnaud Minier      * PLLDIV = unused, PLLP = unused (SAI3), PLLQ = unused (48M1)
127*214652daSArnaud Minier      * SRC = MSI --> 01
128*214652daSArnaud Minier      */
129*214652daSArnaud Minier     qtest_writel(qts, (RCC_BASE_ADDR + A_PLLCFGR), R_PLLCFGR_PLLREN_MASK |
130*214652daSArnaud Minier             (40 << R_PLLCFGR_PLLN_SHIFT) |
131*214652daSArnaud Minier             (0b01 << R_PLLCFGR_PLLSRC_SHIFT));
132*214652daSArnaud Minier 
133*214652daSArnaud Minier     /* PLL activation */
134*214652daSArnaud Minier 
135*214652daSArnaud Minier     value = qtest_readl(qts, (RCC_BASE_ADDR + A_CR));
136*214652daSArnaud Minier     qtest_writel(qts, (RCC_BASE_ADDR + A_CR), value | R_CR_PLLON_MASK);
137*214652daSArnaud Minier 
138*214652daSArnaud Minier     /* RCC_CFGR is OK by defaut */
139*214652daSArnaud Minier     qtest_writel(qts, (RCC_BASE_ADDR + A_CFGR), 0);
140*214652daSArnaud Minier 
141*214652daSArnaud Minier     /* CCIPR : no periph clock by default */
142*214652daSArnaud Minier     qtest_writel(qts, (RCC_BASE_ADDR + A_CCIPR), 0);
143*214652daSArnaud Minier 
144*214652daSArnaud Minier     /* Switches on the PLL clock source */
145*214652daSArnaud Minier     value = qtest_readl(qts, (RCC_BASE_ADDR + A_CFGR));
146*214652daSArnaud Minier     qtest_writel(qts, (RCC_BASE_ADDR + A_CFGR), (value & ~R_CFGR_SW_MASK) |
147*214652daSArnaud Minier         (0b11 << R_CFGR_SW_SHIFT));
148*214652daSArnaud Minier 
149*214652daSArnaud Minier     /* Enable SYSCFG clock enabled */
150*214652daSArnaud Minier     qtest_writel(qts, (RCC_BASE_ADDR + A_APB2ENR), R_APB2ENR_SYSCFGEN_MASK);
151*214652daSArnaud Minier 
152*214652daSArnaud Minier     /* Enable the IO port B clock (See p.252) */
153*214652daSArnaud Minier     qtest_writel(qts, (RCC_BASE_ADDR + A_AHB2ENR), R_AHB2ENR_GPIOBEN_MASK);
154*214652daSArnaud Minier 
155*214652daSArnaud Minier     /* Enable the clock for USART1 (cf p.259) */
156*214652daSArnaud Minier     /* We rewrite SYSCFGEN to not disable it */
157*214652daSArnaud Minier     qtest_writel(qts, (RCC_BASE_ADDR + A_APB2ENR),
158*214652daSArnaud Minier                  R_APB2ENR_SYSCFGEN_MASK | R_APB2ENR_USART1EN_MASK);
159*214652daSArnaud Minier 
160*214652daSArnaud Minier     /* TODO: Enable usart via gpio */
161*214652daSArnaud Minier 
162*214652daSArnaud Minier     /* Set PCLK as the clock for USART1(cf p.272) i.e. reset both bits */
163*214652daSArnaud Minier     qtest_writel(qts, (RCC_BASE_ADDR + A_CCIPR), 0);
164*214652daSArnaud Minier 
165*214652daSArnaud Minier     /* Reset USART1 (see p.249) */
166*214652daSArnaud Minier     qtest_writel(qts, (RCC_BASE_ADDR + A_APB2RSTR), 1 << 14);
167*214652daSArnaud Minier     qtest_writel(qts, (RCC_BASE_ADDR + A_APB2RSTR), 0);
168*214652daSArnaud Minier }
169*214652daSArnaud Minier 
init_uart(QTestState * qts)170*214652daSArnaud Minier static void init_uart(QTestState *qts)
171*214652daSArnaud Minier {
172*214652daSArnaud Minier     uint32_t cr1;
173*214652daSArnaud Minier 
174*214652daSArnaud Minier     init_clocks(qts);
175*214652daSArnaud Minier 
176*214652daSArnaud Minier     /*
177*214652daSArnaud Minier      * For 115200 bauds, see p.1349.
178*214652daSArnaud Minier      * The clock has a frequency of 80Mhz,
179*214652daSArnaud Minier      * for 115200, we have to put a divider of 695 = 0x2B7.
180*214652daSArnaud Minier      */
181*214652daSArnaud Minier     qtest_writel(qts, (USART1_BASE_ADDR + A_BRR), 0x2B7);
182*214652daSArnaud Minier 
183*214652daSArnaud Minier     /*
184*214652daSArnaud Minier      * Set the oversampling by 16,
185*214652daSArnaud Minier      * disable the parity control and
186*214652daSArnaud Minier      * set the word length to 8. (cf p.1377)
187*214652daSArnaud Minier      */
188*214652daSArnaud Minier     cr1 = qtest_readl(qts, (USART1_BASE_ADDR + A_CR1));
189*214652daSArnaud Minier     cr1 &= ~(R_CR1_M1_MASK | R_CR1_M0_MASK | R_CR1_OVER8_MASK | R_CR1_PCE_MASK);
190*214652daSArnaud Minier     qtest_writel(qts, (USART1_BASE_ADDR + A_CR1), cr1);
191*214652daSArnaud Minier 
192*214652daSArnaud Minier     /* Enable the transmitter, the receiver and the USART. */
193*214652daSArnaud Minier     qtest_writel(qts, (USART1_BASE_ADDR + A_CR1),
194*214652daSArnaud Minier         R_CR1_UE_MASK | R_CR1_RE_MASK | R_CR1_TE_MASK);
195*214652daSArnaud Minier }
196*214652daSArnaud Minier 
test_write_read(void)197*214652daSArnaud Minier static void test_write_read(void)
198*214652daSArnaud Minier {
199*214652daSArnaud Minier     QTestState *qts = qtest_init("-M b-l475e-iot01a");
200*214652daSArnaud Minier 
201*214652daSArnaud Minier     /* Test that we can write and retrieve a value from the device */
202*214652daSArnaud Minier     qtest_writel(qts, USART1_BASE_ADDR + A_TDR, 0xFFFFFFFF);
203*214652daSArnaud Minier     const uint32_t tdr = qtest_readl(qts, USART1_BASE_ADDR + A_TDR);
204*214652daSArnaud Minier     g_assert_cmpuint(tdr, ==, 0x000001FF);
205*214652daSArnaud Minier }
206*214652daSArnaud Minier 
test_receive_char(void)207*214652daSArnaud Minier static void test_receive_char(void)
208*214652daSArnaud Minier {
209*214652daSArnaud Minier     int sock_fd;
210*214652daSArnaud Minier     uint32_t cr1;
211*214652daSArnaud Minier     QTestState *qts = qtest_init_with_serial("-M b-l475e-iot01a", &sock_fd);
212*214652daSArnaud Minier 
213*214652daSArnaud Minier     init_uart(qts);
214*214652daSArnaud Minier 
215*214652daSArnaud Minier     /* Try without initializing IRQ */
216*214652daSArnaud Minier     g_assert_true(send(sock_fd, "a", 1, 0) == 1);
217*214652daSArnaud Minier     usart_wait_for_flag(qts, USART1_BASE_ADDR + A_ISR, R_ISR_RXNE_MASK);
218*214652daSArnaud Minier     g_assert_cmphex(qtest_readl(qts, USART1_BASE_ADDR + A_RDR), ==, 'a');
219*214652daSArnaud Minier     g_assert_false(check_nvic_pending(qts, USART1_IRQ));
220*214652daSArnaud Minier 
221*214652daSArnaud Minier     /* Now with the IRQ */
222*214652daSArnaud Minier     cr1 = qtest_readl(qts, (USART1_BASE_ADDR + A_CR1));
223*214652daSArnaud Minier     cr1 |= R_CR1_RXNEIE_MASK;
224*214652daSArnaud Minier     qtest_writel(qts, USART1_BASE_ADDR + A_CR1, cr1);
225*214652daSArnaud Minier     g_assert_true(send(sock_fd, "b", 1, 0) == 1);
226*214652daSArnaud Minier     usart_wait_for_flag(qts, USART1_BASE_ADDR + A_ISR, R_ISR_RXNE_MASK);
227*214652daSArnaud Minier     g_assert_cmphex(qtest_readl(qts, USART1_BASE_ADDR + A_RDR), ==, 'b');
228*214652daSArnaud Minier     g_assert_true(check_nvic_pending(qts, USART1_IRQ));
229*214652daSArnaud Minier     clear_nvic_pending(qts, USART1_IRQ);
230*214652daSArnaud Minier 
231*214652daSArnaud Minier     close(sock_fd);
232*214652daSArnaud Minier 
233*214652daSArnaud Minier     qtest_quit(qts);
234*214652daSArnaud Minier }
235*214652daSArnaud Minier 
test_send_char(void)236*214652daSArnaud Minier static void test_send_char(void)
237*214652daSArnaud Minier {
238*214652daSArnaud Minier     int sock_fd;
239*214652daSArnaud Minier     char s[1];
240*214652daSArnaud Minier     uint32_t cr1;
241*214652daSArnaud Minier     QTestState *qts = qtest_init_with_serial("-M b-l475e-iot01a", &sock_fd);
242*214652daSArnaud Minier 
243*214652daSArnaud Minier     init_uart(qts);
244*214652daSArnaud Minier 
245*214652daSArnaud Minier     /* Try without initializing IRQ */
246*214652daSArnaud Minier     qtest_writel(qts, USART1_BASE_ADDR + A_TDR, 'c');
247*214652daSArnaud Minier     g_assert_true(recv(sock_fd, s, 1, 0) == 1);
248*214652daSArnaud Minier     g_assert_cmphex(s[0], ==, 'c');
249*214652daSArnaud Minier     g_assert_false(check_nvic_pending(qts, USART1_IRQ));
250*214652daSArnaud Minier 
251*214652daSArnaud Minier     /* Now with the IRQ */
252*214652daSArnaud Minier     cr1 = qtest_readl(qts, (USART1_BASE_ADDR + A_CR1));
253*214652daSArnaud Minier     cr1 |= R_CR1_TXEIE_MASK;
254*214652daSArnaud Minier     qtest_writel(qts, USART1_BASE_ADDR + A_CR1, cr1);
255*214652daSArnaud Minier     qtest_writel(qts, USART1_BASE_ADDR + A_TDR, 'd');
256*214652daSArnaud Minier     g_assert_true(recv(sock_fd, s, 1, 0) == 1);
257*214652daSArnaud Minier     g_assert_cmphex(s[0], ==, 'd');
258*214652daSArnaud Minier     g_assert_true(check_nvic_pending(qts, USART1_IRQ));
259*214652daSArnaud Minier     clear_nvic_pending(qts, USART1_IRQ);
260*214652daSArnaud Minier 
261*214652daSArnaud Minier     close(sock_fd);
262*214652daSArnaud Minier 
263*214652daSArnaud Minier     qtest_quit(qts);
264*214652daSArnaud Minier }
265*214652daSArnaud Minier 
test_receive_str(void)266*214652daSArnaud Minier static void test_receive_str(void)
267*214652daSArnaud Minier {
268*214652daSArnaud Minier     int sock_fd;
269*214652daSArnaud Minier     char s[10];
270*214652daSArnaud Minier     QTestState *qts = qtest_init_with_serial("-M b-l475e-iot01a", &sock_fd);
271*214652daSArnaud Minier 
272*214652daSArnaud Minier     init_uart(qts);
273*214652daSArnaud Minier 
274*214652daSArnaud Minier     usart_receive_string(qts, sock_fd, "hello", s);
275*214652daSArnaud Minier     g_assert_true(memcmp(s, "hello", 5) == 0);
276*214652daSArnaud Minier 
277*214652daSArnaud Minier     close(sock_fd);
278*214652daSArnaud Minier 
279*214652daSArnaud Minier     qtest_quit(qts);
280*214652daSArnaud Minier }
281*214652daSArnaud Minier 
test_send_str(void)282*214652daSArnaud Minier static void test_send_str(void)
283*214652daSArnaud Minier {
284*214652daSArnaud Minier     int sock_fd;
285*214652daSArnaud Minier     char s[10];
286*214652daSArnaud Minier     QTestState *qts = qtest_init_with_serial("-M b-l475e-iot01a", &sock_fd);
287*214652daSArnaud Minier 
288*214652daSArnaud Minier     init_uart(qts);
289*214652daSArnaud Minier 
290*214652daSArnaud Minier     usart_send_string(qts, "world");
291*214652daSArnaud Minier     g_assert_true(recv(sock_fd, s, 10, 0) == 5);
292*214652daSArnaud Minier     g_assert_true(memcmp(s, "world", 5) == 0);
293*214652daSArnaud Minier 
294*214652daSArnaud Minier     close(sock_fd);
295*214652daSArnaud Minier 
296*214652daSArnaud Minier     qtest_quit(qts);
297*214652daSArnaud Minier }
298*214652daSArnaud Minier 
main(int argc,char ** argv)299*214652daSArnaud Minier int main(int argc, char **argv)
300*214652daSArnaud Minier {
301*214652daSArnaud Minier     int ret;
302*214652daSArnaud Minier 
303*214652daSArnaud Minier     g_test_init(&argc, &argv, NULL);
304*214652daSArnaud Minier     g_test_set_nonfatal_assertions();
305*214652daSArnaud Minier 
306*214652daSArnaud Minier     qtest_add_func("stm32l4x5/usart/write_read", test_write_read);
307*214652daSArnaud Minier     qtest_add_func("stm32l4x5/usart/receive_char", test_receive_char);
308*214652daSArnaud Minier     qtest_add_func("stm32l4x5/usart/send_char", test_send_char);
309*214652daSArnaud Minier     qtest_add_func("stm32l4x5/usart/receive_str", test_receive_str);
310*214652daSArnaud Minier     qtest_add_func("stm32l4x5/usart/send_str", test_send_str);
311*214652daSArnaud Minier     ret = g_test_run();
312*214652daSArnaud Minier 
313*214652daSArnaud Minier     return ret;
314*214652daSArnaud Minier }
315*214652daSArnaud Minier 
316