1 /* 2 * QTest testcase for DM163 3 * 4 * Copyright (C) 2024 Samuel Tardieu <sam@rfc1149.net> 5 * Copyright (C) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr> 6 * Copyright (C) 2024 Inès Varhol <ines.varhol@telecom-paris.fr> 7 * 8 * SPDX-License-Identifier: GPL-2.0-or-later 9 */ 10 11 #include "qemu/osdep.h" 12 #include "libqtest.h" 13 14 enum DM163_INPUTS { 15 SIN = 8, 16 DCK = 9, 17 RST_B = 10, 18 LAT_B = 11, 19 SELBK = 12, 20 EN_B = 13 21 }; 22 23 #define DEVICE_NAME "/machine/dm163" 24 #define GPIO_OUT(name, value) qtest_set_irq_in(qts, DEVICE_NAME, NULL, name, \ 25 value) 26 #define GPIO_PULSE(name) \ 27 do { \ 28 GPIO_OUT(name, 1); \ 29 GPIO_OUT(name, 0); \ 30 } while (0) 31 32 33 static void rise_gpio_pin_dck(QTestState *qts) 34 { 35 /* Configure output mode for pin PB1 */ 36 qtest_writel(qts, 0x48000400, 0xFFFFFEB7); 37 /* Write 1 in ODR for PB1 */ 38 qtest_writel(qts, 0x48000414, 0x00000002); 39 } 40 41 static void lower_gpio_pin_dck(QTestState *qts) 42 { 43 /* Configure output mode for pin PB1 */ 44 qtest_writel(qts, 0x48000400, 0xFFFFFEB7); 45 /* Write 0 in ODR for PB1 */ 46 qtest_writel(qts, 0x48000414, 0x00000000); 47 } 48 49 static void rise_gpio_pin_selbk(QTestState *qts) 50 { 51 /* Configure output mode for pin PC5 */ 52 qtest_writel(qts, 0x48000800, 0xFFFFF7FF); 53 /* Write 1 in ODR for PC5 */ 54 qtest_writel(qts, 0x48000814, 0x00000020); 55 } 56 57 static void lower_gpio_pin_selbk(QTestState *qts) 58 { 59 /* Configure output mode for pin PC5 */ 60 qtest_writel(qts, 0x48000800, 0xFFFFF7FF); 61 /* Write 0 in ODR for PC5 */ 62 qtest_writel(qts, 0x48000814, 0x00000000); 63 } 64 65 static void rise_gpio_pin_lat_b(QTestState *qts) 66 { 67 /* Configure output mode for pin PC4 */ 68 qtest_writel(qts, 0x48000800, 0xFFFFFDFF); 69 /* Write 1 in ODR for PC4 */ 70 qtest_writel(qts, 0x48000814, 0x00000010); 71 } 72 73 static void lower_gpio_pin_lat_b(QTestState *qts) 74 { 75 /* Configure output mode for pin PC4 */ 76 qtest_writel(qts, 0x48000800, 0xFFFFFDFF); 77 /* Write 0 in ODR for PC4 */ 78 qtest_writel(qts, 0x48000814, 0x00000000); 79 } 80 81 static void rise_gpio_pin_rst_b(QTestState *qts) 82 { 83 /* Configure output mode for pin PC3 */ 84 qtest_writel(qts, 0x48000800, 0xFFFFFF7F); 85 /* Write 1 in ODR for PC3 */ 86 qtest_writel(qts, 0x48000814, 0x00000008); 87 } 88 89 static void lower_gpio_pin_rst_b(QTestState *qts) 90 { 91 /* Configure output mode for pin PC3 */ 92 qtest_writel(qts, 0x48000800, 0xFFFFFF7F); 93 /* Write 0 in ODR for PC3 */ 94 qtest_writel(qts, 0x48000814, 0x00000000); 95 } 96 97 static void rise_gpio_pin_sin(QTestState *qts) 98 { 99 /* Configure output mode for pin PA4 */ 100 qtest_writel(qts, 0x48000000, 0xFFFFFDFF); 101 /* Write 1 in ODR for PA4 */ 102 qtest_writel(qts, 0x48000014, 0x00000010); 103 } 104 105 static void lower_gpio_pin_sin(QTestState *qts) 106 { 107 /* Configure output mode for pin PA4 */ 108 qtest_writel(qts, 0x48000000, 0xFFFFFDFF); 109 /* Write 0 in ODR for PA4 */ 110 qtest_writel(qts, 0x48000014, 0x00000000); 111 } 112 113 static void test_dm163_bank(const void *opaque) 114 { 115 const unsigned bank = (uintptr_t) opaque; 116 const int width = bank ? 192 : 144; 117 118 QTestState *qts = qtest_initf("-M b-l475e-iot01a"); 119 qtest_irq_intercept_out_named(qts, DEVICE_NAME, "sout"); 120 GPIO_OUT(RST_B, 1); 121 GPIO_OUT(EN_B, 0); 122 GPIO_OUT(DCK, 0); 123 GPIO_OUT(SELBK, bank); 124 GPIO_OUT(LAT_B, 1); 125 126 /* Fill bank with zeroes */ 127 GPIO_OUT(SIN, 0); 128 for (int i = 0; i < width; i++) { 129 GPIO_PULSE(DCK); 130 } 131 /* Fill bank with ones, check that we get the previous zeroes */ 132 GPIO_OUT(SIN, 1); 133 for (int i = 0; i < width; i++) { 134 GPIO_PULSE(DCK); 135 g_assert(!qtest_get_irq(qts, 0)); 136 } 137 138 /* Pulse one more bit in the bank, check that we get a one */ 139 GPIO_PULSE(DCK); 140 g_assert(qtest_get_irq(qts, 0)); 141 142 qtest_quit(qts); 143 } 144 145 static void test_dm163_gpio_connection(void) 146 { 147 QTestState *qts = qtest_init("-M b-l475e-iot01a"); 148 qtest_irq_intercept_in(qts, DEVICE_NAME); 149 150 g_assert_false(qtest_get_irq(qts, SIN)); 151 g_assert_false(qtest_get_irq(qts, DCK)); 152 g_assert_false(qtest_get_irq(qts, RST_B)); 153 g_assert_false(qtest_get_irq(qts, LAT_B)); 154 g_assert_false(qtest_get_irq(qts, SELBK)); 155 156 rise_gpio_pin_dck(qts); 157 g_assert_true(qtest_get_irq(qts, DCK)); 158 lower_gpio_pin_dck(qts); 159 g_assert_false(qtest_get_irq(qts, DCK)); 160 161 rise_gpio_pin_lat_b(qts); 162 g_assert_true(qtest_get_irq(qts, LAT_B)); 163 lower_gpio_pin_lat_b(qts); 164 g_assert_false(qtest_get_irq(qts, LAT_B)); 165 166 rise_gpio_pin_selbk(qts); 167 g_assert_true(qtest_get_irq(qts, SELBK)); 168 lower_gpio_pin_selbk(qts); 169 g_assert_false(qtest_get_irq(qts, SELBK)); 170 171 rise_gpio_pin_rst_b(qts); 172 g_assert_true(qtest_get_irq(qts, RST_B)); 173 lower_gpio_pin_rst_b(qts); 174 g_assert_false(qtest_get_irq(qts, RST_B)); 175 176 rise_gpio_pin_sin(qts); 177 g_assert_true(qtest_get_irq(qts, SIN)); 178 lower_gpio_pin_sin(qts); 179 g_assert_false(qtest_get_irq(qts, SIN)); 180 181 g_assert_false(qtest_get_irq(qts, DCK)); 182 g_assert_false(qtest_get_irq(qts, LAT_B)); 183 g_assert_false(qtest_get_irq(qts, SELBK)); 184 g_assert_false(qtest_get_irq(qts, RST_B)); 185 } 186 187 int main(int argc, char **argv) 188 { 189 g_test_init(&argc, &argv, NULL); 190 qtest_add_data_func("/dm163/bank0", (void *)0, test_dm163_bank); 191 qtest_add_data_func("/dm163/bank1", (void *)1, test_dm163_bank); 192 qtest_add_func("/dm163/gpio_connection", test_dm163_gpio_connection); 193 return g_test_run(); 194 } 195