Tegra: implement FIQ interrupt handler

This patch adds a handler for FIQ interrupts triggered when
the CPU is in the NS world. The handler stores the NS world's
context along with ELR_EL3/SPSR_EL3.

The NS world driver issues an SMC initially to register it's
handler. The monitor firmware stores this handler address and
jumps to it when the FIQ interrupt fires. Upon entry into the
NS world the driver then issues another SMC to get the CPU
context when the FIQ fired. This allows the NS world driver to
determine the CPU state and call stack when the interrupt
fired. Generally, systems register watchdog interrupts as FIQs
which are then used to get the CPU state during hangs/crashes.

Change-Id: I733af61a08d1318c75acedbe9569a758744edd0c
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
diff --git a/plat/nvidia/tegra/common/tegra_sip_calls.c b/plat/nvidia/tegra/common/tegra_sip_calls.c
index 77f039a..ba0e1ef 100644
--- a/plat/nvidia/tegra/common/tegra_sip_calls.c
+++ b/plat/nvidia/tegra/common/tegra_sip_calls.c
@@ -42,6 +42,8 @@
  * Common Tegra SiP SMCs
  ******************************************************************************/
 #define TEGRA_SIP_NEW_VIDEOMEM_REGION		0x82000003
+#define TEGRA_SIP_FIQ_NS_ENTRYPOINT		0x82000005
+#define TEGRA_SIP_FIQ_NS_GET_CONTEXT		0x82000006
 
 /*******************************************************************************
  * SoC specific SiP handler
@@ -108,6 +110,41 @@
 		SMC_RET1(handle, 0);
 		break;
 
+	/*
+	 * The NS world registers the address of its handler to be
+	 * used for processing the FIQ. This is normally used by the
+	 * NS FIQ debugger driver to detect system hangs by programming
+	 * a watchdog timer to fire a FIQ interrupt.
+	 */
+	case TEGRA_SIP_FIQ_NS_ENTRYPOINT:
+
+		if (!x1)
+			SMC_RET1(handle, SMC_UNK);
+
+		/*
+		 * TODO: Check if x1 contains a valid DRAM address
+		 */
+
+		/* store the NS world's entrypoint */
+		tegra_fiq_set_ns_entrypoint(x1);
+
+		SMC_RET1(handle, 0);
+		break;
+
+	/*
+	 * The NS world's FIQ handler issues this SMC to get the NS EL1/EL0
+	 * CPU context when the FIQ interrupt was triggered. This allows the
+	 * NS world to understand the CPU state when the watchdog interrupt
+	 * triggered.
+	 */
+	case TEGRA_SIP_FIQ_NS_GET_CONTEXT:
+
+		/* retrieve context registers when FIQ triggered */
+		tegra_fiq_get_intr_context();
+
+		SMC_RET0(handle);
+		break;
+
 	default:
 		ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
 		break;