xref: /OK3568_Linux_fs/kernel/include/linux/arm_sdei.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun // Copyright (C) 2017 Arm Ltd.
3*4882a593Smuzhiyun #ifndef __LINUX_ARM_SDEI_H
4*4882a593Smuzhiyun #define __LINUX_ARM_SDEI_H
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #include <uapi/linux/arm_sdei.h>
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <acpi/ghes.h>
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #ifdef CONFIG_ARM_SDE_INTERFACE
11*4882a593Smuzhiyun #include <asm/sdei.h>
12*4882a593Smuzhiyun #endif
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun /* Arch code should override this to set the entry point from firmware... */
15*4882a593Smuzhiyun #ifndef sdei_arch_get_entry_point
16*4882a593Smuzhiyun #define sdei_arch_get_entry_point(conduit)	(0)
17*4882a593Smuzhiyun #endif
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun /*
20*4882a593Smuzhiyun  * When an event occurs sdei_event_handler() will call a user-provided callback
21*4882a593Smuzhiyun  * like this in NMI context on the CPU that received the event.
22*4882a593Smuzhiyun  */
23*4882a593Smuzhiyun typedef int (sdei_event_callback)(u32 event, struct pt_regs *regs, void *arg);
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun /*
26*4882a593Smuzhiyun  * Register your callback to claim an event. The event must be described
27*4882a593Smuzhiyun  * by firmware.
28*4882a593Smuzhiyun  */
29*4882a593Smuzhiyun int sdei_event_register(u32 event_num, sdei_event_callback *cb, void *arg);
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun /*
32*4882a593Smuzhiyun  * Calls to sdei_event_unregister() may return EINPROGRESS. Keep calling
33*4882a593Smuzhiyun  * it until it succeeds.
34*4882a593Smuzhiyun  */
35*4882a593Smuzhiyun int sdei_event_unregister(u32 event_num);
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun int sdei_event_enable(u32 event_num);
38*4882a593Smuzhiyun int sdei_event_disable(u32 event_num);
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun #ifdef CONFIG_FIQ_DEBUGGER_TRUST_ZONE
41*4882a593Smuzhiyun #ifdef CONFIG_ARM_SDE_INTERFACE
42*4882a593Smuzhiyun int sdei_event_enable_nolock(u32 event_num);
43*4882a593Smuzhiyun int sdei_event_disable_nolock(u32 event_num);
44*4882a593Smuzhiyun int sdei_event_routing_set_nolock(u32 event_num, unsigned long flags,
45*4882a593Smuzhiyun 				  unsigned long affinity);
46*4882a593Smuzhiyun int sdei_event_routing_set(u32 event_num, unsigned long flags,
47*4882a593Smuzhiyun 			   unsigned long affinity);
48*4882a593Smuzhiyun int sdei_interrupt_bind(u32 intr_num, u32 *event_num);
49*4882a593Smuzhiyun int sdei_interrupt_release(u32 event_num);
50*4882a593Smuzhiyun #else
sdei_event_enable_nolock(u32 event_num)51*4882a593Smuzhiyun static inline int sdei_event_enable_nolock(u32 event_num)
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun 	return SDEI_NOT_SUPPORTED;
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun 
sdei_event_disable_nolock(u32 event_num)56*4882a593Smuzhiyun static inline int sdei_event_disable_nolock(u32 event_num)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun 	return SDEI_NOT_SUPPORTED;
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun 
sdei_event_routing_set_nolock(u32 event_num,unsigned long flags,unsigned long affinity)61*4882a593Smuzhiyun static inline int sdei_event_routing_set_nolock(u32 event_num,
62*4882a593Smuzhiyun 						unsigned long flags,
63*4882a593Smuzhiyun 						unsigned long affinity)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun 	return SDEI_NOT_SUPPORTED;
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun 
sdei_event_routing_set(u32 event_num,unsigned long flags,unsigned long affinity)68*4882a593Smuzhiyun static inline int sdei_event_routing_set(u32 event_num,
69*4882a593Smuzhiyun 					 unsigned long flags,
70*4882a593Smuzhiyun 					 unsigned long affinity)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun 	return SDEI_NOT_SUPPORTED;
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun 
sdei_interrupt_bind(u32 intr_num,u32 * event_num)75*4882a593Smuzhiyun static inline int sdei_interrupt_bind(u32 intr_num, u32 *event_num)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun 	return SDEI_NOT_SUPPORTED;
78*4882a593Smuzhiyun }
79*4882a593Smuzhiyun 
sdei_interrupt_release(u32 event_num)80*4882a593Smuzhiyun static inline int sdei_interrupt_release(u32 event_num)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun 	return SDEI_NOT_SUPPORTED;
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun #endif /* CONFIG_ARM_SDE_INTERFACE */
85*4882a593Smuzhiyun #endif /* CONFIG_FIQ_DEBUGGER_TRUST_ZONE */
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun /* GHES register/unregister helpers */
88*4882a593Smuzhiyun int sdei_register_ghes(struct ghes *ghes, sdei_event_callback *normal_cb,
89*4882a593Smuzhiyun 		       sdei_event_callback *critical_cb);
90*4882a593Smuzhiyun int sdei_unregister_ghes(struct ghes *ghes);
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun #ifdef CONFIG_ARM_SDE_INTERFACE
93*4882a593Smuzhiyun /* For use by arch code when CPU hotplug notifiers are not appropriate. */
94*4882a593Smuzhiyun int sdei_mask_local_cpu(void);
95*4882a593Smuzhiyun int sdei_unmask_local_cpu(void);
96*4882a593Smuzhiyun #else
sdei_mask_local_cpu(void)97*4882a593Smuzhiyun static inline int sdei_mask_local_cpu(void) { return 0; }
sdei_unmask_local_cpu(void)98*4882a593Smuzhiyun static inline int sdei_unmask_local_cpu(void) { return 0; }
99*4882a593Smuzhiyun #endif /* CONFIG_ARM_SDE_INTERFACE */
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun /*
103*4882a593Smuzhiyun  * This struct represents an event that has been registered. The driver
104*4882a593Smuzhiyun  * maintains a list of all events, and which ones are registered. (Private
105*4882a593Smuzhiyun  * events have one entry in the list, but are registered on each CPU).
106*4882a593Smuzhiyun  * A pointer to this struct is passed to firmware, and back to the event
107*4882a593Smuzhiyun  * handler. The event handler can then use this to invoke the registered
108*4882a593Smuzhiyun  * callback, without having to walk the list.
109*4882a593Smuzhiyun  *
110*4882a593Smuzhiyun  * For CPU private events, this structure is per-cpu.
111*4882a593Smuzhiyun  */
112*4882a593Smuzhiyun struct sdei_registered_event {
113*4882a593Smuzhiyun 	/* For use by arch code: */
114*4882a593Smuzhiyun 	struct pt_regs          interrupted_regs;
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	sdei_event_callback	*callback;
117*4882a593Smuzhiyun 	void			*callback_arg;
118*4882a593Smuzhiyun 	u32			 event_num;
119*4882a593Smuzhiyun 	u8			 priority;
120*4882a593Smuzhiyun };
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun /* The arch code entry point should then call this when an event arrives. */
123*4882a593Smuzhiyun int notrace sdei_event_handler(struct pt_regs *regs,
124*4882a593Smuzhiyun 			       struct sdei_registered_event *arg);
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun /* arch code may use this to retrieve the extra registers. */
127*4882a593Smuzhiyun int sdei_api_event_context(u32 query, u64 *result);
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun #endif /* __LINUX_ARM_SDEI_H */
130