xref: /openbmc/qemu/tests/qtest/pnv-xscom-test.c (revision e1a821d4)
11e8a1faeSThomas Huth /*
21e8a1faeSThomas Huth  * QTest testcase for PowerNV XSCOM bus
31e8a1faeSThomas Huth  *
41e8a1faeSThomas Huth  * Copyright (c) 2016, IBM Corporation.
51e8a1faeSThomas Huth  *
61e8a1faeSThomas Huth  * This work is licensed under the terms of the GNU GPL, version 2 or
71e8a1faeSThomas Huth  * later. See the COPYING file in the top-level directory.
81e8a1faeSThomas Huth  */
91e8a1faeSThomas Huth #include "qemu/osdep.h"
101e8a1faeSThomas Huth 
11907b5105SMarc-André Lureau #include "libqtest.h"
121e8a1faeSThomas Huth 
131e8a1faeSThomas Huth typedef enum PnvChipType {
141e8a1faeSThomas Huth     PNV_CHIP_POWER8E,     /* AKA Murano (default) */
151e8a1faeSThomas Huth     PNV_CHIP_POWER8,      /* AKA Venice */
161e8a1faeSThomas Huth     PNV_CHIP_POWER8NVL,   /* AKA Naples */
171e8a1faeSThomas Huth     PNV_CHIP_POWER9,      /* AKA Nimbus */
18*e1a821d4SNicholas Piggin     PNV_CHIP_POWER10,
191e8a1faeSThomas Huth } PnvChipType;
201e8a1faeSThomas Huth 
211e8a1faeSThomas Huth typedef struct PnvChip {
221e8a1faeSThomas Huth     PnvChipType chip_type;
231e8a1faeSThomas Huth     const char *cpu_model;
241e8a1faeSThomas Huth     uint64_t    xscom_base;
251e8a1faeSThomas Huth     uint64_t    cfam_id;
261e8a1faeSThomas Huth     uint32_t    first_core;
271e8a1faeSThomas Huth } PnvChip;
281e8a1faeSThomas Huth 
291e8a1faeSThomas Huth static const PnvChip pnv_chips[] = {
301e8a1faeSThomas Huth     {
311e8a1faeSThomas Huth         .chip_type  = PNV_CHIP_POWER8,
321e8a1faeSThomas Huth         .cpu_model  = "POWER8",
331e8a1faeSThomas Huth         .xscom_base = 0x0003fc0000000000ull,
341e8a1faeSThomas Huth         .cfam_id    = 0x220ea04980000000ull,
351e8a1faeSThomas Huth         .first_core = 0x1,
361e8a1faeSThomas Huth     }, {
371e8a1faeSThomas Huth         .chip_type  = PNV_CHIP_POWER8NVL,
381e8a1faeSThomas Huth         .cpu_model  = "POWER8NVL",
391e8a1faeSThomas Huth         .xscom_base = 0x0003fc0000000000ull,
401e8a1faeSThomas Huth         .cfam_id    = 0x120d304980000000ull,
411e8a1faeSThomas Huth         .first_core = 0x1,
421e8a1faeSThomas Huth     },
431e8a1faeSThomas Huth     {
441e8a1faeSThomas Huth         .chip_type  = PNV_CHIP_POWER9,
451e8a1faeSThomas Huth         .cpu_model  = "POWER9",
461e8a1faeSThomas Huth         .xscom_base = 0x000603fc00000000ull,
471e8a1faeSThomas Huth         .cfam_id    = 0x220d104900008000ull,
481e8a1faeSThomas Huth         .first_core = 0x0,
491e8a1faeSThomas Huth     },
50*e1a821d4SNicholas Piggin     {
51*e1a821d4SNicholas Piggin         .chip_type  = PNV_CHIP_POWER10,
52*e1a821d4SNicholas Piggin         .cpu_model  = "POWER10",
53*e1a821d4SNicholas Piggin         .xscom_base = 0x000603fc00000000ull,
54*e1a821d4SNicholas Piggin         .cfam_id    = 0x120da04900008000ull,
55*e1a821d4SNicholas Piggin         .first_core = 0x0,
56*e1a821d4SNicholas Piggin     },
571e8a1faeSThomas Huth };
581e8a1faeSThomas Huth 
pnv_xscom_addr(const PnvChip * chip,uint32_t pcba)591e8a1faeSThomas Huth static uint64_t pnv_xscom_addr(const PnvChip *chip, uint32_t pcba)
601e8a1faeSThomas Huth {
611e8a1faeSThomas Huth     uint64_t addr = chip->xscom_base;
621e8a1faeSThomas Huth 
63*e1a821d4SNicholas Piggin     if (chip->chip_type == PNV_CHIP_POWER10) {
64*e1a821d4SNicholas Piggin         addr |= ((uint64_t) pcba << 3);
65*e1a821d4SNicholas Piggin     } else if (chip->chip_type == PNV_CHIP_POWER9) {
661e8a1faeSThomas Huth         addr |= ((uint64_t) pcba << 3);
671e8a1faeSThomas Huth     } else {
681e8a1faeSThomas Huth         addr |= (((uint64_t) pcba << 4) & ~0xffull) |
691e8a1faeSThomas Huth             (((uint64_t) pcba << 3) & 0x78);
701e8a1faeSThomas Huth     }
711e8a1faeSThomas Huth     return addr;
721e8a1faeSThomas Huth }
731e8a1faeSThomas Huth 
pnv_xscom_read(QTestState * qts,const PnvChip * chip,uint32_t pcba)741e8a1faeSThomas Huth static uint64_t pnv_xscom_read(QTestState *qts, const PnvChip *chip,
751e8a1faeSThomas Huth                                uint32_t pcba)
761e8a1faeSThomas Huth {
771e8a1faeSThomas Huth     return qtest_readq(qts, pnv_xscom_addr(chip, pcba));
781e8a1faeSThomas Huth }
791e8a1faeSThomas Huth 
test_xscom_cfam_id(QTestState * qts,const PnvChip * chip)801e8a1faeSThomas Huth static void test_xscom_cfam_id(QTestState *qts, const PnvChip *chip)
811e8a1faeSThomas Huth {
821e8a1faeSThomas Huth     uint64_t f000f = pnv_xscom_read(qts, chip, 0xf000f);
831e8a1faeSThomas Huth 
841e8a1faeSThomas Huth     g_assert_cmphex(f000f, ==, chip->cfam_id);
851e8a1faeSThomas Huth }
861e8a1faeSThomas Huth 
test_cfam_id(const void * data)871e8a1faeSThomas Huth static void test_cfam_id(const void *data)
881e8a1faeSThomas Huth {
891e8a1faeSThomas Huth     const PnvChip *chip = data;
901e8a1faeSThomas Huth     const char *machine = "powernv8";
911e8a1faeSThomas Huth     QTestState *qts;
921e8a1faeSThomas Huth 
931e8a1faeSThomas Huth     if (chip->chip_type == PNV_CHIP_POWER9) {
941e8a1faeSThomas Huth         machine = "powernv9";
95*e1a821d4SNicholas Piggin     } else if (chip->chip_type == PNV_CHIP_POWER10) {
96*e1a821d4SNicholas Piggin         machine = "powernv10";
971e8a1faeSThomas Huth     }
981e8a1faeSThomas Huth 
991e8a1faeSThomas Huth     qts = qtest_initf("-M %s -accel tcg -cpu %s",
1001e8a1faeSThomas Huth                       machine, chip->cpu_model);
1011e8a1faeSThomas Huth     test_xscom_cfam_id(qts, chip);
1021e8a1faeSThomas Huth     qtest_quit(qts);
1031e8a1faeSThomas Huth }
1041e8a1faeSThomas Huth 
1051e8a1faeSThomas Huth 
1061e8a1faeSThomas Huth #define PNV_XSCOM_EX_CORE_BASE    0x10000000ull
1071e8a1faeSThomas Huth #define PNV_XSCOM_EX_BASE(core) \
1081e8a1faeSThomas Huth     (PNV_XSCOM_EX_CORE_BASE | ((uint64_t)(core) << 24))
1091e8a1faeSThomas Huth #define PNV_XSCOM_P9_EC_BASE(core) \
1101e8a1faeSThomas Huth     ((uint64_t)(((core) & 0x1F) + 0x20) << 24)
111*e1a821d4SNicholas Piggin #define PNV_XSCOM_P10_EC_BASE(core) \
112*e1a821d4SNicholas Piggin     ((uint64_t)((((core) & ~0x3) + 0x20) << 24) + 0x20000 + \
113*e1a821d4SNicholas Piggin      (0x1000 << (3 - (core & 0x3))))
1141e8a1faeSThomas Huth 
1151e8a1faeSThomas Huth #define PNV_XSCOM_EX_DTS_RESULT0     0x50000
1161e8a1faeSThomas Huth 
test_xscom_core(QTestState * qts,const PnvChip * chip)1171e8a1faeSThomas Huth static void test_xscom_core(QTestState *qts, const PnvChip *chip)
1181e8a1faeSThomas Huth {
119*e1a821d4SNicholas Piggin     if (chip->chip_type == PNV_CHIP_POWER10) {
120*e1a821d4SNicholas Piggin         uint32_t first_core_thread_state =
121*e1a821d4SNicholas Piggin                  PNV_XSCOM_P10_EC_BASE(chip->first_core) + 0x412;
122*e1a821d4SNicholas Piggin         uint64_t thread_state;
123*e1a821d4SNicholas Piggin 
124*e1a821d4SNicholas Piggin         thread_state = pnv_xscom_read(qts, chip, first_core_thread_state);
125*e1a821d4SNicholas Piggin 
126*e1a821d4SNicholas Piggin         g_assert_cmphex(thread_state, ==, 0);
127*e1a821d4SNicholas Piggin     } else {
1281e8a1faeSThomas Huth         uint32_t first_core_dts0 = PNV_XSCOM_EX_DTS_RESULT0;
1291e8a1faeSThomas Huth         uint64_t dts0;
1301e8a1faeSThomas Huth 
131*e1a821d4SNicholas Piggin         if (chip->chip_type == PNV_CHIP_POWER9) {
1321e8a1faeSThomas Huth             first_core_dts0 |= PNV_XSCOM_P9_EC_BASE(chip->first_core);
133*e1a821d4SNicholas Piggin         } else { /* POWER8 */
134*e1a821d4SNicholas Piggin             first_core_dts0 |= PNV_XSCOM_EX_BASE(chip->first_core);
1351e8a1faeSThomas Huth         }
1361e8a1faeSThomas Huth 
1371e8a1faeSThomas Huth         dts0 = pnv_xscom_read(qts, chip, first_core_dts0);
1381e8a1faeSThomas Huth 
1391e8a1faeSThomas Huth         g_assert_cmphex(dts0, ==, 0x26f024f023f0000ull);
1401e8a1faeSThomas Huth     }
141*e1a821d4SNicholas Piggin }
1421e8a1faeSThomas Huth 
test_core(const void * data)1431e8a1faeSThomas Huth static void test_core(const void *data)
1441e8a1faeSThomas Huth {
1451e8a1faeSThomas Huth     const PnvChip *chip = data;
1461e8a1faeSThomas Huth     QTestState *qts;
1471e8a1faeSThomas Huth     const char *machine = "powernv8";
1481e8a1faeSThomas Huth 
1491e8a1faeSThomas Huth     if (chip->chip_type == PNV_CHIP_POWER9) {
1501e8a1faeSThomas Huth         machine = "powernv9";
151*e1a821d4SNicholas Piggin     } else if (chip->chip_type == PNV_CHIP_POWER10) {
152*e1a821d4SNicholas Piggin         machine = "powernv10";
1531e8a1faeSThomas Huth     }
1541e8a1faeSThomas Huth 
1551e8a1faeSThomas Huth     qts = qtest_initf("-M %s -accel tcg -cpu %s",
1561e8a1faeSThomas Huth                       machine, chip->cpu_model);
1571e8a1faeSThomas Huth     test_xscom_core(qts, chip);
1581e8a1faeSThomas Huth     qtest_quit(qts);
1591e8a1faeSThomas Huth }
1601e8a1faeSThomas Huth 
add_test(const char * name,void (* test)(const void * data))1611e8a1faeSThomas Huth static void add_test(const char *name, void (*test)(const void *data))
1621e8a1faeSThomas Huth {
1631e8a1faeSThomas Huth     int i;
1641e8a1faeSThomas Huth 
1651e8a1faeSThomas Huth     for (i = 0; i < ARRAY_SIZE(pnv_chips); i++) {
1661e8a1faeSThomas Huth         char *tname = g_strdup_printf("pnv-xscom/%s/%s", name,
1671e8a1faeSThomas Huth                                       pnv_chips[i].cpu_model);
1681e8a1faeSThomas Huth         qtest_add_data_func(tname, &pnv_chips[i], test);
1691e8a1faeSThomas Huth         g_free(tname);
1701e8a1faeSThomas Huth     }
1711e8a1faeSThomas Huth }
1721e8a1faeSThomas Huth 
main(int argc,char ** argv)1731e8a1faeSThomas Huth int main(int argc, char **argv)
1741e8a1faeSThomas Huth {
1751e8a1faeSThomas Huth     g_test_init(&argc, &argv, NULL);
1761e8a1faeSThomas Huth 
1771e8a1faeSThomas Huth     add_test("cfam_id", test_cfam_id);
1781e8a1faeSThomas Huth     add_test("core", test_core);
1791e8a1faeSThomas Huth     return g_test_run();
1801e8a1faeSThomas Huth }
181