1 /* 2 * QTests for Nuvoton NPCM7xx/8xx GMAC Modules. 3 * 4 * Copyright 2024 Google LLC 5 * Authors: 6 * Hao Wu <wuhaotsh@google.com> 7 * Nabih Estefan <nabihestefan@google.com> 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License as published by the 11 * Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, but WITHOUT 15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17 * for more details. 18 */ 19 20 #include "qemu/osdep.h" 21 #include "libqos/libqos.h" 22 23 /* Name of the GMAC Device */ 24 #define TYPE_NPCM_GMAC "npcm-gmac" 25 26 /* Address of the PCS Module */ 27 #define PCS_BASE_ADDRESS 0xf0780000 28 #define NPCM_PCS_IND_AC_BA 0x1fe 29 30 typedef struct GMACModule { 31 int irq; 32 uint64_t base_addr; 33 } GMACModule; 34 35 typedef struct TestData { 36 const GMACModule *module; 37 } TestData; 38 39 /* Values extracted from hw/arm/npcm8xx.c */ 40 static const GMACModule gmac_module_list[] = { 41 { 42 .irq = 14, 43 .base_addr = 0xf0802000 44 }, 45 { 46 .irq = 15, 47 .base_addr = 0xf0804000 48 }, 49 { 50 .irq = 16, 51 .base_addr = 0xf0806000 52 }, 53 { 54 .irq = 17, 55 .base_addr = 0xf0808000 56 } 57 }; 58 59 /* Returns the index of the GMAC module. */ 60 static int gmac_module_index(const GMACModule *mod) 61 { 62 ptrdiff_t diff = mod - gmac_module_list; 63 64 g_assert_true(diff >= 0 && diff < ARRAY_SIZE(gmac_module_list)); 65 66 return diff; 67 } 68 69 /* 32-bit register indices. Taken from npcm_gmac.c */ 70 typedef enum NPCMRegister { 71 /* DMA Registers */ 72 NPCM_DMA_BUS_MODE = 0x1000, 73 NPCM_DMA_XMT_POLL_DEMAND = 0x1004, 74 NPCM_DMA_RCV_POLL_DEMAND = 0x1008, 75 NPCM_DMA_RCV_BASE_ADDR = 0x100c, 76 NPCM_DMA_TX_BASE_ADDR = 0x1010, 77 NPCM_DMA_STATUS = 0x1014, 78 NPCM_DMA_CONTROL = 0x1018, 79 NPCM_DMA_INTR_ENA = 0x101c, 80 NPCM_DMA_MISSED_FRAME_CTR = 0x1020, 81 NPCM_DMA_HOST_TX_DESC = 0x1048, 82 NPCM_DMA_HOST_RX_DESC = 0x104c, 83 NPCM_DMA_CUR_TX_BUF_ADDR = 0x1050, 84 NPCM_DMA_CUR_RX_BUF_ADDR = 0x1054, 85 NPCM_DMA_HW_FEATURE = 0x1058, 86 87 /* GMAC Registers */ 88 NPCM_GMAC_MAC_CONFIG = 0x0, 89 NPCM_GMAC_FRAME_FILTER = 0x4, 90 NPCM_GMAC_HASH_HIGH = 0x8, 91 NPCM_GMAC_HASH_LOW = 0xc, 92 NPCM_GMAC_MII_ADDR = 0x10, 93 NPCM_GMAC_MII_DATA = 0x14, 94 NPCM_GMAC_FLOW_CTRL = 0x18, 95 NPCM_GMAC_VLAN_FLAG = 0x1c, 96 NPCM_GMAC_VERSION = 0x20, 97 NPCM_GMAC_WAKEUP_FILTER = 0x28, 98 NPCM_GMAC_PMT = 0x2c, 99 NPCM_GMAC_LPI_CTRL = 0x30, 100 NPCM_GMAC_TIMER_CTRL = 0x34, 101 NPCM_GMAC_INT_STATUS = 0x38, 102 NPCM_GMAC_INT_MASK = 0x3c, 103 NPCM_GMAC_MAC0_ADDR_HI = 0x40, 104 NPCM_GMAC_MAC0_ADDR_LO = 0x44, 105 NPCM_GMAC_MAC1_ADDR_HI = 0x48, 106 NPCM_GMAC_MAC1_ADDR_LO = 0x4c, 107 NPCM_GMAC_MAC2_ADDR_HI = 0x50, 108 NPCM_GMAC_MAC2_ADDR_LO = 0x54, 109 NPCM_GMAC_MAC3_ADDR_HI = 0x58, 110 NPCM_GMAC_MAC3_ADDR_LO = 0x5c, 111 NPCM_GMAC_RGMII_STATUS = 0xd8, 112 NPCM_GMAC_WATCHDOG = 0xdc, 113 NPCM_GMAC_PTP_TCR = 0x700, 114 NPCM_GMAC_PTP_SSIR = 0x704, 115 NPCM_GMAC_PTP_STSR = 0x708, 116 NPCM_GMAC_PTP_STNSR = 0x70c, 117 NPCM_GMAC_PTP_STSUR = 0x710, 118 NPCM_GMAC_PTP_STNSUR = 0x714, 119 NPCM_GMAC_PTP_TAR = 0x718, 120 NPCM_GMAC_PTP_TTSR = 0x71c, 121 122 /* PCS Registers */ 123 NPCM_PCS_SR_CTL_ID1 = 0x3c0008, 124 NPCM_PCS_SR_CTL_ID2 = 0x3c000a, 125 NPCM_PCS_SR_CTL_STS = 0x3c0010, 126 127 NPCM_PCS_SR_MII_CTRL = 0x3e0000, 128 NPCM_PCS_SR_MII_STS = 0x3e0002, 129 NPCM_PCS_SR_MII_DEV_ID1 = 0x3e0004, 130 NPCM_PCS_SR_MII_DEV_ID2 = 0x3e0006, 131 NPCM_PCS_SR_MII_AN_ADV = 0x3e0008, 132 NPCM_PCS_SR_MII_LP_BABL = 0x3e000a, 133 NPCM_PCS_SR_MII_AN_EXPN = 0x3e000c, 134 NPCM_PCS_SR_MII_EXT_STS = 0x3e001e, 135 136 NPCM_PCS_SR_TIM_SYNC_ABL = 0x3e0e10, 137 NPCM_PCS_SR_TIM_SYNC_TX_MAX_DLY_LWR = 0x3e0e12, 138 NPCM_PCS_SR_TIM_SYNC_TX_MAX_DLY_UPR = 0x3e0e14, 139 NPCM_PCS_SR_TIM_SYNC_TX_MIN_DLY_LWR = 0x3e0e16, 140 NPCM_PCS_SR_TIM_SYNC_TX_MIN_DLY_UPR = 0x3e0e18, 141 NPCM_PCS_SR_TIM_SYNC_RX_MAX_DLY_LWR = 0x3e0e1a, 142 NPCM_PCS_SR_TIM_SYNC_RX_MAX_DLY_UPR = 0x3e0e1c, 143 NPCM_PCS_SR_TIM_SYNC_RX_MIN_DLY_LWR = 0x3e0e1e, 144 NPCM_PCS_SR_TIM_SYNC_RX_MIN_DLY_UPR = 0x3e0e20, 145 146 NPCM_PCS_VR_MII_MMD_DIG_CTRL1 = 0x3f0000, 147 NPCM_PCS_VR_MII_AN_CTRL = 0x3f0002, 148 NPCM_PCS_VR_MII_AN_INTR_STS = 0x3f0004, 149 NPCM_PCS_VR_MII_TC = 0x3f0006, 150 NPCM_PCS_VR_MII_DBG_CTRL = 0x3f000a, 151 NPCM_PCS_VR_MII_EEE_MCTRL0 = 0x3f000c, 152 NPCM_PCS_VR_MII_EEE_TXTIMER = 0x3f0010, 153 NPCM_PCS_VR_MII_EEE_RXTIMER = 0x3f0012, 154 NPCM_PCS_VR_MII_LINK_TIMER_CTRL = 0x3f0014, 155 NPCM_PCS_VR_MII_EEE_MCTRL1 = 0x3f0016, 156 NPCM_PCS_VR_MII_DIG_STS = 0x3f0020, 157 NPCM_PCS_VR_MII_ICG_ERRCNT1 = 0x3f0022, 158 NPCM_PCS_VR_MII_MISC_STS = 0x3f0030, 159 NPCM_PCS_VR_MII_RX_LSTS = 0x3f0040, 160 NPCM_PCS_VR_MII_MP_TX_BSTCTRL0 = 0x3f0070, 161 NPCM_PCS_VR_MII_MP_TX_LVLCTRL0 = 0x3f0074, 162 NPCM_PCS_VR_MII_MP_TX_GENCTRL0 = 0x3f007a, 163 NPCM_PCS_VR_MII_MP_TX_GENCTRL1 = 0x3f007c, 164 NPCM_PCS_VR_MII_MP_TX_STS = 0x3f0090, 165 NPCM_PCS_VR_MII_MP_RX_GENCTRL0 = 0x3f00b0, 166 NPCM_PCS_VR_MII_MP_RX_GENCTRL1 = 0x3f00b2, 167 NPCM_PCS_VR_MII_MP_RX_LOS_CTRL0 = 0x3f00ba, 168 NPCM_PCS_VR_MII_MP_MPLL_CTRL0 = 0x3f00f0, 169 NPCM_PCS_VR_MII_MP_MPLL_CTRL1 = 0x3f00f2, 170 NPCM_PCS_VR_MII_MP_MPLL_STS = 0x3f0110, 171 NPCM_PCS_VR_MII_MP_MISC_CTRL2 = 0x3f0126, 172 NPCM_PCS_VR_MII_MP_LVL_CTRL = 0x3f0130, 173 NPCM_PCS_VR_MII_MP_MISC_CTRL0 = 0x3f0132, 174 NPCM_PCS_VR_MII_MP_MISC_CTRL1 = 0x3f0134, 175 NPCM_PCS_VR_MII_DIG_CTRL2 = 0x3f01c2, 176 NPCM_PCS_VR_MII_DIG_ERRCNT_SEL = 0x3f01c4, 177 } NPCMRegister; 178 179 static uint32_t gmac_read(QTestState *qts, const GMACModule *mod, 180 NPCMRegister regno) 181 { 182 return qtest_readl(qts, mod->base_addr + regno); 183 } 184 185 static uint16_t pcs_read(QTestState *qts, const GMACModule *mod, 186 NPCMRegister regno) 187 { 188 uint32_t write_value = (regno & 0x3ffe00) >> 9; 189 qtest_writel(qts, PCS_BASE_ADDRESS + NPCM_PCS_IND_AC_BA, write_value); 190 uint32_t read_offset = regno & 0x1ff; 191 return qtest_readl(qts, PCS_BASE_ADDRESS + read_offset); 192 } 193 194 /* Check that GMAC registers are reset to default value */ 195 static void test_init(gconstpointer test_data) 196 { 197 const TestData *td = test_data; 198 const GMACModule *mod = td->module; 199 QTestState *qts = qtest_init("-machine npcm845-evb"); 200 201 #define CHECK_REG32(regno, value) \ 202 do { \ 203 g_assert_cmphex(gmac_read(qts, mod, (regno)), ==, (value)); \ 204 } while (0) 205 206 #define CHECK_REG_PCS(regno, value) \ 207 do { \ 208 g_assert_cmphex(pcs_read(qts, mod, (regno)), ==, (value)); \ 209 } while (0) 210 211 CHECK_REG32(NPCM_DMA_BUS_MODE, 0x00020100); 212 CHECK_REG32(NPCM_DMA_XMT_POLL_DEMAND, 0); 213 CHECK_REG32(NPCM_DMA_RCV_POLL_DEMAND, 0); 214 CHECK_REG32(NPCM_DMA_RCV_BASE_ADDR, 0); 215 CHECK_REG32(NPCM_DMA_TX_BASE_ADDR, 0); 216 CHECK_REG32(NPCM_DMA_STATUS, 0); 217 CHECK_REG32(NPCM_DMA_CONTROL, 0); 218 CHECK_REG32(NPCM_DMA_INTR_ENA, 0); 219 CHECK_REG32(NPCM_DMA_MISSED_FRAME_CTR, 0); 220 CHECK_REG32(NPCM_DMA_HOST_TX_DESC, 0); 221 CHECK_REG32(NPCM_DMA_HOST_RX_DESC, 0); 222 CHECK_REG32(NPCM_DMA_CUR_TX_BUF_ADDR, 0); 223 CHECK_REG32(NPCM_DMA_CUR_RX_BUF_ADDR, 0); 224 CHECK_REG32(NPCM_DMA_HW_FEATURE, 0x100d4f37); 225 226 CHECK_REG32(NPCM_GMAC_MAC_CONFIG, 0); 227 CHECK_REG32(NPCM_GMAC_FRAME_FILTER, 0); 228 CHECK_REG32(NPCM_GMAC_HASH_HIGH, 0); 229 CHECK_REG32(NPCM_GMAC_HASH_LOW, 0); 230 CHECK_REG32(NPCM_GMAC_MII_ADDR, 0); 231 CHECK_REG32(NPCM_GMAC_MII_DATA, 0); 232 CHECK_REG32(NPCM_GMAC_FLOW_CTRL, 0); 233 CHECK_REG32(NPCM_GMAC_VLAN_FLAG, 0); 234 CHECK_REG32(NPCM_GMAC_VERSION, 0x00001032); 235 CHECK_REG32(NPCM_GMAC_WAKEUP_FILTER, 0); 236 CHECK_REG32(NPCM_GMAC_PMT, 0); 237 CHECK_REG32(NPCM_GMAC_LPI_CTRL, 0); 238 CHECK_REG32(NPCM_GMAC_TIMER_CTRL, 0x03e80000); 239 CHECK_REG32(NPCM_GMAC_INT_STATUS, 0); 240 CHECK_REG32(NPCM_GMAC_INT_MASK, 0); 241 CHECK_REG32(NPCM_GMAC_MAC0_ADDR_HI, 0x8000ffff); 242 CHECK_REG32(NPCM_GMAC_MAC0_ADDR_LO, 0xffffffff); 243 CHECK_REG32(NPCM_GMAC_MAC1_ADDR_HI, 0x0000ffff); 244 CHECK_REG32(NPCM_GMAC_MAC1_ADDR_LO, 0xffffffff); 245 CHECK_REG32(NPCM_GMAC_MAC2_ADDR_HI, 0x0000ffff); 246 CHECK_REG32(NPCM_GMAC_MAC2_ADDR_LO, 0xffffffff); 247 CHECK_REG32(NPCM_GMAC_MAC3_ADDR_HI, 0x0000ffff); 248 CHECK_REG32(NPCM_GMAC_MAC3_ADDR_LO, 0xffffffff); 249 CHECK_REG32(NPCM_GMAC_RGMII_STATUS, 0); 250 CHECK_REG32(NPCM_GMAC_WATCHDOG, 0); 251 CHECK_REG32(NPCM_GMAC_PTP_TCR, 0x00002000); 252 CHECK_REG32(NPCM_GMAC_PTP_SSIR, 0); 253 CHECK_REG32(NPCM_GMAC_PTP_STSR, 0); 254 CHECK_REG32(NPCM_GMAC_PTP_STNSR, 0); 255 CHECK_REG32(NPCM_GMAC_PTP_STSUR, 0); 256 CHECK_REG32(NPCM_GMAC_PTP_STNSUR, 0); 257 CHECK_REG32(NPCM_GMAC_PTP_TAR, 0); 258 CHECK_REG32(NPCM_GMAC_PTP_TTSR, 0); 259 260 /* TODO Add registers PCS */ 261 if (mod->base_addr == 0xf0802000) { 262 CHECK_REG_PCS(NPCM_PCS_SR_CTL_ID1, 0x699e); 263 CHECK_REG_PCS(NPCM_PCS_SR_CTL_ID2, 0); 264 CHECK_REG_PCS(NPCM_PCS_SR_CTL_STS, 0x8000); 265 266 CHECK_REG_PCS(NPCM_PCS_SR_MII_CTRL, 0x1140); 267 CHECK_REG_PCS(NPCM_PCS_SR_MII_STS, 0x0109); 268 CHECK_REG_PCS(NPCM_PCS_SR_MII_DEV_ID1, 0x699e); 269 CHECK_REG_PCS(NPCM_PCS_SR_MII_DEV_ID2, 0x0ced0); 270 CHECK_REG_PCS(NPCM_PCS_SR_MII_AN_ADV, 0x0020); 271 CHECK_REG_PCS(NPCM_PCS_SR_MII_LP_BABL, 0); 272 CHECK_REG_PCS(NPCM_PCS_SR_MII_AN_EXPN, 0); 273 CHECK_REG_PCS(NPCM_PCS_SR_MII_EXT_STS, 0xc000); 274 275 CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_ABL, 0x0003); 276 CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_TX_MAX_DLY_LWR, 0x0038); 277 CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_TX_MAX_DLY_UPR, 0); 278 CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_TX_MIN_DLY_LWR, 0x0038); 279 CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_TX_MIN_DLY_UPR, 0); 280 CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_RX_MAX_DLY_LWR, 0x0058); 281 CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_RX_MAX_DLY_UPR, 0); 282 CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_RX_MIN_DLY_LWR, 0x0048); 283 CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_RX_MIN_DLY_UPR, 0); 284 285 CHECK_REG_PCS(NPCM_PCS_VR_MII_MMD_DIG_CTRL1, 0x2400); 286 CHECK_REG_PCS(NPCM_PCS_VR_MII_AN_CTRL, 0); 287 CHECK_REG_PCS(NPCM_PCS_VR_MII_AN_INTR_STS, 0x000a); 288 CHECK_REG_PCS(NPCM_PCS_VR_MII_TC, 0); 289 CHECK_REG_PCS(NPCM_PCS_VR_MII_DBG_CTRL, 0); 290 CHECK_REG_PCS(NPCM_PCS_VR_MII_EEE_MCTRL0, 0x899c); 291 CHECK_REG_PCS(NPCM_PCS_VR_MII_EEE_TXTIMER, 0); 292 CHECK_REG_PCS(NPCM_PCS_VR_MII_EEE_RXTIMER, 0); 293 CHECK_REG_PCS(NPCM_PCS_VR_MII_LINK_TIMER_CTRL, 0); 294 CHECK_REG_PCS(NPCM_PCS_VR_MII_EEE_MCTRL1, 0); 295 CHECK_REG_PCS(NPCM_PCS_VR_MII_DIG_STS, 0x0010); 296 CHECK_REG_PCS(NPCM_PCS_VR_MII_ICG_ERRCNT1, 0); 297 CHECK_REG_PCS(NPCM_PCS_VR_MII_MISC_STS, 0); 298 CHECK_REG_PCS(NPCM_PCS_VR_MII_RX_LSTS, 0); 299 CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_TX_BSTCTRL0, 0x00a); 300 CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_TX_LVLCTRL0, 0x007f); 301 CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_TX_GENCTRL0, 0x0001); 302 CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_TX_GENCTRL1, 0); 303 CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_TX_STS, 0); 304 CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_RX_GENCTRL0, 0x0100); 305 CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_RX_GENCTRL1, 0x1100); 306 CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_RX_LOS_CTRL0, 0x000e); 307 CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_MPLL_CTRL0, 0x0100); 308 CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_MPLL_CTRL1, 0x0032); 309 CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_MPLL_STS, 0x0001); 310 CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_MISC_CTRL2, 0); 311 CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_LVL_CTRL, 0x0019); 312 CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_MISC_CTRL0, 0); 313 CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_MISC_CTRL1, 0); 314 CHECK_REG_PCS(NPCM_PCS_VR_MII_DIG_CTRL2, 0); 315 CHECK_REG_PCS(NPCM_PCS_VR_MII_DIG_ERRCNT_SEL, 0); 316 } 317 318 qtest_quit(qts); 319 } 320 321 static void gmac_add_test(const char *name, const TestData* td, 322 GTestDataFunc fn) 323 { 324 g_autofree char *full_name = g_strdup_printf( 325 "npcm7xx_gmac/gmac[%d]/%s", gmac_module_index(td->module), name); 326 qtest_add_data_func(full_name, td, fn); 327 } 328 329 int main(int argc, char **argv) 330 { 331 TestData test_data_list[ARRAY_SIZE(gmac_module_list)]; 332 333 g_test_init(&argc, &argv, NULL); 334 335 for (int i = 0; i < ARRAY_SIZE(gmac_module_list); ++i) { 336 TestData *td = &test_data_list[i]; 337 338 td->module = &gmac_module_list[i]; 339 340 gmac_add_test("init", td, test_init); 341 } 342 343 return g_test_run(); 344 } 345