summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--framework/framework.mk1
-rw-r--r--include/runtime_services/sdei.h111
-rw-r--r--lib/sdei/sdei.c188
3 files changed, 300 insertions, 0 deletions
diff --git a/framework/framework.mk b/framework/framework.mk
index a04fc7e..2aac690 100644
--- a/framework/framework.mk
+++ b/framework/framework.mk
@@ -68,6 +68,7 @@ FRAMEWORK_SOURCES := ${AUTOGEN_DIR}/tests_list.c \
lib/power_management/suspend/${ARCH}/asm_tftf_suspend.S \
lib/power_management/suspend/tftf_suspend.c \
lib/psci/psci.c \
+ lib/sdei/sdei.c \
lib/smc/${ARCH}/asm_smc.S \
lib/smc/${ARCH}/smc.c \
${STD_LIB_SOURCES} \
diff --git a/include/runtime_services/sdei.h b/include/runtime_services/sdei.h
new file mode 100644
index 0000000..90ca642
--- /dev/null
+++ b/include/runtime_services/sdei.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SDEI_H__
+#define __SDEI_H__
+
+#define SDEI_VERSION 0xC4000020
+#define SDEI_EVENT_REGISTER 0xC4000021
+#define SDEI_EVENT_ENABLE 0xC4000022
+#define SDEI_EVENT_DISABLE 0xC4000023
+#define SDEI_EVENT_CONTEXT 0xC4000024
+#define SDEI_EVENT_COMPLETE 0xC4000025
+#define SDEI_EVENT_COMPLETE_AND_RESUME 0xC4000026
+
+#define SDEI_EVENT_UNREGISTER 0xC4000027
+#define SDEI_EVENT_STATUS 0xC4000028
+#define SDEI_EVENT_GET_INFO 0xC4000029
+#define SDEI_EVENT_ROUTING_SET 0xC400002A
+#define SDEI_PE_MASK 0xC400002B
+#define SDEI_PE_UNMASK 0xC400002C
+
+#define SDEI_INTERRUPT_BIND 0xC400002D
+#define SDEI_INTERRUPT_RELEASE 0xC400002E
+#define SDEI_EVENT_SIGNAL 0xC400002F
+#define SDEI_FEATURES 0xC4000030
+#define SDEI_PRIVATE_RESET 0xC4000031
+#define SDEI_SHARED_RESET 0xC4000032
+
+/* For debug */
+#define SDEI_SHOW_DEBUG 0xC400003F
+
+/* SDEI_EVENT_REGISTER flags */
+#define SDEI_REGF_RM_ANY 0
+#define SDEI_REGF_RM_PE 1
+
+/* SDEI_EVENT_COMPLETE status flags */
+#define SDEI_EV_HANDLED 0
+#define SDEI_EV_FAILED 1
+
+/* sde event status values in bit position */
+#define SDEI_STATF_REGISTERED 0
+#define SDEI_STATF_ENABLED 1
+#define SDEI_STATF_RUNNING 2
+
+#define SDEI_INFOF_TYPE 0
+#define SDEI_INFOF_SIGNALABLE 1
+#define SDEI_INFOF_ROUTING_MODE 2
+#define SDEI_INFOF_ROUTING_AFF 3
+
+#define SMC_EINVAL 2
+#define SMC_EDENY 3
+#define SMC_EPEND 5
+#define SMC_ENOMEM 10
+
+#define MAKE_SDEI_VERSION(_major, _minor, _vendor) \
+ (((unsigned long long)(_major)) << 48 | \
+ ((unsigned long long)(_minor)) << 32 | \
+ (_vendor))
+
+#ifndef __ASSEMBLY__
+struct sdei_intr_ctx {
+ unsigned int priority;
+ unsigned int num;
+ unsigned int enabled;
+};
+
+typedef int sdei_handler_t(int ev, unsigned long long arg);
+
+long long sdei_version(void);
+long long sdei_interrupt_bind(int intr, struct sdei_intr_ctx *intr_ctx);
+long long sdei_interrupt_release(int intr, const struct sdei_intr_ctx *intr_ctx);
+long long sdei_event_register(int ev, sdei_handler_t *ep,
+ unsigned long long ep_arg, int flags, unsigned long long mpidr);
+long long sdei_event_unregister(int ev);
+long long sdei_event_enable(int ev);
+long long sdei_event_disable(int ev);
+long long sdei_pe_mask(void);
+long long sdei_pe_unmask(void);
+long long sdei_private_reset(void);
+long long sdei_shared_reset(void);
+long long sdei_event_signal(unsigned long long mpidr);
+#endif /* __ASSEMBLY__ */
+
+#endif /* __SDEI_H__ */
diff --git a/lib/sdei/sdei.c b/lib/sdei/sdei.c
new file mode 100644
index 0000000..f7b6ec7
--- /dev/null
+++ b/lib/sdei/sdei.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arm_gic.h>
+#include <assert.h>
+#include <sdei.h>
+#include <smc.h>
+#include <tftf_lib.h>
+
+long long sdei_version(void)
+{
+ smc_args args = { SDEI_VERSION };
+ smc_ret_values ret;
+
+ ret = tftf_smc(&args);
+ return ret.ret0;
+}
+
+long long sdei_interrupt_bind(int intr, struct sdei_intr_ctx *intr_ctx)
+{
+ smc_args args = { 0 };
+ smc_ret_values ret;
+
+ assert(intr_ctx);
+
+ intr_ctx->priority = arm_gic_get_intr_priority(intr);
+ intr_ctx->num = intr;
+ intr_ctx->enabled = arm_gic_intr_enabled(intr);
+ arm_gic_intr_disable(intr);
+
+ args.arg0 = SDEI_INTERRUPT_BIND;
+ args.arg1 = intr;
+ ret = tftf_smc(&args);
+ if (ret.ret0 < 0) {
+ arm_gic_set_intr_priority(intr_ctx->num, intr_ctx->priority);
+ if (intr_ctx->enabled)
+ arm_gic_intr_enable(intr_ctx->num);
+ }
+
+ return ret.ret0;
+}
+
+long long sdei_interrupt_release(int intr, const struct sdei_intr_ctx *intr_ctx)
+{
+ smc_args args = { 0 };
+ smc_ret_values ret;
+
+ assert(intr_ctx);
+
+ args.arg0 = SDEI_INTERRUPT_RELEASE;
+ args.arg1 = intr;
+ ret = tftf_smc(&args);
+ if (ret.ret0 == 0) {
+ arm_gic_set_intr_priority(intr_ctx->num, intr_ctx->priority);
+ if (intr_ctx->enabled)
+ arm_gic_intr_enable(intr_ctx->num);
+ }
+
+ return ret.ret0;
+}
+
+long long sdei_event_register(int ev, sdei_handler_t *ep,
+ unsigned long long ep_arg, int flags, unsigned long long mpidr)
+{
+ smc_args args = { 0 };
+ smc_ret_values ret;
+
+ args.arg0 = SDEI_EVENT_REGISTER;
+ args.arg1 = ev;
+ args.arg2 = (u_register_t)ep;
+ args.arg3 = ep_arg;
+ args.arg4 = flags;
+ args.arg5 = mpidr;
+ ret = tftf_smc(&args);
+ return ret.ret0;
+}
+
+long long sdei_event_unregister(int ev)
+{
+ smc_args args = { 0 };
+ smc_ret_values ret;
+
+ args.arg0 = SDEI_EVENT_UNREGISTER;
+ args.arg1 = ev;
+ ret = tftf_smc(&args);
+ return ret.ret0;
+}
+
+long long sdei_event_enable(int ev)
+{
+ smc_args args = { 0 };
+ smc_ret_values ret;
+
+ args.arg0 = SDEI_EVENT_ENABLE;
+ args.arg1 = ev;
+ ret = tftf_smc(&args);
+ return ret.ret0;
+}
+
+long long sdei_event_disable(int ev)
+{
+ smc_args args = { 0 };
+ smc_ret_values ret;
+
+ args.arg0 = SDEI_EVENT_DISABLE;
+ args.arg1 = ev;
+ ret = tftf_smc(&args);
+ return ret.ret0;
+}
+
+long long sdei_pe_mask(void)
+{
+ smc_args args = { 0 };
+ smc_ret_values ret;
+
+ args.arg0 = SDEI_PE_MASK;
+ ret = tftf_smc(&args);
+ return ret.ret0;
+}
+
+long long sdei_pe_unmask(void)
+{
+ smc_args args = { 0 };
+ smc_ret_values ret;
+
+ args.arg0 = SDEI_PE_UNMASK;
+ ret = tftf_smc(&args);
+ return ret.ret0;
+}
+
+long long sdei_private_reset(void)
+{
+ smc_args args = { 0 };
+ smc_ret_values ret;
+
+ args.arg0 = SDEI_PRIVATE_RESET;
+ ret = tftf_smc(&args);
+ return ret.ret0;
+}
+
+long long sdei_shared_reset(void)
+{
+ smc_args args = { 0 };
+ smc_ret_values ret;
+
+ args.arg0 = SDEI_SHARED_RESET;
+ ret = tftf_smc(&args);
+ return ret.ret0;
+}
+
+long long sdei_event_signal(unsigned long long mpidr)
+{
+ smc_args args = { 0 };
+ smc_ret_values ret;
+
+ args.arg0 = SDEI_EVENT_SIGNAL;
+ args.arg1 = 0; /* must be event 0 */
+ args.arg2 = mpidr;
+ ret = tftf_smc(&args);
+ return ret.ret0;
+}