xref: /qemu/tests/qtest/microbit-test.c (revision 17ff8e18cc1a160737d72a0bf3dac2f6372524ea)
1*17ff8e18SSteffen Görtz /*
2*17ff8e18SSteffen Görtz  * QTest testcase for Microbit board using the Nordic Semiconductor nRF51 SoC.
3*17ff8e18SSteffen Görtz  *
4*17ff8e18SSteffen Görtz  * nRF51:
5*17ff8e18SSteffen Görtz  * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
6*17ff8e18SSteffen Görtz  * Product Spec: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.1.pdf
7*17ff8e18SSteffen Görtz  *
8*17ff8e18SSteffen Görtz  * Microbit Board: http://microbit.org/
9*17ff8e18SSteffen Görtz  *
10*17ff8e18SSteffen Görtz  * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
11*17ff8e18SSteffen Görtz  *
12*17ff8e18SSteffen Görtz  * This code is licensed under the GPL version 2 or later.  See
13*17ff8e18SSteffen Görtz  * the COPYING file in the top-level directory.
14*17ff8e18SSteffen Görtz  */
15*17ff8e18SSteffen Görtz 
16*17ff8e18SSteffen Görtz 
17*17ff8e18SSteffen Görtz #include "qemu/osdep.h"
18*17ff8e18SSteffen Görtz #include "exec/hwaddr.h"
19*17ff8e18SSteffen Görtz #include "libqtest.h"
20*17ff8e18SSteffen Görtz 
21*17ff8e18SSteffen Görtz #include "hw/arm/nrf51.h"
22*17ff8e18SSteffen Görtz #include "hw/gpio/nrf51_gpio.h"
23*17ff8e18SSteffen Görtz 
24*17ff8e18SSteffen Görtz static void test_nrf51_gpio(void)
25*17ff8e18SSteffen Görtz {
26*17ff8e18SSteffen Görtz     size_t i;
27*17ff8e18SSteffen Görtz     uint32_t actual, expected;
28*17ff8e18SSteffen Görtz 
29*17ff8e18SSteffen Görtz     struct {
30*17ff8e18SSteffen Görtz         hwaddr addr;
31*17ff8e18SSteffen Görtz         uint32_t expected;
32*17ff8e18SSteffen Görtz     } const reset_state[] = {
33*17ff8e18SSteffen Görtz         {NRF51_GPIO_REG_OUT, 0x00000000}, {NRF51_GPIO_REG_OUTSET, 0x00000000},
34*17ff8e18SSteffen Görtz         {NRF51_GPIO_REG_OUTCLR, 0x00000000}, {NRF51_GPIO_REG_IN, 0x00000000},
35*17ff8e18SSteffen Görtz         {NRF51_GPIO_REG_DIR, 0x00000000}, {NRF51_GPIO_REG_DIRSET, 0x00000000},
36*17ff8e18SSteffen Görtz         {NRF51_GPIO_REG_DIRCLR, 0x00000000}
37*17ff8e18SSteffen Görtz     };
38*17ff8e18SSteffen Görtz 
39*17ff8e18SSteffen Görtz     /* Check reset state */
40*17ff8e18SSteffen Görtz     for (i = 0; i < ARRAY_SIZE(reset_state); i++) {
41*17ff8e18SSteffen Görtz         expected = reset_state[i].expected;
42*17ff8e18SSteffen Görtz         actual = readl(NRF51_GPIO_BASE + reset_state[i].addr);
43*17ff8e18SSteffen Görtz         g_assert_cmpuint(actual, ==, expected);
44*17ff8e18SSteffen Görtz     }
45*17ff8e18SSteffen Görtz 
46*17ff8e18SSteffen Görtz     for (i = 0; i < NRF51_GPIO_PINS; i++) {
47*17ff8e18SSteffen Görtz         expected = 0x00000002;
48*17ff8e18SSteffen Görtz         actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START + i * 4);
49*17ff8e18SSteffen Görtz         g_assert_cmpuint(actual, ==, expected);
50*17ff8e18SSteffen Görtz     }
51*17ff8e18SSteffen Görtz 
52*17ff8e18SSteffen Görtz     /* Check dir bit consistency between dir and cnf */
53*17ff8e18SSteffen Görtz     /* Check set via DIRSET */
54*17ff8e18SSteffen Görtz     expected = 0x80000001;
55*17ff8e18SSteffen Görtz     writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIRSET, expected);
56*17ff8e18SSteffen Görtz     actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR);
57*17ff8e18SSteffen Görtz     g_assert_cmpuint(actual, ==, expected);
58*17ff8e18SSteffen Görtz     actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START) & 0x01;
59*17ff8e18SSteffen Görtz     g_assert_cmpuint(actual, ==, 0x01);
60*17ff8e18SSteffen Görtz     actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01;
61*17ff8e18SSteffen Görtz     g_assert_cmpuint(actual, ==, 0x01);
62*17ff8e18SSteffen Görtz 
63*17ff8e18SSteffen Görtz     /* Check clear via DIRCLR */
64*17ff8e18SSteffen Görtz     writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIRCLR, 0x80000001);
65*17ff8e18SSteffen Görtz     actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR);
66*17ff8e18SSteffen Görtz     g_assert_cmpuint(actual, ==, 0x00000000);
67*17ff8e18SSteffen Görtz     actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START) & 0x01;
68*17ff8e18SSteffen Görtz     g_assert_cmpuint(actual, ==, 0x00);
69*17ff8e18SSteffen Görtz     actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01;
70*17ff8e18SSteffen Görtz     g_assert_cmpuint(actual, ==, 0x00);
71*17ff8e18SSteffen Görtz 
72*17ff8e18SSteffen Görtz     /* Check set via DIR */
73*17ff8e18SSteffen Görtz     expected = 0x80000001;
74*17ff8e18SSteffen Görtz     writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR, expected);
75*17ff8e18SSteffen Görtz     actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR);
76*17ff8e18SSteffen Görtz     g_assert_cmpuint(actual, ==, expected);
77*17ff8e18SSteffen Görtz     actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START) & 0x01;
78*17ff8e18SSteffen Görtz     g_assert_cmpuint(actual, ==, 0x01);
79*17ff8e18SSteffen Görtz     actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01;
80*17ff8e18SSteffen Görtz     g_assert_cmpuint(actual, ==, 0x01);
81*17ff8e18SSteffen Görtz 
82*17ff8e18SSteffen Görtz     /* Reset DIR */
83*17ff8e18SSteffen Görtz     writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR, 0x00000000);
84*17ff8e18SSteffen Görtz 
85*17ff8e18SSteffen Görtz     /* Check Input propagates */
86*17ff8e18SSteffen Görtz     writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x00);
87*17ff8e18SSteffen Görtz     qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 0);
88*17ff8e18SSteffen Görtz     actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
89*17ff8e18SSteffen Görtz     g_assert_cmpuint(actual, ==, 0x00);
90*17ff8e18SSteffen Görtz     qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 1);
91*17ff8e18SSteffen Görtz     actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
92*17ff8e18SSteffen Görtz     g_assert_cmpuint(actual, ==, 0x01);
93*17ff8e18SSteffen Görtz     qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, -1);
94*17ff8e18SSteffen Görtz     actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
95*17ff8e18SSteffen Görtz     g_assert_cmpuint(actual, ==, 0x01);
96*17ff8e18SSteffen Görtz     writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02);
97*17ff8e18SSteffen Görtz 
98*17ff8e18SSteffen Görtz     /* Check pull-up working */
99*17ff8e18SSteffen Görtz     qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 0);
100*17ff8e18SSteffen Görtz     writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0000);
101*17ff8e18SSteffen Görtz     actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
102*17ff8e18SSteffen Görtz     g_assert_cmpuint(actual, ==, 0x00);
103*17ff8e18SSteffen Görtz     writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b1110);
104*17ff8e18SSteffen Görtz     actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
105*17ff8e18SSteffen Görtz     g_assert_cmpuint(actual, ==, 0x01);
106*17ff8e18SSteffen Görtz     writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02);
107*17ff8e18SSteffen Görtz 
108*17ff8e18SSteffen Görtz     /* Check pull-down working */
109*17ff8e18SSteffen Görtz     qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 1);
110*17ff8e18SSteffen Görtz     writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0000);
111*17ff8e18SSteffen Görtz     actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
112*17ff8e18SSteffen Görtz     g_assert_cmpuint(actual, ==, 0x01);
113*17ff8e18SSteffen Görtz     writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0110);
114*17ff8e18SSteffen Görtz     actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
115*17ff8e18SSteffen Görtz     g_assert_cmpuint(actual, ==, 0x00);
116*17ff8e18SSteffen Görtz     writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02);
117*17ff8e18SSteffen Görtz     qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, -1);
118*17ff8e18SSteffen Görtz 
119*17ff8e18SSteffen Görtz     /* Check Output propagates */
120*17ff8e18SSteffen Görtz     irq_intercept_out("/machine/nrf51");
121*17ff8e18SSteffen Görtz     writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0011);
122*17ff8e18SSteffen Görtz     writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTSET, 0x01);
123*17ff8e18SSteffen Görtz     g_assert_true(get_irq(0));
124*17ff8e18SSteffen Görtz     writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTCLR, 0x01);
125*17ff8e18SSteffen Görtz     g_assert_false(get_irq(0));
126*17ff8e18SSteffen Görtz 
127*17ff8e18SSteffen Görtz     /* Check self-stimulation */
128*17ff8e18SSteffen Görtz     writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b01);
129*17ff8e18SSteffen Görtz     writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTSET, 0x01);
130*17ff8e18SSteffen Görtz     actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
131*17ff8e18SSteffen Görtz     g_assert_cmpuint(actual, ==, 0x01);
132*17ff8e18SSteffen Görtz 
133*17ff8e18SSteffen Görtz     writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTCLR, 0x01);
134*17ff8e18SSteffen Görtz     actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
135*17ff8e18SSteffen Görtz     g_assert_cmpuint(actual, ==, 0x00);
136*17ff8e18SSteffen Görtz 
137*17ff8e18SSteffen Görtz     /*
138*17ff8e18SSteffen Görtz      * Check short-circuit - generates an guest_error which must be checked
139*17ff8e18SSteffen Görtz      * manually as long as qtest can not scan qemu_log messages
140*17ff8e18SSteffen Görtz      */
141*17ff8e18SSteffen Görtz     writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b01);
142*17ff8e18SSteffen Görtz     writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTSET, 0x01);
143*17ff8e18SSteffen Görtz     qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 0);
144*17ff8e18SSteffen Görtz }
145*17ff8e18SSteffen Görtz 
146*17ff8e18SSteffen Görtz int main(int argc, char **argv)
147*17ff8e18SSteffen Görtz {
148*17ff8e18SSteffen Görtz     int ret;
149*17ff8e18SSteffen Görtz 
150*17ff8e18SSteffen Görtz     g_test_init(&argc, &argv, NULL);
151*17ff8e18SSteffen Görtz 
152*17ff8e18SSteffen Görtz     global_qtest = qtest_initf("-machine microbit");
153*17ff8e18SSteffen Görtz 
154*17ff8e18SSteffen Görtz     qtest_add_func("/microbit/nrf51/gpio", test_nrf51_gpio);
155*17ff8e18SSteffen Görtz 
156*17ff8e18SSteffen Görtz     ret = g_test_run();
157*17ff8e18SSteffen Görtz 
158*17ff8e18SSteffen Görtz     qtest_quit(global_qtest);
159*17ff8e18SSteffen Görtz     return ret;
160*17ff8e18SSteffen Görtz }
161