James Morse | ad6eb31 | 2018-01-08 15:38:09 +0000 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | // Copyright (C) 2017 Arm Ltd. |
| 3 | #ifndef __LINUX_ARM_SDEI_H |
| 4 | #define __LINUX_ARM_SDEI_H |
| 5 | |
| 6 | #include <uapi/linux/arm_sdei.h> |
| 7 | |
| 8 | enum sdei_conduit_types { |
| 9 | CONDUIT_INVALID = 0, |
| 10 | CONDUIT_SMC, |
| 11 | CONDUIT_HVC, |
| 12 | }; |
| 13 | |
James Morse | f96935d | 2019-01-29 18:49:01 +0000 | [diff] [blame] | 14 | #include <acpi/ghes.h> |
James Morse | f9f0539 | 2019-01-29 18:49:02 +0000 | [diff] [blame] | 15 | |
| 16 | #ifdef CONFIG_ARM_SDE_INTERFACE |
James Morse | ad6eb31 | 2018-01-08 15:38:09 +0000 | [diff] [blame] | 17 | #include <asm/sdei.h> |
James Morse | f9f0539 | 2019-01-29 18:49:02 +0000 | [diff] [blame] | 18 | #endif |
James Morse | ad6eb31 | 2018-01-08 15:38:09 +0000 | [diff] [blame] | 19 | |
| 20 | /* Arch code should override this to set the entry point from firmware... */ |
| 21 | #ifndef sdei_arch_get_entry_point |
| 22 | #define sdei_arch_get_entry_point(conduit) (0) |
| 23 | #endif |
| 24 | |
| 25 | /* |
| 26 | * When an event occurs sdei_event_handler() will call a user-provided callback |
| 27 | * like this in NMI context on the CPU that received the event. |
| 28 | */ |
| 29 | typedef int (sdei_event_callback)(u32 event, struct pt_regs *regs, void *arg); |
| 30 | |
| 31 | /* |
| 32 | * Register your callback to claim an event. The event must be described |
| 33 | * by firmware. |
| 34 | */ |
| 35 | int sdei_event_register(u32 event_num, sdei_event_callback *cb, void *arg); |
| 36 | |
| 37 | /* |
| 38 | * Calls to sdei_event_unregister() may return EINPROGRESS. Keep calling |
| 39 | * it until it succeeds. |
| 40 | */ |
| 41 | int sdei_event_unregister(u32 event_num); |
| 42 | |
| 43 | int sdei_event_enable(u32 event_num); |
| 44 | int sdei_event_disable(u32 event_num); |
| 45 | |
James Morse | f96935d | 2019-01-29 18:49:01 +0000 | [diff] [blame] | 46 | /* GHES register/unregister helpers */ |
| 47 | int sdei_register_ghes(struct ghes *ghes, sdei_event_callback *normal_cb, |
| 48 | sdei_event_callback *critical_cb); |
| 49 | int sdei_unregister_ghes(struct ghes *ghes); |
| 50 | |
James Morse | ad6eb31 | 2018-01-08 15:38:09 +0000 | [diff] [blame] | 51 | #ifdef CONFIG_ARM_SDE_INTERFACE |
| 52 | /* For use by arch code when CPU hotplug notifiers are not appropriate. */ |
| 53 | int sdei_mask_local_cpu(void); |
| 54 | int sdei_unmask_local_cpu(void); |
| 55 | #else |
| 56 | static inline int sdei_mask_local_cpu(void) { return 0; } |
| 57 | static inline int sdei_unmask_local_cpu(void) { return 0; } |
| 58 | #endif /* CONFIG_ARM_SDE_INTERFACE */ |
| 59 | |
| 60 | |
| 61 | /* |
| 62 | * This struct represents an event that has been registered. The driver |
| 63 | * maintains a list of all events, and which ones are registered. (Private |
| 64 | * events have one entry in the list, but are registered on each CPU). |
| 65 | * A pointer to this struct is passed to firmware, and back to the event |
| 66 | * handler. The event handler can then use this to invoke the registered |
| 67 | * callback, without having to walk the list. |
| 68 | * |
| 69 | * For CPU private events, this structure is per-cpu. |
| 70 | */ |
| 71 | struct sdei_registered_event { |
| 72 | /* For use by arch code: */ |
| 73 | struct pt_regs interrupted_regs; |
| 74 | |
| 75 | sdei_event_callback *callback; |
| 76 | void *callback_arg; |
| 77 | u32 event_num; |
| 78 | u8 priority; |
| 79 | }; |
| 80 | |
| 81 | /* The arch code entry point should then call this when an event arrives. */ |
| 82 | int notrace sdei_event_handler(struct pt_regs *regs, |
| 83 | struct sdei_registered_event *arg); |
| 84 | |
| 85 | /* arch code may use this to retrieve the extra registers. */ |
| 86 | int sdei_api_event_context(u32 query, u64 *result); |
| 87 | |
| 88 | #endif /* __LINUX_ARM_SDEI_H */ |