From 28abe44fae7b4d4a18333c2f0079bc5d3c0c2ccc Mon Sep 17 00:00:00 2001 From: Deepa Karthikeyan Date: Thu, 4 Jan 2024 01:43:51 -0600 Subject: [PATCH] Add getscom support for odyssey chipunit Added the translation required for the odyssey chipunit like memport. With this change, the getscom and the putscom support for odyssey chipunits shall work as expected. Tested and Working as expected. root@p10bmc:/tmp# putscom odyssey c0002040 -p2 deadbeefdeadbeef odyssey k0:n0:s0:p02 /usr/bin/edbg putscom odyssey c0002040 -p2 deadbeefdeadbeef root@p10bmc:/tmp# getscom odyssey c0002040 -all odyssey k0:n0:s0:p02 0xDEADBEEFDEADBEEF odyssey k0:n0:s0:p03 0x004011000A000640 odyssey k0:n0:s0:p34 0x004011000A000640 odyssey k0:n0:s0:p35 0x004011000A000640 /usr/bin/edbg getscom odyssey c0002040 -all root@p10bmc:/tmp# putscom odyssey c0002040 -p2 004011000A000640 odyssey k0:n0:s0:p02 /usr/bin/edbg putscom odyssey c0002040 -p2 004011000A000640 root@p10bmc:/tmp# getscom odyssey c0002040 -all odyssey k0:n0:s0:p02 0x004011000A000640 odyssey k0:n0:s0:p03 0x004011000A000640 odyssey k0:n0:s0:p34 0x004011000A000640 odyssey k0:n0:s0:p35 0x004011000A000640 /usr/bin/edbg getscom odyssey c0002040 -all Signed-off-by: Deepa Karthikeyan --- libpdbg/dtb.c | 14 +++++++++++ libpdbg/p10_fapi_targets.c | 50 +++++++++++++++++++++++++++++++++++++- libpdbg/p10_scom_addr.h | 7 ++++++ libpdbg/target.c | 42 +++++++++++++++++++++++++++++--- libpdbg/target.h | 8 ++++++ 5 files changed, 116 insertions(+), 5 deletions(-) diff --git a/libpdbg/dtb.c b/libpdbg/dtb.c index b4e2084d2b..2ca99f3dfe 100644 --- a/libpdbg/dtb.c +++ b/libpdbg/dtb.c @@ -627,6 +627,20 @@ bool is_ody_ocmb_chip(struct pdbg_target *target) return false; } +bool is_child_of_ody_chip(struct pdbg_target *target) +{ + struct pdbg_target *ocmb = NULL; + assert(target); + + ocmb = pdbg_target_parent("ocmb", target); + /*If it has a parent and the parent is of odyssey ocmb chip + return true */ + if( (ocmb) && (is_ody_ocmb_chip(ocmb)) ) + return true; + + return false; +} + __attribute__((destructor)) static void pdbg_close_targets(void) { diff --git a/libpdbg/p10_fapi_targets.c b/libpdbg/p10_fapi_targets.c index d64829b199..4c7322ef68 100644 --- a/libpdbg/p10_fapi_targets.c +++ b/libpdbg/p10_fapi_targets.c @@ -514,12 +514,60 @@ static struct smpgroup p10_smpgroup = { }; DECLARE_HW_UNIT(p10_smpgroup); +static uint64_t p10_memport_translate(struct mem_port *memport, uint64_t addr) +{ + /*If this memport is a child of odyssey ocmb, we need to perform translation*/ + struct pdbg_target *target = get_parent(t(memport), false); + if(strcmp(target->class,"ocmb") == 0) + { + if(!is_ody_ocmb_chip(target)) + { + //If it is not odyssey chip, no translation is required. + return 0; + } + } + else + { + //It should not come here at all. memport is not under ocmb!!! + return 0; + } + const uint8_t ODY_MEMPORT0_RING_ID = 0x6; // RDF0 + const uint8_t ODY_MEMPORT1_RING_ID = 0xA; // RDF1 + const uint8_t ODY_MEMPORT0_PHY_RING_ID = 0xC; + const uint8_t ODY_MEMPORT1_PHY_RING_ID = 0xD; + uint8_t l_ring = get_ring_id(addr); + if (l_ring == ODY_MEMPORT0_RING_ID || l_ring == ODY_MEMPORT1_RING_ID) + { + if (pdbg_target_index(t(memport)) == 0) + { + set_ody_ring_id(addr, ODY_MEMPORT0_RING_ID); + } + else + { + set_ody_ring_id(addr, ODY_MEMPORT1_RING_ID); + } + } + + if (l_ring == ODY_MEMPORT0_PHY_RING_ID || l_ring == ODY_MEMPORT1_PHY_RING_ID) + { + if (pdbg_target_index(t(memport)) == 0) + { + set_ody_ring_id(addr, ODY_MEMPORT0_PHY_RING_ID); + } + else + { + set_ody_ring_id(addr, ODY_MEMPORT1_PHY_RING_ID); + } + } + return addr; +} + struct mem_port p10_mem_port = { .target = { .name = "POWER10 mem_port", .compatible = "ibm,power10-memport", .class = "mem_port", - .translate = no_translate, + .translate = translate_cast(p10_memport_translate), }, }; DECLARE_HW_UNIT(p10_mem_port); diff --git a/libpdbg/p10_scom_addr.h b/libpdbg/p10_scom_addr.h index f307e469d9..97a03375bf 100644 --- a/libpdbg/p10_scom_addr.h +++ b/libpdbg/p10_scom_addr.h @@ -97,6 +97,13 @@ static uint64_t set_io_lane(uint64_t addr, uint64_t lane) return addr; } +static uint64_t set_ody_ring_id(uint64_t addr, uint8_t ring) +{ + addr &= 0xFFFFFFFFFFFFC3FFULL; + addr |= ((ring & 0xF) << 10); + return addr; +} + static uint8_t get_sat_id(uint64_t addr) { return ((addr >> 6) & 0xF); diff --git a/libpdbg/target.c b/libpdbg/target.c index 0e8061b643..9a4cfb62a0 100644 --- a/libpdbg/target.c +++ b/libpdbg/target.c @@ -507,7 +507,17 @@ int ocmb_getscom(struct pdbg_target *target, uint64_t addr, uint64_t *val) { struct ocmb *ocmb; - assert(pdbg_target_is_class(target, "ocmb")); + assert(pdbg_target_is_class(target, "ocmb") || is_child_of_ody_chip(target)); + + /*TODO: https://jsw.ibm.com/browse/PFEBMC-1931 + Handling Odyssey as a special case can be removed, + once device tree hierarchy for ocmb is fixed */ + /*It is memport or perv under odyssey ocmb, + so we need to translate before calling getscom */ + if(is_child_of_ody_chip(target)) + { + target = get_class_target_addr(target, "ocmb", &addr); + } if (pdbg_target_status(target) != PDBG_TARGET_ENABLED) return -1; @@ -526,7 +536,17 @@ int ocmb_putscom(struct pdbg_target *target, uint64_t addr, uint64_t val) { struct ocmb *ocmb; - assert(pdbg_target_is_class(target, "ocmb")); + assert(pdbg_target_is_class(target, "ocmb") || is_child_of_ody_chip(target)); + + /*TODO: https://jsw.ibm.com/browse/PFEBMC-1931 + Handling Odyssey as a special case can be removed, + once device tree hierarchy for ocmb is fixed */ + /*It is memport or perv under odyssey ocmb, + so we need to translate before calling getscom */ + if(is_child_of_ody_chip(target)) + { + target = get_class_target_addr(target, "ocmb", &addr); + } if (pdbg_target_status(target) != PDBG_TARGET_ENABLED) return -1; @@ -590,7 +610,21 @@ struct pdbg_target_class *get_target_class(struct pdbg_target *target) are failing, for now treating ody ocmb as special case*/ enum pdbg_target_status pdbg_target_probe_ody_ocmb(struct pdbg_target *target) { - assert(is_ody_ocmb_chip(target)); + assert(is_ody_ocmb_chip(target) || is_child_of_ody_chip(target)); + + if(is_child_of_ody_chip(target)) + { + if (target && target->probe && target->probe(target)) { + target->status = PDBG_TARGET_NONEXISTENT; + return PDBG_TARGET_NONEXISTENT; + } + target->status = PDBG_TARGET_ENABLED; + + //point to the ocmb target and continue, it will not be NULL for sure + struct pdbg_target *parent_target = pdbg_target_parent("ocmb", target); + return pdbg_target_probe_ody_ocmb(parent_target); + } + if(pdbg_get_backend() == PDBG_BACKEND_KERNEL) { struct pdbg_target *pibtarget = get_ody_pib_target(target); @@ -667,7 +701,7 @@ enum pdbg_target_status pdbg_target_probe(struct pdbg_target *target) /* odyssey ddr5 ocmb is a chip itself but in device tree it is placed under chiplet, mc, mcc, omi so do not probe parent targets. */ - if(is_ody_ocmb_chip(target)) + if(is_ody_ocmb_chip(target) || is_child_of_ody_chip(target)) return pdbg_target_probe_ody_ocmb(target); parent = get_parent(target, false); diff --git a/libpdbg/target.h b/libpdbg/target.h index c3353275d0..a0bd744e05 100644 --- a/libpdbg/target.h +++ b/libpdbg/target.h @@ -116,6 +116,14 @@ void clear_target_classes(); */ bool is_ody_ocmb_chip(struct pdbg_target *target); +/** + * @brief Return true if given target is child of odyssey chip + * @param[in] target - pdbg target + * + * @return true if target is of child of odyssey ocmb chip + */ +bool is_child_of_ody_chip(struct pdbg_target *target); + /** * @brief Return matching backend sbefifo target for ocmb target * @param[in] target - pdbg target