Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | /* SPDX-License-Identifier: GPL-2.0+ */ /* * Main SSAM/SSH controller structure and functionality. * * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com> */ #ifndef _SURFACE_AGGREGATOR_CONTROLLER_H #define _SURFACE_AGGREGATOR_CONTROLLER_H #include <linux/kref.h> #include <linux/list.h> #include <linux/mutex.h> #include <linux/rbtree.h> #include <linux/rwsem.h> #include <linux/serdev.h> #include <linux/spinlock.h> #include <linux/srcu.h> #include <linux/types.h> #include <linux/workqueue.h> #include <linux/surface_aggregator/controller.h> #include <linux/surface_aggregator/serial_hub.h> #include "ssh_request_layer.h" /* -- Safe counters. -------------------------------------------------------- */ /** * struct ssh_seq_counter - Safe counter for SSH sequence IDs. * @value: The current counter value. */ struct ssh_seq_counter { u8 value; }; /** * struct ssh_rqid_counter - Safe counter for SSH request IDs. * @value: The current counter value. */ struct ssh_rqid_counter { u16 value; }; /* -- Event/notification system. -------------------------------------------- */ /** * struct ssam_nf_head - Notifier head for SSAM events. * @srcu: The SRCU struct for synchronization. * @head: List-head for notifier blocks registered under this head. */ struct ssam_nf_head { struct srcu_struct srcu; struct list_head head; }; /** * struct ssam_nf - Notifier callback- and activation-registry for SSAM events. * @lock: Lock guarding (de-)registration of notifier blocks. Note: This * lock does not need to be held for notifier calls, only * registration and deregistration. * @refcount: The root of the RB-tree used for reference-counting enabled * events/notifications. * @head: The list of notifier heads for event/notification callbacks. */ struct ssam_nf { struct mutex lock; struct rb_root refcount; struct ssam_nf_head head[SSH_NUM_EVENTS]; }; /* -- Event/async request completion system. -------------------------------- */ struct ssam_cplt; /** * struct ssam_event_item - Struct for event queuing and completion. * @node: The node in the queue. * @rqid: The request ID of the event. * @ops: Instance specific functions. * @ops.free: Callback for freeing this event item. * @event: Actual event data. */ struct ssam_event_item { struct list_head node; u16 rqid; struct { void (*free)(struct ssam_event_item *event); } ops; struct ssam_event event; /* must be last */ }; /** * struct ssam_event_queue - Queue for completing received events. * @cplt: Reference to the completion system on which this queue is active. * @lock: The lock for any operation on the queue. * @head: The list-head of the queue. * @work: The &struct work_struct performing completion work for this queue. */ struct ssam_event_queue { struct ssam_cplt *cplt; spinlock_t lock; struct list_head head; struct work_struct work; }; /** * struct ssam_event_target - Set of queues for a single SSH target ID. * @queue: The array of queues, one queue per event ID. */ struct ssam_event_target { struct ssam_event_queue queue[SSH_NUM_EVENTS]; }; /** * struct ssam_cplt - SSAM event/async request completion system. * @dev: The device with which this system is associated. Only used * for logging. * @wq: The &struct workqueue_struct on which all completion work * items are queued. * @event: Event completion management. * @event.target: Array of &struct ssam_event_target, one for each target. * @event.notif: Notifier callbacks and event activation reference counting. */ struct ssam_cplt { struct device *dev; struct workqueue_struct *wq; struct { struct ssam_event_target target[SSH_NUM_TARGETS]; struct ssam_nf notif; } event; }; /* -- Main SSAM device structures. ------------------------------------------ */ /** * enum ssam_controller_state - State values for &struct ssam_controller. * @SSAM_CONTROLLER_UNINITIALIZED: * The controller has not been initialized yet or has been deinitialized. * @SSAM_CONTROLLER_INITIALIZED: * The controller is initialized, but has not been started yet. * @SSAM_CONTROLLER_STARTED: * The controller has been started and is ready to use. * @SSAM_CONTROLLER_STOPPED: * The controller has been stopped. * @SSAM_CONTROLLER_SUSPENDED: * The controller has been suspended. */ enum ssam_controller_state { SSAM_CONTROLLER_UNINITIALIZED, SSAM_CONTROLLER_INITIALIZED, SSAM_CONTROLLER_STARTED, SSAM_CONTROLLER_STOPPED, SSAM_CONTROLLER_SUSPENDED, }; /** * struct ssam_controller_caps - Controller device capabilities. * @ssh_power_profile: SSH power profile. * @ssh_buffer_size: SSH driver UART buffer size. * @screen_on_sleep_idle_timeout: SAM UART screen-on sleep idle timeout. * @screen_off_sleep_idle_timeout: SAM UART screen-off sleep idle timeout. * @d3_closes_handle: SAM closes UART handle in D3. * * Controller and SSH device capabilities found in ACPI. */ struct ssam_controller_caps { u32 ssh_power_profile; u32 ssh_buffer_size; u32 screen_on_sleep_idle_timeout; u32 screen_off_sleep_idle_timeout; u32 d3_closes_handle:1; }; /** * struct ssam_controller - SSAM controller device. * @kref: Reference count of the controller. * @lock: Main lock for the controller, used to guard state changes. * @state: Controller state. * @rtl: Request transport layer for SSH I/O. * @cplt: Completion system for SSH/SSAM events and asynchronous requests. * @counter: Safe SSH message ID counters. * @counter.seq: Sequence ID counter. * @counter.rqid: Request ID counter. * @irq: Wakeup IRQ resources. * @irq.num: The wakeup IRQ number. * @irq.wakeup_enabled: Whether wakeup by IRQ is enabled during suspend. * @caps: The controller device capabilities. */ struct ssam_controller { struct kref kref; struct rw_semaphore lock; enum ssam_controller_state state; struct ssh_rtl rtl; struct ssam_cplt cplt; struct { struct ssh_seq_counter seq; struct ssh_rqid_counter rqid; } counter; struct { int num; bool wakeup_enabled; } irq; struct ssam_controller_caps caps; }; #define to_ssam_controller(ptr, member) \ container_of(ptr, struct ssam_controller, member) #define ssam_dbg(ctrl, fmt, ...) rtl_dbg(&(ctrl)->rtl, fmt, ##__VA_ARGS__) #define ssam_info(ctrl, fmt, ...) rtl_info(&(ctrl)->rtl, fmt, ##__VA_ARGS__) #define ssam_warn(ctrl, fmt, ...) rtl_warn(&(ctrl)->rtl, fmt, ##__VA_ARGS__) #define ssam_err(ctrl, fmt, ...) rtl_err(&(ctrl)->rtl, fmt, ##__VA_ARGS__) /** * ssam_controller_receive_buf() - Provide input-data to the controller. * @ctrl: The controller. * @buf: The input buffer. * @n: The number of bytes in the input buffer. * * Provide input data to be evaluated by the controller, which has been * received via the lower-level transport. * * Return: Returns the number of bytes consumed, or, if the packet transport * layer of the controller has been shut down, %-ESHUTDOWN. */ static inline int ssam_controller_receive_buf(struct ssam_controller *ctrl, const unsigned char *buf, size_t n) { return ssh_ptl_rx_rcvbuf(&ctrl->rtl.ptl, buf, n); } /** * ssam_controller_write_wakeup() - Notify the controller that the underlying * device has space available for data to be written. * @ctrl: The controller. */ static inline void ssam_controller_write_wakeup(struct ssam_controller *ctrl) { ssh_ptl_tx_wakeup_transfer(&ctrl->rtl.ptl); } int ssam_controller_init(struct ssam_controller *ctrl, struct serdev_device *s); int ssam_controller_start(struct ssam_controller *ctrl); void ssam_controller_shutdown(struct ssam_controller *ctrl); void ssam_controller_destroy(struct ssam_controller *ctrl); int ssam_notifier_disable_registered(struct ssam_controller *ctrl); void ssam_notifier_restore_registered(struct ssam_controller *ctrl); int ssam_irq_setup(struct ssam_controller *ctrl); void ssam_irq_free(struct ssam_controller *ctrl); int ssam_irq_arm_for_wakeup(struct ssam_controller *ctrl); void ssam_irq_disarm_wakeup(struct ssam_controller *ctrl); void ssam_controller_lock(struct ssam_controller *c); void ssam_controller_unlock(struct ssam_controller *c); int ssam_get_firmware_version(struct ssam_controller *ctrl, u32 *version); int ssam_ctrl_notif_display_off(struct ssam_controller *ctrl); int ssam_ctrl_notif_display_on(struct ssam_controller *ctrl); int ssam_ctrl_notif_d0_exit(struct ssam_controller *ctrl); int ssam_ctrl_notif_d0_entry(struct ssam_controller *ctrl); int ssam_controller_suspend(struct ssam_controller *ctrl); int ssam_controller_resume(struct ssam_controller *ctrl); int ssam_event_item_cache_init(void); void ssam_event_item_cache_destroy(void); #endif /* _SURFACE_AGGREGATOR_CONTROLLER_H */ |