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