1 /* SPDX-License-Identifier: GPL-2.0+ */
3 * Surface System Aggregator Module (SSAM) bus and client-device subsystem.
5 * Main interface for the surface-aggregator bus, surface-aggregator client
6 * devices, and respective drivers building on top of the SSAM controller.
7 * Provides support for non-platform/non-ACPI SSAM clients via dedicated
10 * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
13 #ifndef _LINUX_SURFACE_AGGREGATOR_DEVICE_H
14 #define _LINUX_SURFACE_AGGREGATOR_DEVICE_H
16 #include <linux/device.h>
17 #include <linux/mod_devicetable.h>
18 #include <linux/types.h>
20 #include <linux/surface_aggregator/controller.h>
23 /* -- Surface System Aggregator Module bus. --------------------------------- */
26 * enum ssam_device_domain - SAM device domain.
27 * @SSAM_DOMAIN_VIRTUAL: Virtual device.
28 * @SSAM_DOMAIN_SERIALHUB: Physical device connected via Surface Serial Hub.
30 enum ssam_device_domain {
31 SSAM_DOMAIN_VIRTUAL = 0x00,
32 SSAM_DOMAIN_SERIALHUB = 0x01,
36 * enum ssam_virtual_tc - Target categories for the virtual SAM domain.
37 * @SSAM_VIRTUAL_TC_HUB: Device hub category.
39 enum ssam_virtual_tc {
40 SSAM_VIRTUAL_TC_HUB = 0x00,
44 * struct ssam_device_uid - Unique identifier for SSAM device.
45 * @domain: Domain of the device.
46 * @category: Target category of the device.
47 * @target: Target ID of the device.
48 * @instance: Instance ID of the device.
49 * @function: Sub-function of the device. This field can be used to split a
50 * single SAM device into multiple virtual subdevices to separate
51 * different functionality of that device and allow one driver per
54 struct ssam_device_uid {
63 * Special values for device matching.
65 * These values are intended to be used with SSAM_DEVICE(), SSAM_VDEV(), and
66 * SSAM_SDEV() exclusively. Specifically, they are used to initialize the
67 * match_flags member of the device ID structure. Do not use them directly
68 * with struct ssam_device_id or struct ssam_device_uid.
70 #define SSAM_ANY_TID 0xffff
71 #define SSAM_ANY_IID 0xffff
72 #define SSAM_ANY_FUN 0xffff
75 * SSAM_DEVICE() - Initialize a &struct ssam_device_id with the given
77 * @d: Domain of the device.
78 * @cat: Target category of the device.
79 * @tid: Target ID of the device.
80 * @iid: Instance ID of the device.
81 * @fun: Sub-function of the device.
83 * Initializes a &struct ssam_device_id with the given parameters. See &struct
84 * ssam_device_uid for details regarding the parameters. The special values
85 * %SSAM_ANY_TID, %SSAM_ANY_IID, and %SSAM_ANY_FUN can be used to specify that
86 * matching should ignore target ID, instance ID, and/or sub-function,
87 * respectively. This macro initializes the ``match_flags`` field based on the
90 * Note: The parameters @d and @cat must be valid &u8 values, the parameters
91 * @tid, @iid, and @fun must be either valid &u8 values or %SSAM_ANY_TID,
92 * %SSAM_ANY_IID, or %SSAM_ANY_FUN, respectively. Other non-&u8 values are not
95 #define SSAM_DEVICE(d, cat, tid, iid, fun) \
96 .match_flags = (((tid) != SSAM_ANY_TID) ? SSAM_MATCH_TARGET : 0) \
97 | (((iid) != SSAM_ANY_IID) ? SSAM_MATCH_INSTANCE : 0) \
98 | (((fun) != SSAM_ANY_FUN) ? SSAM_MATCH_FUNCTION : 0), \
101 .target = ((tid) != SSAM_ANY_TID) ? (tid) : 0, \
102 .instance = ((iid) != SSAM_ANY_IID) ? (iid) : 0, \
103 .function = ((fun) != SSAM_ANY_FUN) ? (fun) : 0 \
106 * SSAM_VDEV() - Initialize a &struct ssam_device_id as virtual device with
107 * the given parameters.
108 * @cat: Target category of the device.
109 * @tid: Target ID of the device.
110 * @iid: Instance ID of the device.
111 * @fun: Sub-function of the device.
113 * Initializes a &struct ssam_device_id with the given parameters in the
114 * virtual domain. See &struct ssam_device_uid for details regarding the
115 * parameters. The special values %SSAM_ANY_TID, %SSAM_ANY_IID, and
116 * %SSAM_ANY_FUN can be used to specify that matching should ignore target ID,
117 * instance ID, and/or sub-function, respectively. This macro initializes the
118 * ``match_flags`` field based on the given parameters.
120 * Note: The parameter @cat must be a valid &u8 value, the parameters @tid,
121 * @iid, and @fun must be either valid &u8 values or %SSAM_ANY_TID,
122 * %SSAM_ANY_IID, or %SSAM_ANY_FUN, respectively. Other non-&u8 values are not
125 #define SSAM_VDEV(cat, tid, iid, fun) \
126 SSAM_DEVICE(SSAM_DOMAIN_VIRTUAL, SSAM_VIRTUAL_TC_##cat, tid, iid, fun)
129 * SSAM_SDEV() - Initialize a &struct ssam_device_id as physical SSH device
130 * with the given parameters.
131 * @cat: Target category of the device.
132 * @tid: Target ID of the device.
133 * @iid: Instance ID of the device.
134 * @fun: Sub-function of the device.
136 * Initializes a &struct ssam_device_id with the given parameters in the SSH
137 * domain. See &struct ssam_device_uid for details regarding the parameters.
138 * The special values %SSAM_ANY_TID, %SSAM_ANY_IID, and %SSAM_ANY_FUN can be
139 * used to specify that matching should ignore target ID, instance ID, and/or
140 * sub-function, respectively. This macro initializes the ``match_flags``
141 * field based on the given parameters.
143 * Note: The parameter @cat must be a valid &u8 value, the parameters @tid,
144 * @iid, and @fun must be either valid &u8 values or %SSAM_ANY_TID,
145 * %SSAM_ANY_IID, or %SSAM_ANY_FUN, respectively. Other non-&u8 values are not
148 #define SSAM_SDEV(cat, tid, iid, fun) \
149 SSAM_DEVICE(SSAM_DOMAIN_SERIALHUB, SSAM_SSH_TC_##cat, tid, iid, fun)
152 * struct ssam_device - SSAM client device.
153 * @dev: Driver model representation of the device.
154 * @ctrl: SSAM controller managing this device.
155 * @uid: UID identifying the device.
159 struct ssam_controller *ctrl;
161 struct ssam_device_uid uid;
165 * struct ssam_device_driver - SSAM client device driver.
166 * @driver: Base driver model structure.
167 * @match_table: Match table specifying which devices the driver should bind to.
168 * @probe: Called when the driver is being bound to a device.
169 * @remove: Called when the driver is being unbound from the device.
171 struct ssam_device_driver {
172 struct device_driver driver;
174 const struct ssam_device_id *match_table;
176 int (*probe)(struct ssam_device *sdev);
177 void (*remove)(struct ssam_device *sdev);
180 extern struct bus_type ssam_bus_type;
181 extern const struct device_type ssam_device_type;
184 * is_ssam_device() - Check if the given device is a SSAM client device.
185 * @d: The device to test the type of.
187 * Return: Returns %true if the specified device is of type &struct
188 * ssam_device, i.e. the device type points to %ssam_device_type, and %false
191 static inline bool is_ssam_device(struct device *d)
193 return d->type == &ssam_device_type;
197 * to_ssam_device() - Casts the given device to a SSAM client device.
198 * @d: The device to cast.
200 * Casts the given &struct device to a &struct ssam_device. The caller has to
201 * ensure that the given device is actually enclosed in a &struct ssam_device,
202 * e.g. by calling is_ssam_device().
204 * Return: Returns a pointer to the &struct ssam_device wrapping the given
207 static inline struct ssam_device *to_ssam_device(struct device *d)
209 return container_of(d, struct ssam_device, dev);
213 * to_ssam_device_driver() - Casts the given device driver to a SSAM client
215 * @d: The driver to cast.
217 * Casts the given &struct device_driver to a &struct ssam_device_driver. The
218 * caller has to ensure that the given driver is actually enclosed in a
219 * &struct ssam_device_driver.
221 * Return: Returns the pointer to the &struct ssam_device_driver wrapping the
222 * given device driver @d.
225 struct ssam_device_driver *to_ssam_device_driver(struct device_driver *d)
227 return container_of(d, struct ssam_device_driver, driver);
230 const struct ssam_device_id *ssam_device_id_match(const struct ssam_device_id *table,
231 const struct ssam_device_uid uid);
233 const struct ssam_device_id *ssam_device_get_match(const struct ssam_device *dev);
235 const void *ssam_device_get_match_data(const struct ssam_device *dev);
237 struct ssam_device *ssam_device_alloc(struct ssam_controller *ctrl,
238 struct ssam_device_uid uid);
240 int ssam_device_add(struct ssam_device *sdev);
241 void ssam_device_remove(struct ssam_device *sdev);
244 * ssam_device_get() - Increment reference count of SSAM client device.
245 * @sdev: The device to increment the reference count of.
247 * Increments the reference count of the given SSAM client device by
248 * incrementing the reference count of the enclosed &struct device via
251 * See ssam_device_put() for the counter-part of this function.
253 * Return: Returns the device provided as input.
255 static inline struct ssam_device *ssam_device_get(struct ssam_device *sdev)
257 return sdev ? to_ssam_device(get_device(&sdev->dev)) : NULL;
261 * ssam_device_put() - Decrement reference count of SSAM client device.
262 * @sdev: The device to decrement the reference count of.
264 * Decrements the reference count of the given SSAM client device by
265 * decrementing the reference count of the enclosed &struct device via
268 * See ssam_device_get() for the counter-part of this function.
270 static inline void ssam_device_put(struct ssam_device *sdev)
273 put_device(&sdev->dev);
277 * ssam_device_get_drvdata() - Get driver-data of SSAM client device.
278 * @sdev: The device to get the driver-data from.
280 * Return: Returns the driver-data of the given device, previously set via
281 * ssam_device_set_drvdata().
283 static inline void *ssam_device_get_drvdata(struct ssam_device *sdev)
285 return dev_get_drvdata(&sdev->dev);
289 * ssam_device_set_drvdata() - Set driver-data of SSAM client device.
290 * @sdev: The device to set the driver-data of.
291 * @data: The data to set the device's driver-data pointer to.
293 static inline void ssam_device_set_drvdata(struct ssam_device *sdev, void *data)
295 dev_set_drvdata(&sdev->dev, data);
298 int __ssam_device_driver_register(struct ssam_device_driver *d, struct module *o);
299 void ssam_device_driver_unregister(struct ssam_device_driver *d);
302 * ssam_device_driver_register() - Register a SSAM client device driver.
303 * @drv: The driver to register.
305 #define ssam_device_driver_register(drv) \
306 __ssam_device_driver_register(drv, THIS_MODULE)
309 * module_ssam_device_driver() - Helper macro for SSAM device driver
311 * @drv: The driver managed by this module.
313 * Helper macro to register a SSAM device driver via module_init() and
314 * module_exit(). This macro may only be used once per module and replaces the
315 * aforementioned definitions.
317 #define module_ssam_device_driver(drv) \
318 module_driver(drv, ssam_device_driver_register, \
319 ssam_device_driver_unregister)
322 /* -- Helpers for client-device requests. ----------------------------------- */
325 * SSAM_DEFINE_SYNC_REQUEST_CL_N() - Define synchronous client-device SAM
326 * request function with neither argument nor return value.
327 * @name: Name of the generated function.
328 * @spec: Specification (&struct ssam_request_spec_md) defining the request.
330 * Defines a function executing the synchronous SAM request specified by
331 * @spec, with the request having neither argument nor return value. Device
332 * specifying parameters are not hard-coded, but instead are provided via the
333 * client device, specifically its UID, supplied when calling this function.
334 * The generated function takes care of setting up the request struct, buffer
335 * allocation, as well as execution of the request itself, returning once the
336 * request has been fully completed. The required transport buffer will be
337 * allocated on the stack.
339 * The generated function is defined as ``int name(struct ssam_device *sdev)``,
340 * returning the status of the request, which is zero on success and negative
341 * on failure. The ``sdev`` parameter specifies both the target device of the
342 * request and by association the controller via which the request is sent.
344 * Refer to ssam_request_sync_onstack() for more details on the behavior of
345 * the generated function.
347 #define SSAM_DEFINE_SYNC_REQUEST_CL_N(name, spec...) \
348 SSAM_DEFINE_SYNC_REQUEST_MD_N(__raw_##name, spec) \
349 int name(struct ssam_device *sdev) \
351 return __raw_##name(sdev->ctrl, sdev->uid.target, \
352 sdev->uid.instance); \
356 * SSAM_DEFINE_SYNC_REQUEST_CL_W() - Define synchronous client-device SAM
357 * request function with argument.
358 * @name: Name of the generated function.
359 * @atype: Type of the request's argument.
360 * @spec: Specification (&struct ssam_request_spec_md) defining the request.
362 * Defines a function executing the synchronous SAM request specified by
363 * @spec, with the request taking an argument of type @atype and having no
364 * return value. Device specifying parameters are not hard-coded, but instead
365 * are provided via the client device, specifically its UID, supplied when
366 * calling this function. The generated function takes care of setting up the
367 * request struct, buffer allocation, as well as execution of the request
368 * itself, returning once the request has been fully completed. The required
369 * transport buffer will be allocated on the stack.
371 * The generated function is defined as ``int name(struct ssam_device *sdev,
372 * const atype *arg)``, returning the status of the request, which is zero on
373 * success and negative on failure. The ``sdev`` parameter specifies both the
374 * target device of the request and by association the controller via which
375 * the request is sent. The request's argument is specified via the ``arg``
378 * Refer to ssam_request_sync_onstack() for more details on the behavior of
379 * the generated function.
381 #define SSAM_DEFINE_SYNC_REQUEST_CL_W(name, atype, spec...) \
382 SSAM_DEFINE_SYNC_REQUEST_MD_W(__raw_##name, atype, spec) \
383 int name(struct ssam_device *sdev, const atype *arg) \
385 return __raw_##name(sdev->ctrl, sdev->uid.target, \
386 sdev->uid.instance, arg); \
390 * SSAM_DEFINE_SYNC_REQUEST_CL_R() - Define synchronous client-device SAM
391 * request function with return value.
392 * @name: Name of the generated function.
393 * @rtype: Type of the request's return value.
394 * @spec: Specification (&struct ssam_request_spec_md) defining the request.
396 * Defines a function executing the synchronous SAM request specified by
397 * @spec, with the request taking no argument but having a return value of
398 * type @rtype. Device specifying parameters are not hard-coded, but instead
399 * are provided via the client device, specifically its UID, supplied when
400 * calling this function. The generated function takes care of setting up the
401 * request struct, buffer allocation, as well as execution of the request
402 * itself, returning once the request has been fully completed. The required
403 * transport buffer will be allocated on the stack.
405 * The generated function is defined as ``int name(struct ssam_device *sdev,
406 * rtype *ret)``, returning the status of the request, which is zero on
407 * success and negative on failure. The ``sdev`` parameter specifies both the
408 * target device of the request and by association the controller via which
409 * the request is sent. The request's return value is written to the memory
410 * pointed to by the ``ret`` parameter.
412 * Refer to ssam_request_sync_onstack() for more details on the behavior of
413 * the generated function.
415 #define SSAM_DEFINE_SYNC_REQUEST_CL_R(name, rtype, spec...) \
416 SSAM_DEFINE_SYNC_REQUEST_MD_R(__raw_##name, rtype, spec) \
417 int name(struct ssam_device *sdev, rtype *ret) \
419 return __raw_##name(sdev->ctrl, sdev->uid.target, \
420 sdev->uid.instance, ret); \
423 #endif /* _LINUX_SURFACE_AGGREGATOR_DEVICE_H */