// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later /* Copyright 2013-2019 IBM Corp. */ #include #include #include #include #include #include static struct proc_chip *chips[MAX_CHIPS]; enum proc_chip_quirks proc_chip_quirks; uint32_t pir_to_chip_id(uint32_t pir) { if (proc_gen == proc_gen_p10) return P10_PIR2GCID(pir); else if (proc_gen == proc_gen_p9) return P9_PIR2GCID(pir); else if (proc_gen == proc_gen_p8) return P8_PIR2GCID(pir); else assert(false); } uint32_t pir_to_core_id(uint32_t pir) { if (proc_gen == proc_gen_p10) { if (this_cpu()->is_fused_core) return P10_PIRFUSED2NORMALCOREID(pir); else return P10_PIR2COREID(pir); } else if (proc_gen == proc_gen_p9) { if (this_cpu()->is_fused_core) return P9_PIRFUSED2NORMALCOREID(pir); else return P9_PIR2COREID(pir); } else if (proc_gen == proc_gen_p8) { return P8_PIR2COREID(pir); } else { assert(false); } } uint32_t pir_to_fused_core_id(uint32_t pir) { if (proc_gen == proc_gen_p10) { if (this_cpu()->is_fused_core) return P10_PIR2FUSEDCOREID(pir); else return P10_PIR2COREID(pir); } else if (proc_gen == proc_gen_p9) { if (this_cpu()->is_fused_core) return P9_PIR2FUSEDCOREID(pir); else return P9_PIR2COREID(pir); } else if (proc_gen == proc_gen_p8) { return P8_PIR2COREID(pir); } else { assert(false); } } uint32_t pir_to_thread_id(uint32_t pir) { if (proc_gen == proc_gen_p10) { if (this_cpu()->is_fused_core) return P10_PIRFUSED2NORMALTHREADID(pir); else return P10_PIR2THREADID(pir); } else if (proc_gen == proc_gen_p9) { if (this_cpu()->is_fused_core) return P9_PIRFUSED2NORMALTHREADID(pir); else return P9_PIR2THREADID(pir); } else if (proc_gen == proc_gen_p8) { return P8_PIR2THREADID(pir); } else { assert(false); } } struct proc_chip *next_chip(struct proc_chip *chip) { unsigned int i; for (i = chip ? (chip->id + 1) : 0; i < MAX_CHIPS; i++) if (chips[i]) return chips[i]; return NULL; } struct proc_chip *get_chip(uint32_t chip_id) { if (chip_id >= MAX_CHIPS) return NULL; return chips[chip_id]; } static void init_chip(struct dt_node *dn) { struct proc_chip *chip; uint32_t id; const char *lc = NULL; id = dt_get_chip_id(dn); assert(id < MAX_CHIPS); assert(chips[id] == NULL); chip = zalloc(sizeof(struct proc_chip)); assert(chip); chip->id = id; chip->devnode = dn; chip->dbob_id = dt_prop_get_u32_def(dn, "ibm,dbob-id", 0xffffffff); chip->pcid = dt_prop_get_u32_def(dn, "ibm,proc-chip-id", 0xffffffff); if (dt_prop_get_u32_def(dn, "ibm,occ-functional-state", 0)) chip->occ_functional = true; else chip->occ_functional = false; list_head_init(&chip->i2cms); /* Update the location code for this chip. */ if (dt_has_node_property(dn, "ibm,loc-code", NULL)) lc = dt_prop_get(dn, "ibm,loc-code"); else if (dt_has_node_property(dn, "ibm,slot-location-code", NULL)) lc = dt_prop_get(dn, "ibm,slot-location-code"); if (lc) chip->loc_code = strdup(lc); chip->primary_topology = dt_prop_get_u32_def(dn, "ibm,primary-topology-index", 0xffffffff); prlog(PR_INFO, "CHIP: Initialised chip %d from %s\n", id, dn->name); chips[id] = chip; } void init_chips(void) { struct dt_node *xn; /* Detect mambo chip */ if (dt_find_by_path(dt_root, "/mambo")) { proc_chip_quirks |= QUIRK_NO_CHIPTOD | QUIRK_MAMBO_CALLOUTS | QUIRK_NO_F000F | QUIRK_NO_PBA | QUIRK_NO_OCC_IRQ | QUIRK_NO_RNG; enable_mambo_console(); prlog(PR_NOTICE, "CHIP: Detected Mambo simulator\n"); dt_for_each_compatible(dt_root, xn, "ibm,mambo-chip") init_chip(xn); } /* Detect simics */ if (dt_find_by_path(dt_root, "/simics")) { proc_chip_quirks |= QUIRK_SIMICS | QUIRK_NO_PBA | QUIRK_NO_OCC_IRQ | QUIRK_SLOW_SIM; tb_hz = 512000; prlog(PR_NOTICE, "CHIP: Detected Simics simulator\n"); } /* Detect Awan emulator */ xn = dt_find_by_path(dt_root, "/awan"); if (xn) { const char *model_type; proc_chip_quirks |= QUIRK_AWAN | QUIRK_SLOW_SIM | QUIRK_NO_PBA | QUIRK_NO_OCC_IRQ; tb_hz = 512000; model_type = dt_prop_get_def(xn, "device_type", (void *)"core"); if (strcmp(model_type, "core") == 0) { proc_chip_quirks |= QUIRK_NO_RNG | QUIRK_NO_CHIPTOD | QUIRK_NO_F000F; } prlog(PR_NOTICE, "CHIP: Detected Awan emulator %s model\n", model_type); } /* Detect Qemu */ if (dt_node_is_compatible(dt_root, "qemu,powernv") || dt_node_is_compatible(dt_root, "qemu,powernv8") || dt_node_is_compatible(dt_root, "qemu,powernv9") || dt_node_is_compatible(dt_root, "qemu,powernv10") || dt_find_by_path(dt_root, "/qemu")) { proc_chip_quirks |= QUIRK_QEMU | QUIRK_NO_DIRECT_CTL | QUIRK_NO_RNG; prlog(PR_NOTICE, "CHIP: Detected QEMU simulator\n"); } if (dt_find_by_path(dt_root, "/bml")) { proc_chip_quirks |= QUIRK_BML; prlog(PR_NOTICE, "CHIP: Detected BML\n"); } /* We walk the chips based on xscom nodes in the tree */ dt_for_each_compatible(dt_root, xn, "ibm,xscom") { init_chip(xn); } }