blob: c1da99a313069fc4237c0d576e3930cbbc3be094 [file] [log] [blame]
Arunachalam Ganapathybbb13052025-06-24 14:00:06 +01001/*
2 * Copyright (c) 2025, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8#include <common_def.h>
9#include <errno.h>
10#include <stddef.h>
11#include <debug.h>
12#include <mmio.h>
13#include <pcie.h>
14#include <pcie_spec.h>
15#include <pcie_dvsec_rmeda.h>
16#include <platform.h>
17#include <tftf_lib.h>
18
19/*
20 * Check if the DVSEC header matches RME Sys Arch spec
21 *
22 * DVSEC_REVISION must be 0
23 * DVSEC_VENDOR_ID must be Arm
24 * DVSEC_ID must be RME_DA
25 */
26static bool is_dvsec_arm_rmeda(uint32_t rp_bdf, uint32_t dvsec_base)
27{
28 uint32_t hdr1 = 0U;
29 uint32_t hdr2 = 0U;
30
31 hdr1 = pcie_read_cfg(rp_bdf, dvsec_base + PCIE_ECAP_DVSEC_HDR1_OFFSET);
32 hdr2 = pcie_read_cfg(rp_bdf, dvsec_base + PCIE_ECAP_DVSEC_HDR2_OFFSET);
33
34 if ((EXTRACT(DVSEC_HDR1_VENDOR_ID, hdr1) == DVSEC_VENDOR_ID_ARM) &&
35 (EXTRACT(DVSEC_HDR1_REVISION, hdr1) == DVSEC_REVISION_0) &&
36 (EXTRACT(DVSEC_HDR2_DVSEC_ID, hdr2) == DVSEC_ID_RME_DA)) {
37 return true;
38 }
39
40 return false;
41}
42
43/*
44 * Traverse all DVSEC extended capability and return the first RMEDA DVSEC if the
45 * header, revision are expected as mentioned in RME System Architecture.
46 */
47uint32_t pcie_find_rmeda_capability(uint32_t rp_bdf, uint32_t *cid_offset)
48{
49 uint32_t ech;
50 unsigned int dvsec_offset;
51 uint16_t next_cap_offset;
52
53 dvsec_offset = PCIE_ECAP_START;
54 do {
55 assert((dvsec_offset + sizeof(ech)) < SZ_4K);
56
57 ech = pcie_read_cfg(rp_bdf, dvsec_offset);
58
59 /* Check for PCIE_ECH_CAP_VER_1 as well? */
60 if ((EXTRACT(PCIE_ECH_ID, ech) == ECID_DVSEC) &&
61 is_dvsec_arm_rmeda(rp_bdf, dvsec_offset)) {
62 *cid_offset = dvsec_offset;
63 return PCIE_SUCCESS;
64 }
65
66 next_cap_offset = EXTRACT(PCIE_ECH_NEXT_CAP_OFFSET, ech);
67 dvsec_offset += next_cap_offset;
68 } while ((next_cap_offset != 0U) && (dvsec_offset < PCIE_ECAP_END));
69
70 return PCIE_CAP_NOT_FOUND;
71}