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