arm-trusted-firmware/plat/xilinx/zynqmp/aarch64/zynqmp_common.c
Saivardhan Thatikonda e14ae4b301 fix(xilinx): dcc console tests failing
The commit a6485b2b3b ("refactor(delay-timer): add timer
callback functions") is breaking DCC console due to uninitialized
timer ops structure. Fix it by moving generic delay timer init
prior to console setup to make sure that time is setup before DCC
console setup.

Fixes: a6485b2b3b ("refactor(delay-timer): add timer callback
functions")

Change-Id: I67910332773741c0b08f02feb232efab6356db12
Signed-off-by: Saivardhan Thatikonda <saivardhan.thatikonda@amd.com>
2025-01-21 19:02:51 +05:30

406 lines
7.3 KiB
C

/*
* Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdbool.h>
#include <string.h>
#include <common/debug.h>
#include <lib/mmio.h>
#include <lib/smccc.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat/common/platform.h>
#include <plat_arm.h>
#include <services/arm_arch_svc.h>
#include <plat_ipi.h>
#include <plat_private.h>
#include <plat_startup.h>
#include "zynqmp_pm_api_sys.h"
/*
* Table of regions to map using the MMU.
* This doesn't include TZRAM as the 'mem_layout' argument passed to
* configure_mmu_elx() will give the available subset of that,
*/
const mmap_region_t plat_zynqmp_mmap[] = {
MAP_REGION_FLAT(DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(CRF_APB_BASE, CRF_APB_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
{0}
};
const mmap_region_t *plat_get_mmap(void)
{
return plat_zynqmp_mmap;
}
static uint32_t zynqmp_get_silicon_ver(void)
{
static uint32_t ver;
if (ver == 0U) {
ver = mmio_read_32(ZYNQMP_CSU_BASEADDR +
ZYNQMP_CSU_VERSION_OFFSET);
ver &= ZYNQMP_SILICON_VER_MASK;
ver >>= ZYNQMP_SILICON_VER_SHIFT;
}
return ver;
}
uint32_t get_uart_clk(void)
{
unsigned int ver = zynqmp_get_silicon_ver();
if (ver == ZYNQMP_CSU_VERSION_QEMU) {
return 133000000;
} else {
return 100000000;
}
}
#if LOG_LEVEL >= LOG_LEVEL_NOTICE
static const struct {
uint8_t id;
bool evexists;
uint16_t ver;
char *name;
} __packed zynqmp_devices[] = {
{
.id = 0x10,
.name = "XCZU3EG",
},
{
.id = 0x10,
.ver = 0x2c,
.name = "XCZU3CG",
},
{
.id = 0x11,
.name = "XCZU2EG",
},
{
.id = 0x11,
.ver = 0x2c,
.name = "XCZU2CG",
},
{
.id = 0x20,
.name = "XCZU5EV",
.evexists = true,
},
{
.id = 0x20,
.ver = 0x100,
.name = "XCZU5EG",
.evexists = true,
},
{
.id = 0x20,
.ver = 0x12c,
.name = "XCZU5CG",
},
{
.id = 0x21,
.name = "XCZU4EV",
.evexists = true,
},
{
.id = 0x21,
.ver = 0x100,
.name = "XCZU4EG",
.evexists = true,
},
{
.id = 0x21,
.ver = 0x12c,
.name = "XCZU4CG",
},
{
.id = 0x30,
.name = "XCZU7EV",
.evexists = true,
},
{
.id = 0x30,
.ver = 0x100,
.name = "XCZU7EG",
.evexists = true,
},
{
.id = 0x30,
.ver = 0x12c,
.name = "XCZU7CG",
},
{
.id = 0x38,
.name = "XCZU9EG",
},
{
.id = 0x38,
.ver = 0x2c,
.name = "XCZU9CG",
},
{
.id = 0x39,
.name = "XCZU6EG",
},
{
.id = 0x39,
.ver = 0x2c,
.name = "XCZU6CG",
},
{
.id = 0x40,
.name = "XCZU11EG",
},
{
.id = 0x50,
.name = "XCZU15EG",
},
{
.id = 0x58,
.name = "XCZU19EG",
},
{
.id = 0x59,
.name = "XCZU17EG",
},
{
.id = 0x60,
.name = "XCZU28DR",
},
{
.id = 0x61,
.name = "XCZU21DR",
},
{
.id = 0x62,
.name = "XCZU29DR",
},
{
.id = 0x63,
.name = "XCZU23DR",
},
{
.id = 0x64,
.name = "XCZU27DR",
},
{
.id = 0x65,
.name = "XCZU25DR",
},
{
.id = 0x66,
.name = "XCZU39DR",
},
{
.id = 0x7d,
.name = "XCZU43DR",
},
{
.id = 0x78,
.name = "XCZU46DR",
},
{
.id = 0x7f,
.name = "XCZU47DR",
},
{
.id = 0x7b,
.name = "XCZU48DR",
},
{
.id = 0x7e,
.name = "XCZU49DR",
},
};
#define ZYNQMP_PL_STATUS_BIT 9
#define ZYNQMP_PL_STATUS_MASK BIT(ZYNQMP_PL_STATUS_BIT)
#define ZYNQMP_CSU_VERSION_MASK ~(ZYNQMP_PL_STATUS_MASK)
#define SILICON_ID_XCK24 0x4712093U
#define SILICON_ID_XCK26 0x4724093U
static char *zynqmp_get_silicon_idcode_name(void)
{
uint32_t id, ver, chipid[2];
size_t i, j, len;
const char *name = "EG/EV";
if (pm_get_chipid(chipid) != PM_RET_SUCCESS) {
return "XCZUUNKN";
}
id = chipid[0] & (ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK |
ZYNQMP_CSU_IDCODE_SVD_MASK);
id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
ver = chipid[1] >> ZYNQMP_EFUSE_IPDISABLE_SHIFT;
for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
if ((zynqmp_devices[i].id == id) &&
(zynqmp_devices[i].ver == (ver & ZYNQMP_CSU_VERSION_MASK))) {
break;
}
}
if (i >= ARRAY_SIZE(zynqmp_devices)) {
switch (chipid[0]) {
case SILICON_ID_XCK24:
return "XCK24";
case SILICON_ID_XCK26:
return "XCK26";
default:
return "XCZUUNKN";
}
}
if (!zynqmp_devices[i].evexists) {
return zynqmp_devices[i].name;
}
if ((ver & ZYNQMP_PL_STATUS_MASK) != 0U) {
return zynqmp_devices[i].name;
}
len = strlen(zynqmp_devices[i].name) - 2U;
for (j = 0; j < strlen(name); j++) {
zynqmp_devices[i].name[len] = name[j];
len++;
}
zynqmp_devices[i].name[len] = '\0';
return zynqmp_devices[i].name;
}
static unsigned int zynqmp_get_rtl_ver(void)
{
uint32_t ver;
ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
ver &= ZYNQMP_RTL_VER_MASK;
ver >>= ZYNQMP_RTL_VER_SHIFT;
return ver;
}
static char *zynqmp_print_silicon_idcode(void)
{
uint32_t id, maskid, tmp;
id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
tmp = id;
tmp &= ZYNQMP_CSU_IDCODE_XILINX_ID_MASK |
ZYNQMP_CSU_IDCODE_FAMILY_MASK;
maskid = (ZYNQMP_CSU_IDCODE_XILINX_ID << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT) |
(ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT);
if (tmp != maskid) {
ERROR("Incorrect IDCODE 0x%x, maskid 0x%x\n", id, maskid);
return "UNKN";
}
VERBOSE("IDCODE 0x%x\n", id);
return zynqmp_get_silicon_idcode_name();
}
int32_t plat_is_smccc_feature_available(u_register_t fid)
{
switch (fid) {
case SMCCC_ARCH_SOC_ID:
return SMC_ARCH_CALL_SUCCESS;
default:
return SMC_ARCH_CALL_NOT_SUPPORTED;
}
return SMC_ARCH_CALL_NOT_SUPPORTED;
}
int32_t plat_get_soc_version(void)
{
uint32_t chip_id = zynqmp_get_silicon_ver();
uint32_t manfid = SOC_ID_SET_JEP_106(JEDEC_XILINX_BKID, JEDEC_XILINX_MFID);
uint32_t result = (manfid | (chip_id & 0xFFFFU));
return (int32_t)result;
}
int32_t plat_get_soc_revision(void)
{
return (int32_t)mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
}
static uint32_t zynqmp_get_ps_ver(void)
{
uint32_t ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
ver &= ZYNQMP_PS_VER_MASK;
ver >>= ZYNQMP_PS_VER_SHIFT;
return ver + 1U;
}
static void zynqmp_print_platform_name(void)
{
uint32_t ver = zynqmp_get_silicon_ver();
uint32_t rtl = zynqmp_get_rtl_ver();
const char *label = "Unknown";
switch (ver) {
case ZYNQMP_CSU_VERSION_QEMU:
label = "QEMU";
break;
case ZYNQMP_CSU_VERSION_SILICON:
label = "silicon";
break;
default:
/* Do nothing in default case */
break;
}
VERBOSE("TF-A running on %s/%s at 0x%x\n",
zynqmp_print_silicon_idcode(), label, BL31_BASE);
VERBOSE("TF-A running on v%d/RTL%d.%d\n",
zynqmp_get_ps_ver(), (rtl & 0xf0U) >> 4U, rtl & 0xfU);
}
#else
static inline void zynqmp_print_platform_name(void) { }
#endif
uint32_t zynqmp_get_bootmode(void)
{
uint32_t r;
enum pm_ret_status ret;
ret = pm_mmio_read(CRL_APB_BOOT_MODE_USER, &r);
if (ret != PM_RET_SUCCESS) {
r = mmio_read_32(CRL_APB_BOOT_MODE_USER);
}
return r & CRL_APB_BOOT_MODE_MASK;
}
void zynqmp_config_setup(void)
{
/* Configure IPI data for ZynqMP */
zynqmp_ipi_config_table_init();
zynqmp_print_platform_name();
}
uint32_t plat_get_syscnt_freq2(void)
{
uint32_t ver = zynqmp_get_silicon_ver();
if (ver == ZYNQMP_CSU_VERSION_QEMU) {
return 65000000;
} else {
return mmio_read_32((uint64_t)IOU_SCNTRS_BASEFREQ);
}
}