From f3a866004ea8f9a0cd5420f3dd4d4683f638e6da Mon Sep 17 00:00:00 2001
From: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
Date: Fri, 22 Sep 2017 08:32:09 +0100
Subject: [PATCH] GIC: Add API to set interrupt priority

API documentation updated.

Change-Id: Ib700eb1b8ca65503aeed0ac4ce0e7b934df67ff9
Co-authored-by: Yousuf A <yousuf.sait@arm.com>
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
---
 docs/platform-interrupt-controller-API.rst | 15 ++++++++++++++
 drivers/arm/gic/v2/gicv2_main.c            | 13 ++++++++++++
 drivers/arm/gic/v3/gicv3_main.c            | 23 ++++++++++++++++++++++
 include/drivers/arm/gicv2.h                |  1 +
 include/drivers/arm/gicv3.h                |  2 ++
 include/plat/common/platform.h             |  1 +
 plat/common/plat_gicv2.c                   |  6 ++++++
 plat/common/plat_gicv3.c                   |  6 ++++++
 8 files changed, 67 insertions(+)

diff --git a/docs/platform-interrupt-controller-API.rst b/docs/platform-interrupt-controller-API.rst
index bea1a64b5..3161c20a2 100644
--- a/docs/platform-interrupt-controller-API.rst
+++ b/docs/platform-interrupt-controller-API.rst
@@ -111,6 +111,21 @@ In case of ARM standard platforms using GIC, the implementation of the API
 writes to GIC *Clear Enable Register* to disable the interrupt, and inserts
 barrier to make memory updates visible afterwards.
 
+Function: void plat_ic_set_interrupt_priority(unsigned int id, unsigned int priority); [optional]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : unsigned int
+    Argument : unsigned int
+    Return   : void
+
+This API should set the priority of the interrupt specified by first parameter
+``id`` to the value set by the second parameter ``priority``.
+
+In case of ARM standard platforms using GIC, the implementation of the API
+writes to GIC *Priority Register* set interrupt priority.
+
 ----
 
 *Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.*
diff --git a/drivers/arm/gic/v2/gicv2_main.c b/drivers/arm/gic/v2/gicv2_main.c
index e0058ad13..4861e02df 100644
--- a/drivers/arm/gic/v2/gicv2_main.c
+++ b/drivers/arm/gic/v2/gicv2_main.c
@@ -322,3 +322,16 @@ void gicv2_disable_interrupt(unsigned int id)
 	gicd_set_icenabler(driver_data->gicd_base, id);
 	dsbishst();
 }
+
+/*******************************************************************************
+ * This function sets the interrupt priority as supplied for the given interrupt
+ * id.
+ ******************************************************************************/
+void gicv2_set_interrupt_priority(unsigned int id, unsigned int priority)
+{
+	assert(driver_data);
+	assert(driver_data->gicd_base);
+	assert(id <= MAX_SPI_ID);
+
+	gicd_set_ipriorityr(driver_data->gicd_base, id, priority);
+}
diff --git a/drivers/arm/gic/v3/gicv3_main.c b/drivers/arm/gic/v3/gicv3_main.c
index b3231993e..d0ecab615 100644
--- a/drivers/arm/gic/v3/gicv3_main.c
+++ b/drivers/arm/gic/v3/gicv3_main.c
@@ -869,3 +869,26 @@ void gicv3_disable_interrupt(unsigned int id, unsigned int proc_num)
 
 	dsbishst();
 }
+
+/*******************************************************************************
+ * This function sets the interrupt priority as supplied for the given interrupt
+ * id.
+ ******************************************************************************/
+void gicv3_set_interrupt_priority(unsigned int id, unsigned int proc_num,
+		unsigned int priority)
+{
+	uintptr_t gicr_base;
+
+	assert(gicv3_driver_data);
+	assert(gicv3_driver_data->gicd_base);
+	assert(proc_num < gicv3_driver_data->rdistif_num);
+	assert(gicv3_driver_data->rdistif_base_addrs);
+	assert(id <= MAX_SPI_ID);
+
+	if (id < MIN_SPI_ID) {
+		gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+		gicr_set_ipriorityr(gicr_base, id, priority);
+	} else {
+		gicd_set_ipriorityr(gicv3_driver_data->gicd_base, id, priority);
+	}
+}
diff --git a/include/drivers/arm/gicv2.h b/include/drivers/arm/gicv2.h
index 0af1a25e2..91674fd36 100644
--- a/include/drivers/arm/gicv2.h
+++ b/include/drivers/arm/gicv2.h
@@ -150,6 +150,7 @@ void gicv2_set_pe_target_mask(unsigned int proc_num);
 unsigned int gicv2_get_interrupt_active(unsigned int id);
 void gicv2_enable_interrupt(unsigned int id);
 void gicv2_disable_interrupt(unsigned int id);
+void gicv2_set_interrupt_priority(unsigned int id, unsigned int priority);
 
 #endif /* __ASSEMBLY__ */
 #endif /* __GICV2_H__ */
diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h
index 6e6a47b97..f753ca265 100644
--- a/include/drivers/arm/gicv3.h
+++ b/include/drivers/arm/gicv3.h
@@ -353,6 +353,8 @@ unsigned int gicv3_get_running_priority(void);
 unsigned int gicv3_get_interrupt_active(unsigned int id, unsigned int proc_num);
 void gicv3_enable_interrupt(unsigned int id, unsigned int proc_num);
 void gicv3_disable_interrupt(unsigned int id, unsigned int proc_num);
+void gicv3_set_interrupt_priority(unsigned int id, unsigned int proc_num,
+		unsigned int priority);
 
 #endif /* __ASSEMBLY__ */
 #endif /* __GICV3_H__ */
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index 671aa61e8..03f529cb0 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -79,6 +79,7 @@ int plat_ic_is_sgi(unsigned int id);
 unsigned int plat_ic_get_interrupt_active(unsigned int id);
 void plat_ic_disable_interrupt(unsigned int id);
 void plat_ic_enable_interrupt(unsigned int id);
+void plat_ic_set_interrupt_priority(unsigned int id, unsigned int priority);
 
 /*******************************************************************************
  * Optional common functions (may be overridden)
diff --git a/plat/common/plat_gicv2.c b/plat/common/plat_gicv2.c
index 2591805de..d50138edf 100644
--- a/plat/common/plat_gicv2.c
+++ b/plat/common/plat_gicv2.c
@@ -27,6 +27,7 @@
 #pragma weak plat_ic_get_interrupt_active
 #pragma weak plat_ic_enable_interrupt
 #pragma weak plat_ic_disable_interrupt
+#pragma weak plat_ic_set_interrupt_priority
 
 /*
  * This function returns the highest priority pending interrupt at
@@ -165,3 +166,8 @@ void plat_ic_disable_interrupt(unsigned int id)
 {
 	gicv2_disable_interrupt(id);
 }
+
+void plat_ic_set_interrupt_priority(unsigned int id, unsigned int priority)
+{
+	gicv2_set_interrupt_priority(id, priority);
+}
diff --git a/plat/common/plat_gicv3.c b/plat/common/plat_gicv3.c
index 2a1f0f5c5..230d90ca9 100644
--- a/plat/common/plat_gicv3.c
+++ b/plat/common/plat_gicv3.c
@@ -33,6 +33,7 @@
 #pragma weak plat_ic_get_interrupt_active
 #pragma weak plat_ic_enable_interrupt
 #pragma weak plat_ic_disable_interrupt
+#pragma weak plat_ic_set_interrupt_priority
 
 CASSERT((INTR_TYPE_S_EL1 == INTR_GROUP1S) &&
 	(INTR_TYPE_NS == INTR_GROUP1NS) &&
@@ -198,6 +199,11 @@ void plat_ic_disable_interrupt(unsigned int id)
 {
 	gicv3_disable_interrupt(id, plat_my_core_pos());
 }
+
+void plat_ic_set_interrupt_priority(unsigned int id, unsigned int priority)
+{
+	gicv3_set_interrupt_priority(id, plat_my_core_pos(), priority);
+}
 #endif
 #ifdef IMAGE_BL32
 
-- 
GitLab