diff --git a/core/arch/arm/plat-qcom/bobcat/arch.mk b/core/arch/arm/plat-qcom/bobcat/arch.mk new file mode 100644 index 000000000..e3b71bcb2 --- /dev/null +++ b/core/arch/arm/plat-qcom/bobcat/arch.mk @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: BSD-2-Clause +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +CFG_QCOM_SEC_WDOG ?= y diff --git a/core/arch/arm/plat-qcom/bobcat/ipq52xx/target.mk b/core/arch/arm/plat-qcom/bobcat/ipq52xx/target.mk index 8b1d18043..db46fe6ff 100644 --- a/core/arch/arm/plat-qcom/bobcat/ipq52xx/target.mk +++ b/core/arch/arm/plat-qcom/bobcat/ipq52xx/target.mk @@ -6,3 +6,13 @@ CFG_QCOM_DIAG_LOG ?= $(if $(filter y,$(CFG_TEE_CORE_DEBUG)),y,n) CFG_TZDRAM_START ?= 0x87D80000 CFG_TZDRAM_SIZE ?= 0x280000 CFG_TEE_RAM_VA_SIZE ?= 0x280000 + +CFG_QCOM_DIAG_LOG ?= $(if $(filter y,$(CFG_TEE_CORE_DEBUG)),y,n) + +CFG_HWRNG_PTA ?= y +ifeq ($(CFG_HWRNG_PTA),y) +$(call force,CFG_WITH_SOFTWARE_PRNG,n) +$(call force,CFG_QCOM_RNG,y) +CFG_HWRNG_QUALITY ?= 1024 +CFG_HWRNG_RATE ?= 0 +endif diff --git a/core/arch/arm/plat-qcom/bobcat/ipq52xx/target_config.h b/core/arch/arm/plat-qcom/bobcat/ipq52xx/target_config.h index 17008a0a0..0bcfbb5f5 100644 --- a/core/arch/arm/plat-qcom/bobcat/ipq52xx/target_config.h +++ b/core/arch/arm/plat-qcom/bobcat/ipq52xx/target_config.h @@ -20,4 +20,10 @@ #define IMEM_BASE UL(0x8600000) #define IMEM_SIZE UL(0x18000) +#define RNG_REG_BASE UL(0x4C5000) + +#define WDT_TMR_BASE UL(0x0B117000) +#define WDT_RESET_REG_OFFSET UL(0x4) +#define WDT_BARK_INT_ID UL(0x23) + #endif /* TARGET_CONFIG_H */ diff --git a/core/arch/arm/plat-qcom/bobcat/ipq96xx/target_config.h b/core/arch/arm/plat-qcom/bobcat/ipq96xx/target_config.h index b3eb10732..03e0a2f43 100644 --- a/core/arch/arm/plat-qcom/bobcat/ipq96xx/target_config.h +++ b/core/arch/arm/plat-qcom/bobcat/ipq96xx/target_config.h @@ -19,4 +19,8 @@ #define IMEM_BASE UL(0x8600000) #define IMEM_SIZE UL(0x20000) +#define WDT_TMR_BASE UL(0x0F411000) +#define WDT_RESET_REG_OFFSET UL(0x4) +#define WDT_BARK_INT_ID UL(0x36) + #endif /* TARGET_CONFIG_H */ diff --git a/core/arch/arm/plat-qcom/hoya/arch_config.h b/core/arch/arm/plat-qcom/hoya/arch_config.h index 8848825cb..07563fdb0 100644 --- a/core/arch/arm/plat-qcom/hoya/arch_config.h +++ b/core/arch/arm/plat-qcom/hoya/arch_config.h @@ -31,4 +31,6 @@ #define DIAG_LOG_START_INFO (IMEM_BASE + IMEM_DIAG_OFFSET) #define TCSR_BOOT_MISC_DETECT UL(0x1FD3000) +#define RNG_REG_BASE UL(0x010D1000) + #endif /* ARCH_CONFIG_H */ diff --git a/core/arch/arm/plat-qcom/hoya/qcom-arch.mk b/core/arch/arm/plat-qcom/hoya/qcom-arch.mk index 59e372983..17e0fd346 100644 --- a/core/arch/arm/plat-qcom/hoya/qcom-arch.mk +++ b/core/arch/arm/plat-qcom/hoya/qcom-arch.mk @@ -6,7 +6,7 @@ $(call force,CFG_TEE_CORE_NB_CORE,8) $(call force,CFG_QCOM_RAMBLUR_PIMEM_V3,y) CFG_QCOM_RAMBLUR_TA_WINDOW_ID ?= 2 -$(call force,CFG_QCOM_PRNG,y) +$(call force,CFG_QCOM_RNG,y) $(call force,CFG_ARM_GICV3,y) CFG_TZDRAM_START ?= 0x1c300000 diff --git a/core/drivers/qcom/prng/prng.c b/core/drivers/qcom/rng/qcom-rng.c similarity index 58% rename from core/drivers/qcom/prng/prng.c rename to core/drivers/qcom/rng/qcom-rng.c index 8f50f56b7..f7bb764ca 100644 --- a/core/drivers/qcom/prng/prng.c +++ b/core/drivers/qcom/rng/qcom-rng.c @@ -10,19 +10,18 @@ #include #include -#define SEC_PRNG_REG_SIZE 0x1000 +#define RNG_DATA_OUT 0x0 +#define RNG_STATUS 0x4 +#define RNG_STATUS_DATA_AVAIL_BMSK 0x1 -#define SEC_PRNG_DATA_OUT 0x0 -#define SEC_PRNG_STATUS 0x4 -#define SEC_PRNG_STATUS_DATA_AVAIL_BMSK 0x1 - -#define PRNG_TIMEOUT_US 1000000 +#define RNG_REG_SIZE 0x1000 +#define RNG_TIMEOUT_US 1000000 static struct { paddr_t pa; vaddr_t va; -} prng = { - .pa = SEC_PRNG_REG_BASE, +} rng = { + .pa = RNG_REG_BASE, }; TEE_Result hw_get_random_bytes(void *buf, size_t len) @@ -31,22 +30,22 @@ TEE_Result hw_get_random_bytes(void *buf, size_t len) uint32_t val = 0; uint64_t to = 0; - if (!prng.va) + if (!rng.va) return TEE_ERROR_NOT_SUPPORTED; if (!out || !len) return TEE_ERROR_BAD_PARAMETERS; - to = timeout_init_us(PRNG_TIMEOUT_US); + to = timeout_init_us(RNG_TIMEOUT_US); while (len) { - if (!(io_read32(prng.va + SEC_PRNG_STATUS) & - SEC_PRNG_STATUS_DATA_AVAIL_BMSK)) { + if (!(io_read32(rng.va + RNG_STATUS) & + RNG_STATUS_DATA_AVAIL_BMSK)) { if (timeout_elapsed(to)) return TEE_ERROR_BUSY; continue; } - while ((val = io_read32(prng.va + SEC_PRNG_DATA_OUT)) == 0) { + while ((val = io_read32(rng.va + RNG_DATA_OUT)) == 0) { if (timeout_elapsed(to)) return TEE_ERROR_BUSY; } @@ -60,14 +59,14 @@ TEE_Result hw_get_random_bytes(void *buf, size_t len) return TEE_SUCCESS; } -static TEE_Result qcom_prng_init(void) +static TEE_Result rng_init(void) { - prng.va = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, prng.pa, - SEC_PRNG_REG_SIZE); - if (!prng.va) + rng.va = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, rng.pa, + RNG_REG_SIZE); + if (!rng.va) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } -early_init(qcom_prng_init); +early_init(rng_init); diff --git a/core/drivers/qcom/rng/sub.mk b/core/drivers/qcom/rng/sub.mk new file mode 100644 index 000000000..c622cd336 --- /dev/null +++ b/core/drivers/qcom/rng/sub.mk @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# + +global-incdirs-y += . +srcs-$(CFG_QCOM_RNG) += qcom-rng.c diff --git a/core/drivers/qcom/sub.mk b/core/drivers/qcom/sub.mk index b7a931564..176ccd9f4 100644 --- a/core/drivers/qcom/sub.mk +++ b/core/drivers/qcom/sub.mk @@ -5,7 +5,8 @@ # srcs-$(CFG_QCOM_RAMBLUR_PIMEM_V3) += ramblur/ramblur_pimem_v3.c -srcs-$(CFG_QCOM_PRNG) += prng/prng.c +srcs-$(CFG_QCOM_RNG) += rng/qcom-rng.c +srcs-$(CFG_QCOM_SEC_WDOG) += wdt/wdt.c $(eval $(call cfg-depends-all,CFG_QCOM_QFPROM,CFG_QCOM_CMD_DB CFG_QCOM_RPMH_CLIENT)) $(eval $(call cfg-depends-all,CFG_QCOM_RPMH_CLIENT,CFG_QCOM_CMD_DB)) diff --git a/core/drivers/qcom/wdt/wdt.c b/core/drivers/qcom/wdt/wdt.c new file mode 100644 index 000000000..46d07f957 --- /dev/null +++ b/core/drivers/qcom/wdt/wdt.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * QCOM Secure Watchdog Driver + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, WDT_TMR_BASE, + CORE_MMU_PGDIR_SIZE); + +#define WDT_CTL_OFFSET 0x08 +#define WDT_BARK_TIME_OFFSET 0x10 +#define WDT_BITE_TIME_OFFSET 0x14 + +#define WDT_CTL_INT_ENABLE_SHFT 0 +#define WDT_CTL_UNMASKED_INT_ENABLE_SHFT 1 + +#define WDT_BARK_TIME_RMSK 0xFFFFFU +#define WDT_BITE_TIME_RMSK 0xFFFFFU + +#define WDT_CLK_HZ 32000U + +#define WDT_BARK_TIME_MS 6000U +#define WDT_BITE_TIME_MS 22000U + +static vaddr_t wdt_base; + +static uint32_t ms_to_ticks_wdt(uint32_t ms) +{ + return (uint32_t)(((uint64_t)ms * WDT_CLK_HZ) / 1000U); +} + +static void wdt_enable(bool enable) +{ + io_write32(wdt_base + WDT_CTL_OFFSET, + UINT32_C(1) << WDT_CTL_UNMASKED_INT_ENABLE_SHFT + | (enable ? UINT32_C(1) : UINT32_C(0)) + << WDT_CTL_INT_ENABLE_SHFT); +} + +static void wdt_reset(void) +{ + io_write32(wdt_base + WDT_RESET_REG_OFFSET, 1); +} + +static void wdt_start(uint32_t bark_timeout, uint32_t bite_timeout) +{ + /* Zero timeouts are not allowed, ensure timeouts are > 0. */ + bark_timeout = MAX(bark_timeout, 0x1U); + bite_timeout = MAX(bite_timeout, 0x1U); + + bark_timeout = ms_to_ticks_wdt(bark_timeout); + bite_timeout = ms_to_ticks_wdt(bite_timeout); + + /* Timeouts have a ceiling value */ + bark_timeout = MIN(bark_timeout, (uint32_t)(WDT_BARK_TIME_RMSK)); + bite_timeout = MIN(bite_timeout, (uint32_t)(WDT_BITE_TIME_RMSK)); + + wdt_enable(false); + + io_write32(wdt_base + WDT_BARK_TIME_OFFSET, bark_timeout); + io_write32(wdt_base + WDT_BITE_TIME_OFFSET, bite_timeout); + + wdt_enable(true); + + wdt_reset(); +} + +static enum itr_return +wdt_bark_handler(struct itr_handler *h __unused) +{ + io_write32(wdt_base + WDT_RESET_REG_OFFSET, 1); + + return ITRR_HANDLED; +} + +static TEE_Result wdt_init(void) +{ + TEE_Result res = TEE_SUCCESS; + struct itr_handler *handler = NULL; + + wdt_base = (vaddr_t)phys_to_virt(WDT_TMR_BASE, + MEM_AREA_IO_SEC, 1); + if (!wdt_base) { + EMSG("wdt: Failed to map watchdog registers"); + return TEE_ERROR_GENERIC; + } + + wdt_start(WDT_BARK_TIME_MS, WDT_BITE_TIME_MS); + + res = interrupt_create_handler(interrupt_get_main_chip(), + WDT_BARK_INT_ID, + wdt_bark_handler, + 0u, 0u, &handler); + if (res != TEE_SUCCESS) { + EMSG("wdt: Failed to register bark handler (err=0x%x)", + res); + return res; + } + + return TEE_SUCCESS; +} + +driver_init(wdt_init); +