From 5a8e3c035c3727431be0143670df2ec7e6ce6016 Mon Sep 17 00:00:00 2001 From: Hristo Mitrev Date: Mon, 18 Nov 2024 19:29:32 +0200 Subject: [PATCH] adi: break down adi_config_ap to decrease nesting --- src/target/adi.c | 215 +++++++++++++++++++++++++---------------------- 1 file changed, 113 insertions(+), 102 deletions(-) diff --git a/src/target/adi.c b/src/target/adi.c index c1efd319c46..096a717ca39 100644 --- a/src/target/adi.c +++ b/src/target/adi.c @@ -347,38 +347,31 @@ static void adi_display_ap(const adiv5_access_port_s *const ap) #endif } -bool adi_configure_ap(adiv5_access_port_s *const ap) +bool adi_configure_mem_ap(adiv5_access_port_s *const ap) { - /* Grab the ID register and make sure the value is sane (non-zero) */ - ap->idr = adiv5_ap_read(ap, ADIV5_AP_IDR); - if (!ap->idr) - return false; const uint8_t ap_type = ADIV5_AP_IDR_TYPE(ap->idr); - const uint8_t ap_class = ADIV5_AP_IDR_CLASS(ap->idr); - DEBUG_INFO("AP %3u: IDR=%08" PRIx32, ap->apsel, ap->idr); - /* If this is a MEM-AP */ - if (ap_class == ADIV5_AP_IDR_CLASS_MEM && ap_type >= 1U && ap_type <= 8U) { - /* Grab the config, base and CSW registers */ - const uint32_t cfg = adiv5_ap_read(ap, ADIV5_AP_CFG); - ap->csw = adiv5_ap_read(ap, ADIV5_AP_CSW); - /* This reads the lower half of BASE */ - ap->base = adiv5_ap_read(ap, ADIV5_AP_BASE_LOW); - const uint8_t base_flags = (uint8_t)ap->base & (ADIV5_AP_BASE_FORMAT | ADIV5_AP_BASE_PRESENT); - /* Check if this is a 64-bit AP */ - if (cfg & ADIV5_AP_CFG_LARGE_ADDRESS) { - /* If this base value is invalid for a LPAE MEM-AP, bomb out here */ - if (base_flags == (ADIV5_AP_BASE_FORMAT_LEGACY | ADIV5_AP_BASE_PRESENT_NO_ENTRY)) { - DEBUG_INFO(" -> Invalid\n"); - return false; - } - /* Otherwise note this is a 64-bit AP and read the high part */ - ap->flags |= ADIV5_AP_FLAGS_64BIT; - ap->base |= (uint64_t)adiv5_ap_read(ap, ADIV5_AP_BASE_HIGH) << 32U; + + /* Grab the config, base and CSW registers */ + const uint32_t cfg = adiv5_ap_read(ap, ADIV5_AP_CFG); + ap->csw = adiv5_ap_read(ap, ADIV5_AP_CSW); + /* This reads the lower half of BASE */ + ap->base = adiv5_ap_read(ap, ADIV5_AP_BASE_LOW); + const uint8_t base_flags = (uint8_t)ap->base & (ADIV5_AP_BASE_FORMAT | ADIV5_AP_BASE_PRESENT); + /* Check if this is a 64-bit AP */ + if (cfg & ADIV5_AP_CFG_LARGE_ADDRESS) { + /* If this base value is invalid for a LPAE MEM-AP, bomb out here */ + if (base_flags == (ADIV5_AP_BASE_FORMAT_LEGACY | ADIV5_AP_BASE_PRESENT_NO_ENTRY)) { + DEBUG_INFO(" -> Invalid\n"); + return false; } - /* Check the Debug Base Address register for not-present. See ADIv5 Specification C2.6.1 */ - if (base_flags == (ADIV5_AP_BASE_FORMAT_ADIV5 | ADIV5_AP_BASE_PRESENT_NO_ENTRY) || - (!(ap->flags & ADIV5_AP_FLAGS_64BIT) && (uint32_t)ap->base == ADIV5_AP_BASE_NOT_PRESENT)) { - /* + /* Otherwise note this is a 64-bit AP and read the high part */ + ap->flags |= ADIV5_AP_FLAGS_64BIT; + ap->base |= (uint64_t)adiv5_ap_read(ap, ADIV5_AP_BASE_HIGH) << 32U; + } + /* Check the Debug Base Address register for not-present. See ADIv5 Specification C2.6.1 */ + if (base_flags == (ADIV5_AP_BASE_FORMAT_ADIV5 | ADIV5_AP_BASE_PRESENT_NO_ENTRY) || + (!(ap->flags & ADIV5_AP_FLAGS_64BIT) && (uint32_t)ap->base == ADIV5_AP_BASE_NOT_PRESENT)) { + /* * Debug Base Address not present in this MEM-AP * No debug entries... useless AP * AP0 on STM32MP157C reads 0x00000002 @@ -387,88 +380,106 @@ bool adi_configure_ap(adiv5_access_port_s *const ap) * valid debug components on AP0, so we have to have an exception * for this part family. */ - if (ap->dp->target_designer_code != JEP106_MANUFACTURER_TEXAS || ap->base != 0xf0000002U) { - DEBUG_INFO(" -> Not Present\n"); - return false; - } - } - /* Make sure we only pay attention to the base address, not the presence and format bits */ - ap->base &= ADIV5_AP_BASE_BASEADDR; - /* Check if the AP is disabled, skipping it if that is the case */ - if ((ap->csw & ADIV5_AP_CSW_AP_ENABLED) == 0U) { - DEBUG_INFO(" -> Disabled\n"); + if (ap->dp->target_designer_code != JEP106_MANUFACTURER_TEXAS || ap->base != 0xf0000002U) { + DEBUG_INFO(" -> Not Present\n"); return false; } + } + /* Make sure we only pay attention to the base address, not the presence and format bits */ + ap->base &= ADIV5_AP_BASE_BASEADDR; + /* Check if the AP is disabled, skipping it if that is the case */ + if ((ap->csw & ADIV5_AP_CSW_AP_ENABLED) == 0U) { + DEBUG_INFO(" -> Disabled\n"); + return false; + } - /* Apply bus-common fixups to the CSW value */ - ap->csw &= ~(ADIV5_AP_CSW_SIZE_MASK | ADIV5_AP_CSW_ADDRINC_MASK); - ap->csw |= ADIV5_AP_CSW_DBGSWENABLE; + /* Apply bus-common fixups to the CSW value */ + ap->csw &= ~(ADIV5_AP_CSW_SIZE_MASK | ADIV5_AP_CSW_ADDRINC_MASK); + ap->csw |= ADIV5_AP_CSW_DBGSWENABLE; - switch (ap_type) { - case ADIV5_AP_IDR_TYPE_APB2_3: - /* We have no prot modes on APB2 and APB3 */ - break; - case ADIV5_AP_IDR_TYPE_AXI3_4: - /* XXX: Handle AXI4 w/ ACE-Lite which makes Mode and Type do ~things~™ (§E1.3.1, pg237) */ - /* Clear any existing prot modes and disable memory tagging */ - ap->csw &= ~(ADIV5_AP_CSW_AXI3_4_PROT_MASK | ADIV5_AP_CSW_AXI_MTE); - /* Check if secure access is allowed and enable it if so */ - if (ap->csw & ADIV5_AP_CSW_SPIDEN) - ap->csw &= ~ADIV5_AP_CSW_AXI_PROT_NS; - else - ap->csw |= ADIV5_AP_CSW_AXI_PROT_NS; - /* Always privileged accesses */ - ap->csw |= ADIV5_AP_CSW_AXI_PROT_PRIV; - break; - case ADIV5_AP_IDR_TYPE_AXI5: - /* Clear any existing prot modes and disable memory tagging */ - ap->csw &= ~(ADIV5_AP_CSW_AXI5_PROT_MASK | ADIV5_AP_CSW_AXI_MTE); - /* Check if secure access is allowed and enable it if so */ - if (ap->csw & ADIV5_AP_CSW_SPIDEN) - ap->csw &= ~ADIV5_AP_CSW_AXI_PROT_NS; - else - ap->csw |= ADIV5_AP_CSW_AXI_PROT_NS; - /* Always privileged accesses */ - ap->csw |= ADIV5_AP_CSW_AXI_PROT_PRIV; - break; - case ADIV5_AP_IDR_TYPE_AHB3: - case ADIV5_AP_IDR_TYPE_AHB5: - case ADIV5_AP_IDR_TYPE_AHB5_HPROT: - /* Clear any existing HPROT modes */ - ap->csw &= ~ADIV5_AP_CSW_AHB_HPROT_MASK; - /* + switch (ap_type) { + case ADIV5_AP_IDR_TYPE_APB2_3: + /* We have no prot modes on APB2 and APB3 */ + break; + case ADIV5_AP_IDR_TYPE_AXI3_4: + /* XXX: Handle AXI4 w/ ACE-Lite which makes Mode and Type do ~things~™ (§E1.3.1, pg237) */ + /* Clear any existing prot modes and disable memory tagging */ + ap->csw &= ~(ADIV5_AP_CSW_AXI3_4_PROT_MASK | ADIV5_AP_CSW_AXI_MTE); + /* Check if secure access is allowed and enable it if so */ + if (ap->csw & ADIV5_AP_CSW_SPIDEN) + ap->csw &= ~ADIV5_AP_CSW_AXI_PROT_NS; + else + ap->csw |= ADIV5_AP_CSW_AXI_PROT_NS; + /* Always privileged accesses */ + ap->csw |= ADIV5_AP_CSW_AXI_PROT_PRIV; + break; + case ADIV5_AP_IDR_TYPE_AXI5: + /* Clear any existing prot modes and disable memory tagging */ + ap->csw &= ~(ADIV5_AP_CSW_AXI5_PROT_MASK | ADIV5_AP_CSW_AXI_MTE); + /* Check if secure access is allowed and enable it if so */ + if (ap->csw & ADIV5_AP_CSW_SPIDEN) + ap->csw &= ~ADIV5_AP_CSW_AXI_PROT_NS; + else + ap->csw |= ADIV5_AP_CSW_AXI_PROT_NS; + /* Always privileged accesses */ + ap->csw |= ADIV5_AP_CSW_AXI_PROT_PRIV; + break; + case ADIV5_AP_IDR_TYPE_AHB3: + case ADIV5_AP_IDR_TYPE_AHB5: + case ADIV5_AP_IDR_TYPE_AHB5_HPROT: + /* Clear any existing HPROT modes */ + ap->csw &= ~ADIV5_AP_CSW_AHB_HPROT_MASK; + /* * Ensure that MasterType is set to generate transactions as requested from the AHB-AP, * and that we generate privileged data requests via the HPROT bits */ - ap->csw |= ADIV5_AP_CSW_AHB_MASTERTYPE | ADIV5_AP_CSW_AHB_HPROT_DATA | ADIV5_AP_CSW_AHB_HPROT_PRIV; - /* Check to see if secure access is supported and allowed */ - if (ap->csw & ADIV5_AP_CSW_SPIDEN) - ap->csw &= ~ADIV5_AP_CSW_AHB_HNONSEC; - else - ap->csw |= ADIV5_AP_CSW_AHB_HNONSEC; - break; - case ADIV5_AP_IDR_TYPE_APB4_5: - /* Clear any existing prot modes and disable memory tagging */ - ap->csw &= ~ADIV5_AP_CSW_APB_PPROT_MASK; - /* Check if secure access is allowed and enable it if so */ - if (ap->csw & ADIV5_AP_CSW_SPIDEN) - ap->csw &= ~ADIV5_AP_CSW_APB_PPROT_NS; - else - ap->csw |= ADIV5_AP_CSW_APB_PPROT_NS; - ap->csw |= ADIV5_AP_CSW_APB_PPROT_PRIV; - break; - default: - DEBUG_ERROR("Unhandled AP type %u\n", ap_type); - } - - if (cfg & ADIV5_AP_CFG_LARGE_ADDRESS) - DEBUG_INFO(" CFG=%08" PRIx32 " BASE=%08" PRIx32 "%08" PRIx32 " CSW=%08" PRIx32, cfg, - (uint32_t)(ap->base >> 32U), (uint32_t)ap->base, ap->csw); + ap->csw |= ADIV5_AP_CSW_AHB_MASTERTYPE | ADIV5_AP_CSW_AHB_HPROT_DATA | ADIV5_AP_CSW_AHB_HPROT_PRIV; + /* Check to see if secure access is supported and allowed */ + if (ap->csw & ADIV5_AP_CSW_SPIDEN) + ap->csw &= ~ADIV5_AP_CSW_AHB_HNONSEC; else - DEBUG_INFO(" CFG=%08" PRIx32 " BASE=%08" PRIx32 " CSW=%08" PRIx32, cfg, (uint32_t)ap->base, ap->csw); + ap->csw |= ADIV5_AP_CSW_AHB_HNONSEC; + break; + case ADIV5_AP_IDR_TYPE_APB4_5: + /* Clear any existing prot modes and disable memory tagging */ + ap->csw &= ~ADIV5_AP_CSW_APB_PPROT_MASK; + /* Check if secure access is allowed and enable it if so */ + if (ap->csw & ADIV5_AP_CSW_SPIDEN) + ap->csw &= ~ADIV5_AP_CSW_APB_PPROT_NS; + else + ap->csw |= ADIV5_AP_CSW_APB_PPROT_NS; + ap->csw |= ADIV5_AP_CSW_APB_PPROT_PRIV; + break; + default: + DEBUG_ERROR("Unhandled AP type %u\n", ap_type); + } - if (ap->csw & ADIV5_AP_CSW_TRINPROG) { - DEBUG_ERROR("AP %3u: Transaction in progress. AP is not usable!\n", ap->apsel); + if (cfg & ADIV5_AP_CFG_LARGE_ADDRESS) + DEBUG_INFO(" CFG=%08" PRIx32 " BASE=%08" PRIx32 "%08" PRIx32 " CSW=%08" PRIx32, cfg, + (uint32_t)(ap->base >> 32U), (uint32_t)ap->base, ap->csw); + else + DEBUG_INFO(" CFG=%08" PRIx32 " BASE=%08" PRIx32 " CSW=%08" PRIx32, cfg, (uint32_t)ap->base, ap->csw); + + if (ap->csw & ADIV5_AP_CSW_TRINPROG) { + DEBUG_ERROR("AP %3u: Transaction in progress. AP is not usable!\n", ap->apsel); + return false; + } + + return true; +} + +bool adi_configure_ap(adiv5_access_port_s *const ap) +{ + /* Grab the ID register and make sure the value is sane (non-zero) */ + ap->idr = adiv5_ap_read(ap, ADIV5_AP_IDR); + if (!ap->idr) + return false; + const uint8_t ap_type = ADIV5_AP_IDR_TYPE(ap->idr); + const uint8_t ap_class = ADIV5_AP_IDR_CLASS(ap->idr); + DEBUG_INFO("AP %3u: IDR=%08" PRIx32, ap->apsel, ap->idr); + /* If this is a MEM-AP */ + if (ap_class == ADIV5_AP_IDR_CLASS_MEM && ap_type >= 1U && ap_type <= 8U) { + if (!adi_configure_mem_ap(ap)) { return false; } }