diff --git a/core/arch/arm/include/arm64.h b/core/arch/arm/include/arm64.h
index 2c1fd8c..0cf14c0 100644
--- a/core/arch/arm/include/arm64.h
+++ b/core/arch/arm/include/arm64.h
@@ -305,6 +305,10 @@ DEFINE_REG_READ_FUNC_(cntfrq, uint32_t, cntfrq_el0)
 DEFINE_REG_READ_FUNC_(cntpct, uint64_t, cntpct_el0)
 DEFINE_REG_READ_FUNC_(cntkctl, uint32_t, cntkctl_el1)
 DEFINE_REG_WRITE_FUNC_(cntkctl, uint32_t, cntkctl_el1)
+DEFINE_REG_READ_FUNC_(cntps_ctl, uint32_t, cntps_ctl_el1)
+DEFINE_REG_WRITE_FUNC_(cntps_ctl, uint32_t, cntps_ctl_el1)
+DEFINE_REG_READ_FUNC_(cntps_cval, uint32_t, cntps_cval_el1)
+DEFINE_REG_WRITE_FUNC_(cntps_cval, uint32_t, cntps_cval_el1)
 
 DEFINE_REG_READ_FUNC_(pmccntr, uint64_t, pmccntr_el0)
 
diff --git a/core/arch/arm/plat-synquacer/main.c b/core/arch/arm/plat-synquacer/main.c
index c3aac4c..7c3a6bc 100644
--- a/core/arch/arm/plat-synquacer/main.c
+++ b/core/arch/arm/plat-synquacer/main.c
@@ -18,6 +18,7 @@
 #include <sm/optee_smc.h>
 #include <tee/entry_fast.h>
 #include <tee/entry_std.h>
+#include <rng_pta.h>
 
 static void main_fiq(void);
 
@@ -38,6 +39,7 @@ static struct pl011_data console_data;
 
 register_phys_mem(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, CORE_MMU_DEVICE_SIZE);
 register_phys_mem(MEM_AREA_IO_SEC, GIC_BASE, CORE_MMU_DEVICE_SIZE);
+register_phys_mem(MEM_AREA_IO_SEC, THERMAL_SENSOR_BASE, CORE_MMU_DEVICE_SIZE);
 
 const struct thread_handlers *generic_boot_get_handlers(void)
 {
@@ -46,7 +48,7 @@ const struct thread_handlers *generic_boot_get_handlers(void)
 
 static void main_fiq(void)
 {
-	panic();
+	gic_it_handle(&gic_data);
 }
 
 void console_init(void)
@@ -66,12 +68,38 @@ void main_init_gic(void)
 	if (!gicd_base)
 		panic();
 
-	/* Initialize GIC */
-	gic_init(&gic_data, 0, gicd_base);
+	/* On ARMv8-A, GIC configuration is initialized in TF-A */
+	gic_init_base_addr(&gic_data, 0, gicd_base);
+
 	itr_init(&gic_data.chip);
 }
 
-void main_secondary_init_gic(void)
+static enum itr_return timer_itr_cb(struct itr_handler *h __unused)
+{
+	/* Reset timer for next FIQ */
+	generic_timer_handler();
+
+	/* Collect entropy on each timer FIQ */
+	rng_collect_entropy();
+
+	return ITRR_HANDLED;
+}
+
+static struct itr_handler timer_itr = {
+	.it = IT_SEC_TIMER,
+	.flags = ITRF_TRIGGER_LEVEL,
+	.handler = timer_itr_cb,
+};
+
+static TEE_Result init_timer_itr(void)
 {
-	gic_cpu_init(&gic_data);
+	itr_add(&timer_itr);
+	itr_enable(IT_SEC_TIMER);
+
+	/* Enable timer FIQ to fetch entropy required during boot */
+	generic_timer_start();
+	timer_fiq_running = true;
+
+	return TEE_SUCCESS;
 }
+driver_init(init_timer_itr);
diff --git a/core/arch/arm/plat-synquacer/platform_config.h b/core/arch/arm/plat-synquacer/platform_config.h
index 4d6d545..8a91ddb 100644
--- a/core/arch/arm/plat-synquacer/platform_config.h
+++ b/core/arch/arm/plat-synquacer/platform_config.h
@@ -19,6 +19,9 @@
 #define CONSOLE_UART_CLK_IN_HZ		62500000
 #define CONSOLE_BAUDRATE		115200
 
+#define THERMAL_SENSOR_BASE		0x54190000
+#define IT_SEC_TIMER			29
+
 #define DRAM0_BASE			0x80000000
 
 /* Platform specific defines */
diff --git a/core/arch/arm/plat-synquacer/rng_pta.c b/core/arch/arm/plat-synquacer/rng_pta.c
new file mode 100644
index 0000000..a760b54
--- /dev/null
+++ b/core/arch/arm/plat-synquacer/rng_pta.c
@@ -0,0 +1,270 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (C) 2018, Linaro Limited
+ */
+
+#include <crypto/crypto.h>
+#include <kernel/delay.h>
+#include <kernel/pseudo_ta.h>
+#include <kernel/spinlock.h>
+#include <mm/core_memprot.h>
+#include <io.h>
+#include <string.h>
+#include <rng_pta.h>
+#include <rng_pta_client.h>
+
+static uint8_t entropy_pool[ENTROPY_POOL_SIZE] = {0};
+static uint32_t entropy_size;
+
+/* Current sensor data */
+static uint8_t sensor_data[NUM_OF_SENSORS][SENSOR_DATA_SIZE] = {0};
+static uint8_t s;
+
+/* Sensor data that passed health test */
+static uint8_t sensor_data_pass[NUM_OF_SENSORS][SENSOR_DATA_SIZE] = {0};
+static uint8_t num_sensors_pass;
+
+static uint8_t rest_data_pass[NUM_OF_SENSORS][SENSOR_DATA_SIZE] = {0};
+
+static uint32_t health_test_fail_cnt;
+
+static unsigned int entropy_lock = SPINLOCK_UNLOCK;
+
+static void pool_add_entropy(uint8_t *entropy, uint32_t size)
+{
+	uint32_t copy_size;
+
+	if (entropy_size >= ENTROPY_POOL_SIZE)
+		return;
+
+	if ((ENTROPY_POOL_SIZE - entropy_size) >= size)
+		copy_size = size;
+	else
+		copy_size = ENTROPY_POOL_SIZE - entropy_size;
+
+	memcpy((entropy_pool + entropy_size), entropy, copy_size);
+
+	entropy_size += copy_size;
+}
+
+static void pool_get_entropy(uint8_t *buf, uint32_t size)
+{
+	uint32_t off;
+
+	if (size > entropy_size)
+		return;
+
+	off = entropy_size - size;
+
+	memcpy(buf, &entropy_pool[off], size);
+	entropy_size -= size;
+}
+
+static bool health_test(uint8_t sensor_id)
+{
+	bool result = true;
+	uint8_t bit_flip_1_0 = 0, bit_flip_0_1 = 0;
+	uint8_t i;
+
+	/*
+	 * Heatlh test to check if count of bit flips 1-0 or 0-1 lies in 12.5%
+	 * to 37.5% of 128 bytes raw data from particular sensor reading. In
+	 * ideal scenario either of bit flips should be around 25%.
+	 */
+	for (i = 0; i < (SENSOR_DATA_SIZE - 1); i++) {
+		if ((sensor_data[sensor_id][i] ^
+		     sensor_data[sensor_id][i + 1]) & 0x1) {
+			bit_flip_1_0 += sensor_data[sensor_id][i] & 0x1;
+			bit_flip_0_1 += sensor_data[sensor_id][i + 1] & 0x1;
+		}
+	}
+
+	if (bit_flip_1_0 > bit_flip_0_1) {
+		if (bit_flip_0_1 < MIN_BIT_FLIP_COUNT)
+			result = false;
+		if (bit_flip_1_0 > MAX_BIT_FLIP_COUNT)
+			result = false;
+	} else {
+		if (bit_flip_1_0 < MIN_BIT_FLIP_COUNT)
+			result = false;
+		if (bit_flip_0_1 > MAX_BIT_FLIP_COUNT)
+			result = false;
+	}
+
+	return result;
+}
+
+static void pool_check_add_entropy(void)
+{
+	uint32_t i;
+	uint8_t entropy_sha512_256[TEE_SHA256_HASH_SIZE];
+	uint8_t rest_sensors_pass = 0;
+	TEE_Result res;
+
+	for (i = 0; i < NUM_OF_SENSORS; i++) {
+		/* Check if particular sensor data passes health test */
+		if (health_test(i) == true) {
+			if (num_sensors_pass < NUM_OF_SENSORS) {
+				memcpy(sensor_data_pass[num_sensors_pass],
+				       sensor_data[i], SENSOR_DATA_SIZE);
+				num_sensors_pass++;
+			} else {
+				memcpy(rest_data_pass[rest_sensors_pass],
+				       sensor_data[i], SENSOR_DATA_SIZE);
+				rest_sensors_pass++;
+			}
+		} else {
+			health_test_fail_cnt++;
+			/*
+			 * Report health test failures if it exceeds certain
+			 * threshold.
+			 */
+			if (health_test_fail_cnt >= THRESHOLD_REPORT_FAILURE) {
+				IMSG("Health test failed %d times\n",
+					health_test_fail_cnt);
+				health_test_fail_cnt = 0;
+			}
+		}
+	}
+
+	/* Check if sensor_data_pass is full */
+	if (num_sensors_pass == NUM_OF_SENSORS) {
+		/*
+		 * Use vetted conditioner SHA512/256 as per
+		 * NIST.SP.800-90B to condition raw data from entropy
+		 * source.
+		 * Here we have assumed that entropy source provides
+		 * 4 bits per 7 sensor readings per sample.
+		 * Also as per NIST.SP.800-90B, to get full entropy
+		 * from vetted conditioner, we need to supply double of
+		 * input entropy. So with full entropy (8 bits per byte)
+		 * we will get yield as one byte of output data for
+		 * every 28 sensor readings.
+		 * For 32 bytes of SHA512/256 output data, we need to
+		 * supply 896 bytes of raw input data.
+		 */
+		res = hash_sha512_256_compute(entropy_sha512_256,
+					      (uint8_t *)sensor_data_pass,
+					      CONDITIONER_PAYLOAD);
+		if (res == TEE_SUCCESS)
+			pool_add_entropy(entropy_sha512_256,
+					 TEE_SHA256_HASH_SIZE);
+	}
+
+	if (rest_sensors_pass)
+		memcpy((uint8_t *)sensor_data_pass, (uint8_t *)rest_data_pass,
+		       (rest_sensors_pass * SENSOR_DATA_SIZE));
+
+	num_sensors_pass = rest_sensors_pass;
+}
+
+void rng_collect_entropy(void)
+{
+	uint8_t i;
+	void *vaddr;
+	uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
+
+	cpu_spin_lock(&entropy_lock);
+
+	for (i = 0; i < NUM_OF_SENSORS; i++) {
+		vaddr = phys_to_virt_io(THERMAL_SENSOR_BASE0 +
+					(THERMAL_SENSOR_OFFSET * i) +
+					TEMP_DATA_REG_OFFSET);
+		sensor_data[i][s] = (uint8_t)read32((vaddr_t)vaddr);
+	}
+
+	s++;
+
+	if (s >= SENSOR_DATA_SIZE) {
+		pool_check_add_entropy();
+		s = 0;
+	}
+
+	if (entropy_size >= ENTROPY_POOL_SIZE) {
+		generic_timer_stop();
+		timer_fiq_running = false;
+	}
+
+	cpu_spin_unlock(&entropy_lock);
+	thread_set_exceptions(exceptions);
+}
+
+static TEE_Result rng_get_entropy(uint32_t types,
+				  TEE_Param params[TEE_NUM_PARAMS])
+{
+	uint8_t *e = NULL;
+	uint32_t pool_size = 0, rq_size = 0;
+	uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
+
+	cpu_spin_lock(&entropy_lock);
+
+	if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
+				     TEE_PARAM_TYPE_NONE,
+				     TEE_PARAM_TYPE_NONE,
+				     TEE_PARAM_TYPE_NONE)) {
+		EMSG("bad parameters types: 0x%" PRIx32, types);
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	rq_size = params[0].memref.size;
+
+	if ((rq_size == 0) || (rq_size > ENTROPY_POOL_SIZE))
+		return TEE_ERROR_NOT_SUPPORTED;
+
+	e = (uint8_t *)params[0].memref.buffer;
+	if (!e)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	pool_size = entropy_size;
+
+	if (pool_size < rq_size) {
+		params[0].memref.size = pool_size;
+		pool_get_entropy(e, pool_size);
+	} else {
+		params[0].memref.size = rq_size;
+		pool_get_entropy(e, rq_size);
+	}
+
+	if (timer_fiq_running == false) {
+		/* Enable timer FIQ to fetch entropy */
+		generic_timer_start();
+		timer_fiq_running = true;
+	}
+
+	cpu_spin_unlock(&entropy_lock);
+	thread_set_exceptions(exceptions);
+
+	return TEE_SUCCESS;
+}
+
+/*
+ * Trusted Application Entry Points
+ */
+static TEE_Result open_session(uint32_t param_types __unused,
+			       TEE_Param params[TEE_NUM_PARAMS] __unused,
+			       void **session_context __unused)
+{
+	DMSG("open entry point for pseudo-TA \"%s\"", PTA_NAME);
+	return TEE_SUCCESS;
+}
+
+static TEE_Result invoke_command(void *pSessionContext __unused,
+				 uint32_t nCommandID, uint32_t nParamTypes,
+				 TEE_Param pParams[TEE_NUM_PARAMS])
+{
+	FMSG("command entry point for pseudo-TA \"%s\"", PTA_NAME);
+
+	switch (nCommandID) {
+	case PTA_CMD_GET_ENTROPY:
+		return rng_get_entropy(nParamTypes, pParams);
+	default:
+		break;
+	}
+
+	return TEE_ERROR_NOT_IMPLEMENTED;
+}
+
+pseudo_ta_register(.uuid = PTA_RNG_UUID, .name = PTA_NAME,
+		   .flags = PTA_DEFAULT_FLAGS,
+		   .open_session_entry_point = open_session,
+		   .invoke_command_entry_point = invoke_command);
diff --git a/core/arch/arm/plat-synquacer/rng_pta.h b/core/arch/arm/plat-synquacer/rng_pta.h
new file mode 100644
index 0000000..e238c57
--- /dev/null
+++ b/core/arch/arm/plat-synquacer/rng_pta.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2018, Linaro Limited
+ */
+
+#ifndef __RNG_PTA_H
+#define __RNG_PTA_H
+
+#define PTA_NAME "rng.pta"
+
+#define THERMAL_SENSOR_BASE0		0x54190800
+#define THERMAL_SENSOR_OFFSET		0x80
+#define NUM_OF_SENSORS			7
+
+#define TEMP_DATA_REG_OFFSET		0x34
+
+#define ENTROPY_POOL_SIZE		4096
+
+#define SENSOR_DATA_SIZE		128
+#define CONDITIONER_PAYLOAD		(SENSOR_DATA_SIZE * NUM_OF_SENSORS)
+
+#define LSB_MASK			0x1
+
+#define MAX_BIT_FLIP_COUNT		48
+#define MIN_BIT_FLIP_COUNT		16
+
+#define THRESHOLD_REPORT_FAILURE	10
+
+extern bool timer_fiq_running;
+
+void rng_collect_entropy(void);
+
+void generic_timer_start(void);
+void generic_timer_stop(void);
+void generic_timer_handler(void);
+
+#endif /* __RNG_PTA_H */
diff --git a/core/arch/arm/plat-synquacer/rng_pta_client.h b/core/arch/arm/plat-synquacer/rng_pta_client.h
new file mode 100644
index 0000000..ddd398c
--- /dev/null
+++ b/core/arch/arm/plat-synquacer/rng_pta_client.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2018, Linaro Limited
+ */
+
+#ifndef __RNG_PTA_CLIENT_H
+#define __RNG_PTA_CLIENT_H
+
+#define PTA_RNG_UUID { 0xab7a617c, 0xb8e7, 0x4d8f, \
+		{ 0x83, 0x01, 0xd0, 0x9b, 0x61, 0x03, 0x6b, 0x64 } }
+
+/*
+ * PTA_CMD_GET_ENTROPY - Get Entropy from RNG using Thermal Sensor
+ *
+ * param[0] (inout memref) - Entropy buffer memory reference
+ * param[1] unused
+ * param[2] unused
+ * param[3] unused
+ */
+#define PTA_CMD_GET_ENTROPY		0x0
+
+#endif /* __RNG_PTA_CLIENT_H */
diff --git a/core/arch/arm/plat-synquacer/sub.mk b/core/arch/arm/plat-synquacer/sub.mk
index 8ddc2fd..013e57d 100644
--- a/core/arch/arm/plat-synquacer/sub.mk
+++ b/core/arch/arm/plat-synquacer/sub.mk
@@ -1,2 +1,4 @@
 global-incdirs-y += .
 srcs-y += main.c
+srcs-y += rng_pta.c
+srcs-y += timer_fiq.c
diff --git a/core/arch/arm/plat-synquacer/timer_fiq.c b/core/arch/arm/plat-synquacer/timer_fiq.c
new file mode 100644
index 0000000..e25a676
--- /dev/null
+++ b/core/arch/arm/plat-synquacer/timer_fiq.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2018, Linaro Limited
+ */
+
+#include <arm.h>
+#include <console.h>
+#include <drivers/gic.h>
+#include <io.h>
+#include <kernel/panic.h>
+#include <kernel/misc.h>
+#include <rng_pta.h>
+
+bool timer_fiq_running = false;
+
+void generic_timer_start(void)
+{
+	uint64_t cval;
+	uint32_t ctl = 1;
+
+	/* The timer will fire every 2 ms */
+	cval = read_cntpct() + (read_cntfrq() / 500);
+	write_cntps_cval(cval);
+
+	/* Enable the secure physical timer */
+	write_cntps_ctl(ctl);
+}
+
+void generic_timer_stop(void)
+{
+	/* Disable the timer */
+	write_cntps_ctl(0);
+}
+
+void generic_timer_handler(void)
+{
+	/* Ensure that the timer did assert the interrupt */
+	assert((read_cntps_ctl() >> 2));
+
+	/* Disable the timer and reprogram it */
+	write_cntps_ctl(0);
+	generic_timer_start();
+}
