Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0+ */
0002 /*
0003  * Main SSAM/SSH controller structure and functionality.
0004  *
0005  * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
0006  */
0007 
0008 #ifndef _SURFACE_AGGREGATOR_CONTROLLER_H
0009 #define _SURFACE_AGGREGATOR_CONTROLLER_H
0010 
0011 #include <linux/kref.h>
0012 #include <linux/list.h>
0013 #include <linux/mutex.h>
0014 #include <linux/rbtree.h>
0015 #include <linux/rwsem.h>
0016 #include <linux/serdev.h>
0017 #include <linux/spinlock.h>
0018 #include <linux/srcu.h>
0019 #include <linux/types.h>
0020 #include <linux/workqueue.h>
0021 
0022 #include <linux/surface_aggregator/controller.h>
0023 #include <linux/surface_aggregator/serial_hub.h>
0024 
0025 #include "ssh_request_layer.h"
0026 
0027 
0028 /* -- Safe counters. -------------------------------------------------------- */
0029 
0030 /**
0031  * struct ssh_seq_counter - Safe counter for SSH sequence IDs.
0032  * @value: The current counter value.
0033  */
0034 struct ssh_seq_counter {
0035     u8 value;
0036 };
0037 
0038 /**
0039  * struct ssh_rqid_counter - Safe counter for SSH request IDs.
0040  * @value: The current counter value.
0041  */
0042 struct ssh_rqid_counter {
0043     u16 value;
0044 };
0045 
0046 
0047 /* -- Event/notification system. -------------------------------------------- */
0048 
0049 /**
0050  * struct ssam_nf_head - Notifier head for SSAM events.
0051  * @srcu: The SRCU struct for synchronization.
0052  * @head: List-head for notifier blocks registered under this head.
0053  */
0054 struct ssam_nf_head {
0055     struct srcu_struct srcu;
0056     struct list_head head;
0057 };
0058 
0059 /**
0060  * struct ssam_nf - Notifier callback- and activation-registry for SSAM events.
0061  * @lock:     Lock guarding (de-)registration of notifier blocks. Note: This
0062  *            lock does not need to be held for notifier calls, only
0063  *            registration and deregistration.
0064  * @refcount: The root of the RB-tree used for reference-counting enabled
0065  *            events/notifications.
0066  * @head:     The list of notifier heads for event/notification callbacks.
0067  */
0068 struct ssam_nf {
0069     struct mutex lock;
0070     struct rb_root refcount;
0071     struct ssam_nf_head head[SSH_NUM_EVENTS];
0072 };
0073 
0074 
0075 /* -- Event/async request completion system. -------------------------------- */
0076 
0077 struct ssam_cplt;
0078 
0079 /**
0080  * struct ssam_event_item - Struct for event queuing and completion.
0081  * @node:     The node in the queue.
0082  * @rqid:     The request ID of the event.
0083  * @ops:      Instance specific functions.
0084  * @ops.free: Callback for freeing this event item.
0085  * @event:    Actual event data.
0086  */
0087 struct ssam_event_item {
0088     struct list_head node;
0089     u16 rqid;
0090 
0091     struct {
0092         void (*free)(struct ssam_event_item *event);
0093     } ops;
0094 
0095     struct ssam_event event;    /* must be last */
0096 };
0097 
0098 /**
0099  * struct ssam_event_queue - Queue for completing received events.
0100  * @cplt: Reference to the completion system on which this queue is active.
0101  * @lock: The lock for any operation on the queue.
0102  * @head: The list-head of the queue.
0103  * @work: The &struct work_struct performing completion work for this queue.
0104  */
0105 struct ssam_event_queue {
0106     struct ssam_cplt *cplt;
0107 
0108     spinlock_t lock;
0109     struct list_head head;
0110     struct work_struct work;
0111 };
0112 
0113 /**
0114  * struct ssam_event_target - Set of queues for a single SSH target ID.
0115  * @queue: The array of queues, one queue per event ID.
0116  */
0117 struct ssam_event_target {
0118     struct ssam_event_queue queue[SSH_NUM_EVENTS];
0119 };
0120 
0121 /**
0122  * struct ssam_cplt - SSAM event/async request completion system.
0123  * @dev:          The device with which this system is associated. Only used
0124  *                for logging.
0125  * @wq:           The &struct workqueue_struct on which all completion work
0126  *                items are queued.
0127  * @event:        Event completion management.
0128  * @event.target: Array of &struct ssam_event_target, one for each target.
0129  * @event.notif:  Notifier callbacks and event activation reference counting.
0130  */
0131 struct ssam_cplt {
0132     struct device *dev;
0133     struct workqueue_struct *wq;
0134 
0135     struct {
0136         struct ssam_event_target target[SSH_NUM_TARGETS];
0137         struct ssam_nf notif;
0138     } event;
0139 };
0140 
0141 
0142 /* -- Main SSAM device structures. ------------------------------------------ */
0143 
0144 /**
0145  * enum ssam_controller_state - State values for &struct ssam_controller.
0146  * @SSAM_CONTROLLER_UNINITIALIZED:
0147  *  The controller has not been initialized yet or has been deinitialized.
0148  * @SSAM_CONTROLLER_INITIALIZED:
0149  *  The controller is initialized, but has not been started yet.
0150  * @SSAM_CONTROLLER_STARTED:
0151  *  The controller has been started and is ready to use.
0152  * @SSAM_CONTROLLER_STOPPED:
0153  *  The controller has been stopped.
0154  * @SSAM_CONTROLLER_SUSPENDED:
0155  *  The controller has been suspended.
0156  */
0157 enum ssam_controller_state {
0158     SSAM_CONTROLLER_UNINITIALIZED,
0159     SSAM_CONTROLLER_INITIALIZED,
0160     SSAM_CONTROLLER_STARTED,
0161     SSAM_CONTROLLER_STOPPED,
0162     SSAM_CONTROLLER_SUSPENDED,
0163 };
0164 
0165 /**
0166  * struct ssam_controller_caps - Controller device capabilities.
0167  * @ssh_power_profile:             SSH power profile.
0168  * @ssh_buffer_size:               SSH driver UART buffer size.
0169  * @screen_on_sleep_idle_timeout:  SAM UART screen-on sleep idle timeout.
0170  * @screen_off_sleep_idle_timeout: SAM UART screen-off sleep idle timeout.
0171  * @d3_closes_handle:              SAM closes UART handle in D3.
0172  *
0173  * Controller and SSH device capabilities found in ACPI.
0174  */
0175 struct ssam_controller_caps {
0176     u32 ssh_power_profile;
0177     u32 ssh_buffer_size;
0178     u32 screen_on_sleep_idle_timeout;
0179     u32 screen_off_sleep_idle_timeout;
0180     u32 d3_closes_handle:1;
0181 };
0182 
0183 /**
0184  * struct ssam_controller - SSAM controller device.
0185  * @kref:  Reference count of the controller.
0186  * @lock:  Main lock for the controller, used to guard state changes.
0187  * @state: Controller state.
0188  * @rtl:   Request transport layer for SSH I/O.
0189  * @cplt:  Completion system for SSH/SSAM events and asynchronous requests.
0190  * @counter:      Safe SSH message ID counters.
0191  * @counter.seq:  Sequence ID counter.
0192  * @counter.rqid: Request ID counter.
0193  * @irq:          Wakeup IRQ resources.
0194  * @irq.num:      The wakeup IRQ number.
0195  * @irq.wakeup_enabled: Whether wakeup by IRQ is enabled during suspend.
0196  * @caps: The controller device capabilities.
0197  */
0198 struct ssam_controller {
0199     struct kref kref;
0200 
0201     struct rw_semaphore lock;
0202     enum ssam_controller_state state;
0203 
0204     struct ssh_rtl rtl;
0205     struct ssam_cplt cplt;
0206 
0207     struct {
0208         struct ssh_seq_counter seq;
0209         struct ssh_rqid_counter rqid;
0210     } counter;
0211 
0212     struct {
0213         int num;
0214         bool wakeup_enabled;
0215     } irq;
0216 
0217     struct ssam_controller_caps caps;
0218 };
0219 
0220 #define to_ssam_controller(ptr, member) \
0221     container_of(ptr, struct ssam_controller, member)
0222 
0223 #define ssam_dbg(ctrl, fmt, ...)  rtl_dbg(&(ctrl)->rtl, fmt, ##__VA_ARGS__)
0224 #define ssam_info(ctrl, fmt, ...) rtl_info(&(ctrl)->rtl, fmt, ##__VA_ARGS__)
0225 #define ssam_warn(ctrl, fmt, ...) rtl_warn(&(ctrl)->rtl, fmt, ##__VA_ARGS__)
0226 #define ssam_err(ctrl, fmt, ...)  rtl_err(&(ctrl)->rtl, fmt, ##__VA_ARGS__)
0227 
0228 /**
0229  * ssam_controller_receive_buf() - Provide input-data to the controller.
0230  * @ctrl: The controller.
0231  * @buf:  The input buffer.
0232  * @n:    The number of bytes in the input buffer.
0233  *
0234  * Provide input data to be evaluated by the controller, which has been
0235  * received via the lower-level transport.
0236  *
0237  * Return: Returns the number of bytes consumed, or, if the packet transport
0238  * layer of the controller has been shut down, %-ESHUTDOWN.
0239  */
0240 static inline
0241 int ssam_controller_receive_buf(struct ssam_controller *ctrl,
0242                 const unsigned char *buf, size_t n)
0243 {
0244     return ssh_ptl_rx_rcvbuf(&ctrl->rtl.ptl, buf, n);
0245 }
0246 
0247 /**
0248  * ssam_controller_write_wakeup() - Notify the controller that the underlying
0249  * device has space available for data to be written.
0250  * @ctrl: The controller.
0251  */
0252 static inline void ssam_controller_write_wakeup(struct ssam_controller *ctrl)
0253 {
0254     ssh_ptl_tx_wakeup_transfer(&ctrl->rtl.ptl);
0255 }
0256 
0257 int ssam_controller_init(struct ssam_controller *ctrl, struct serdev_device *s);
0258 int ssam_controller_start(struct ssam_controller *ctrl);
0259 void ssam_controller_shutdown(struct ssam_controller *ctrl);
0260 void ssam_controller_destroy(struct ssam_controller *ctrl);
0261 
0262 int ssam_notifier_disable_registered(struct ssam_controller *ctrl);
0263 void ssam_notifier_restore_registered(struct ssam_controller *ctrl);
0264 
0265 int ssam_irq_setup(struct ssam_controller *ctrl);
0266 void ssam_irq_free(struct ssam_controller *ctrl);
0267 int ssam_irq_arm_for_wakeup(struct ssam_controller *ctrl);
0268 void ssam_irq_disarm_wakeup(struct ssam_controller *ctrl);
0269 
0270 void ssam_controller_lock(struct ssam_controller *c);
0271 void ssam_controller_unlock(struct ssam_controller *c);
0272 
0273 int ssam_get_firmware_version(struct ssam_controller *ctrl, u32 *version);
0274 int ssam_ctrl_notif_display_off(struct ssam_controller *ctrl);
0275 int ssam_ctrl_notif_display_on(struct ssam_controller *ctrl);
0276 int ssam_ctrl_notif_d0_exit(struct ssam_controller *ctrl);
0277 int ssam_ctrl_notif_d0_entry(struct ssam_controller *ctrl);
0278 
0279 int ssam_controller_suspend(struct ssam_controller *ctrl);
0280 int ssam_controller_resume(struct ssam_controller *ctrl);
0281 
0282 int ssam_event_item_cache_init(void);
0283 void ssam_event_item_cache_destroy(void);
0284 
0285 #endif /* _SURFACE_AGGREGATOR_CONTROLLER_H */