feat(mt8188): add MT8188 TRNG driver

Add MTK TRNG driver for MT8188.

Change-Id: I604edd42ffce9a153e209a015ba454b51da454e1
diff --git a/plat/mediatek/drivers/rng/mt8188/rng_plat.c b/plat/mediatek/drivers/rng/mt8188/rng_plat.c
new file mode 100644
index 0000000..361be22
--- /dev/null
+++ b/plat/mediatek/drivers/rng/mt8188/rng_plat.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2024, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/smccc.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+#include <services/trng_svc.h>
+#include <smccc_helpers.h>
+
+#include "rng_plat.h"
+
+static void trng_external_swrst(void)
+{
+	/* External swrst to reset whole rng module */
+	mmio_setbits_32(TRNG_SWRST_SET_REG, RNG_SWRST_B);
+	mmio_setbits_32(TRNG_SWRST_CLR_REG, RNG_SWRST_B);
+
+	/* Disable irq */
+	mmio_clrbits_32(RNG_IRQ_CFG, IRQ_EN);
+	/* Set default cutoff value */
+	mmio_write_32(RNG_HTEST, RNG_DEFAULT_CUTOFF);
+	/* Enable rng */
+	mmio_setbits_32(RNG_EN, DRBG_EN | NRBG_EN);
+}
+
+static bool get_entropy_32(uint32_t *out)
+{
+	uint64_t time = timeout_init_us(MTK_TIMEOUT_POLL);
+	int retry_times = 0;
+
+	while (!(mmio_read_32(RNG_STATUS) & DRBG_VALID)) {
+		if (mmio_read_32(RNG_STATUS) & (RNG_ERROR | APB_ERROR)) {
+			mmio_clrbits_32(RNG_EN, DRBG_EN | NRBG_EN);
+
+			mmio_clrbits_32(RNG_SWRST, SWRST_B);
+			mmio_setbits_32(RNG_SWRST, SWRST_B);
+
+			mmio_setbits_32(RNG_EN, DRBG_EN | NRBG_EN);
+		}
+
+		if (timeout_elapsed(time)) {
+			trng_external_swrst();
+			time = timeout_init_us(MTK_TIMEOUT_POLL);
+			retry_times++;
+		}
+
+		if (retry_times > MTK_RETRY_CNT) {
+			ERROR("%s: trng NOT ready\n", __func__);
+			return false;
+		}
+	}
+
+	*out = mmio_read_32(RNG_OUT);
+
+	return true;
+}
+
+/* Get random number from HWRNG and return 8 bytes of entropy.
+ * Return 'true' when random value generated successfully, otherwise return
+ * 'false'.
+ */
+bool plat_get_entropy(uint64_t *out)
+{
+	uint32_t seed[2] = { 0 };
+	int i = 0;
+
+	assert(out);
+	assert(!check_uptr_overflow((uintptr_t)out, sizeof(*out)));
+
+	/* Disable interrupt mode */
+	mmio_clrbits_32(RNG_IRQ_CFG, IRQ_EN);
+	/* Set rng health test cutoff value */
+	mmio_write_32(RNG_HTEST, RNG_DEFAULT_CUTOFF);
+	/* Enable rng module */
+	mmio_setbits_32(RNG_EN, DRBG_EN | NRBG_EN);
+
+	for (i = 0; i < ARRAY_SIZE(seed); i++) {
+		if (!get_entropy_32(&seed[i]))
+			return false;
+	}
+
+	/* Output 8 bytes entropy by combining 2 32-bit random numbers. */
+	*out = ((uint64_t)seed[0] << 32) | seed[1];
+
+	return true;
+}