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