linux/include/linux/surface_aggregator/device.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0+ */
   2/*
   3 * Surface System Aggregator Module (SSAM) bus and client-device subsystem.
   4 *
   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
   8 * subsystem.
   9 *
  10 * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  11 */
  12
  13#ifndef _LINUX_SURFACE_AGGREGATOR_DEVICE_H
  14#define _LINUX_SURFACE_AGGREGATOR_DEVICE_H
  15
  16#include <linux/device.h>
  17#include <linux/mod_devicetable.h>
  18#include <linux/types.h>
  19
  20#include <linux/surface_aggregator/controller.h>
  21
  22
  23/* -- Surface System Aggregator Module bus. --------------------------------- */
  24
  25/**
  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.
  29 */
  30enum ssam_device_domain {
  31        SSAM_DOMAIN_VIRTUAL   = 0x00,
  32        SSAM_DOMAIN_SERIALHUB = 0x01,
  33};
  34
  35/**
  36 * enum ssam_virtual_tc - Target categories for the virtual SAM domain.
  37 * @SSAM_VIRTUAL_TC_HUB: Device hub category.
  38 */
  39enum ssam_virtual_tc {
  40        SSAM_VIRTUAL_TC_HUB = 0x00,
  41};
  42
  43/**
  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
  52 *            such functionality.
  53 */
  54struct ssam_device_uid {
  55        u8 domain;
  56        u8 category;
  57        u8 target;
  58        u8 instance;
  59        u8 function;
  60};
  61
  62/*
  63 * Special values for device matching.
  64 *
  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.
  69 */
  70#define SSAM_ANY_TID            0xffff
  71#define SSAM_ANY_IID            0xffff
  72#define SSAM_ANY_FUN            0xffff
  73
  74/**
  75 * SSAM_DEVICE() - Initialize a &struct ssam_device_id with the given
  76 * parameters.
  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.
  82 *
  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
  88 * given parameters.
  89 *
  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
  93 * allowed.
  94 */
  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),     \
  99        .domain   = d,                                                          \
 100        .category = cat,                                                        \
 101        .target   = __builtin_choose_expr((tid) != SSAM_ANY_TID, (tid), 0),     \
 102        .instance = __builtin_choose_expr((iid) != SSAM_ANY_IID, (iid), 0),     \
 103        .function = __builtin_choose_expr((fun) != SSAM_ANY_FUN, (fun), 0)
 104
 105/**
 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.
 112 *
 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.
 119 *
 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
 123 * allowed.
 124 */
 125#define SSAM_VDEV(cat, tid, iid, fun) \
 126        SSAM_DEVICE(SSAM_DOMAIN_VIRTUAL, SSAM_VIRTUAL_TC_##cat, tid, iid, fun)
 127
 128/**
 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.
 135 *
 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.
 142 *
 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
 146 * allowed.
 147 */
 148#define SSAM_SDEV(cat, tid, iid, fun) \
 149        SSAM_DEVICE(SSAM_DOMAIN_SERIALHUB, SSAM_SSH_TC_##cat, tid, iid, fun)
 150
 151/**
 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.
 156 */
 157struct ssam_device {
 158        struct device dev;
 159        struct ssam_controller *ctrl;
 160
 161        struct ssam_device_uid uid;
 162};
 163
 164/**
 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.
 170 */
 171struct ssam_device_driver {
 172        struct device_driver driver;
 173
 174        const struct ssam_device_id *match_table;
 175
 176        int  (*probe)(struct ssam_device *sdev);
 177        void (*remove)(struct ssam_device *sdev);
 178};
 179
 180extern struct bus_type ssam_bus_type;
 181extern const struct device_type ssam_device_type;
 182
 183/**
 184 * is_ssam_device() - Check if the given device is a SSAM client device.
 185 * @d: The device to test the type of.
 186 *
 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
 189 * otherwise.
 190 */
 191static inline bool is_ssam_device(struct device *d)
 192{
 193        return d->type == &ssam_device_type;
 194}
 195
 196/**
 197 * to_ssam_device() - Casts the given device to a SSAM client device.
 198 * @d: The device to cast.
 199 *
 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().
 203 *
 204 * Return: Returns a pointer to the &struct ssam_device wrapping the given
 205 * device @d.
 206 */
 207static inline struct ssam_device *to_ssam_device(struct device *d)
 208{
 209        return container_of(d, struct ssam_device, dev);
 210}
 211
 212/**
 213 * to_ssam_device_driver() - Casts the given device driver to a SSAM client
 214 * device driver.
 215 * @d: The driver to cast.
 216 *
 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.
 220 *
 221 * Return: Returns the pointer to the &struct ssam_device_driver wrapping the
 222 * given device driver @d.
 223 */
 224static inline
 225struct ssam_device_driver *to_ssam_device_driver(struct device_driver *d)
 226{
 227        return container_of(d, struct ssam_device_driver, driver);
 228}
 229
 230const struct ssam_device_id *ssam_device_id_match(const struct ssam_device_id *table,
 231                                                  const struct ssam_device_uid uid);
 232
 233const struct ssam_device_id *ssam_device_get_match(const struct ssam_device *dev);
 234
 235const void *ssam_device_get_match_data(const struct ssam_device *dev);
 236
 237struct ssam_device *ssam_device_alloc(struct ssam_controller *ctrl,
 238                                      struct ssam_device_uid uid);
 239
 240int ssam_device_add(struct ssam_device *sdev);
 241void ssam_device_remove(struct ssam_device *sdev);
 242
 243/**
 244 * ssam_device_get() - Increment reference count of SSAM client device.
 245 * @sdev: The device to increment the reference count of.
 246 *
 247 * Increments the reference count of the given SSAM client device by
 248 * incrementing the reference count of the enclosed &struct device via
 249 * get_device().
 250 *
 251 * See ssam_device_put() for the counter-part of this function.
 252 *
 253 * Return: Returns the device provided as input.
 254 */
 255static inline struct ssam_device *ssam_device_get(struct ssam_device *sdev)
 256{
 257        return sdev ? to_ssam_device(get_device(&sdev->dev)) : NULL;
 258}
 259
 260/**
 261 * ssam_device_put() - Decrement reference count of SSAM client device.
 262 * @sdev: The device to decrement the reference count of.
 263 *
 264 * Decrements the reference count of the given SSAM client device by
 265 * decrementing the reference count of the enclosed &struct device via
 266 * put_device().
 267 *
 268 * See ssam_device_get() for the counter-part of this function.
 269 */
 270static inline void ssam_device_put(struct ssam_device *sdev)
 271{
 272        if (sdev)
 273                put_device(&sdev->dev);
 274}
 275
 276/**
 277 * ssam_device_get_drvdata() - Get driver-data of SSAM client device.
 278 * @sdev: The device to get the driver-data from.
 279 *
 280 * Return: Returns the driver-data of the given device, previously set via
 281 * ssam_device_set_drvdata().
 282 */
 283static inline void *ssam_device_get_drvdata(struct ssam_device *sdev)
 284{
 285        return dev_get_drvdata(&sdev->dev);
 286}
 287
 288/**
 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.
 292 */
 293static inline void ssam_device_set_drvdata(struct ssam_device *sdev, void *data)
 294{
 295        dev_set_drvdata(&sdev->dev, data);
 296}
 297
 298int __ssam_device_driver_register(struct ssam_device_driver *d, struct module *o);
 299void ssam_device_driver_unregister(struct ssam_device_driver *d);
 300
 301/**
 302 * ssam_device_driver_register() - Register a SSAM client device driver.
 303 * @drv: The driver to register.
 304 */
 305#define ssam_device_driver_register(drv) \
 306        __ssam_device_driver_register(drv, THIS_MODULE)
 307
 308/**
 309 * module_ssam_device_driver() - Helper macro for SSAM device driver
 310 * registration.
 311 * @drv: The driver managed by this module.
 312 *
 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.
 316 */
 317#define module_ssam_device_driver(drv)                  \
 318        module_driver(drv, ssam_device_driver_register, \
 319                      ssam_device_driver_unregister)
 320
 321
 322/* -- Helpers for client-device requests. ----------------------------------- */
 323
 324/**
 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.
 329 *
 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.
 338 *
 339 * The generated function is defined as ``static int name(struct ssam_device
 340 * *sdev)``, returning the status of the request, which is zero on success and
 341 * negative on failure. The ``sdev`` parameter specifies both the target
 342 * device of the request and by association the controller via which the
 343 * request is sent.
 344 *
 345 * Refer to ssam_request_sync_onstack() for more details on the behavior of
 346 * the generated function.
 347 */
 348#define SSAM_DEFINE_SYNC_REQUEST_CL_N(name, spec...)                    \
 349        SSAM_DEFINE_SYNC_REQUEST_MD_N(__raw_##name, spec)               \
 350        static int name(struct ssam_device *sdev)                       \
 351        {                                                               \
 352                return __raw_##name(sdev->ctrl, sdev->uid.target,       \
 353                                    sdev->uid.instance);                \
 354        }
 355
 356/**
 357 * SSAM_DEFINE_SYNC_REQUEST_CL_W() - Define synchronous client-device SAM
 358 * request function with argument.
 359 * @name:  Name of the generated function.
 360 * @atype: Type of the request's argument.
 361 * @spec:  Specification (&struct ssam_request_spec_md) defining the request.
 362 *
 363 * Defines a function executing the synchronous SAM request specified by
 364 * @spec, with the request taking an argument of type @atype and having no
 365 * return value. Device specifying parameters are not hard-coded, but instead
 366 * are provided via the client device, specifically its UID, supplied when
 367 * calling this function. The generated function takes care of setting up the
 368 * request struct, buffer allocation, as well as execution of the request
 369 * itself, returning once the request has been fully completed. The required
 370 * transport buffer will be allocated on the stack.
 371 *
 372 * The generated function is defined as ``static int name(struct ssam_device
 373 * *sdev, const atype *arg)``, returning the status of the request, which is
 374 * zero on success and negative on failure. The ``sdev`` parameter specifies
 375 * both the target device of the request and by association the controller via
 376 * which the request is sent. The request's argument is specified via the
 377 * ``arg`` pointer.
 378 *
 379 * Refer to ssam_request_sync_onstack() for more details on the behavior of
 380 * the generated function.
 381 */
 382#define SSAM_DEFINE_SYNC_REQUEST_CL_W(name, atype, spec...)             \
 383        SSAM_DEFINE_SYNC_REQUEST_MD_W(__raw_##name, atype, spec)        \
 384        static int name(struct ssam_device *sdev, const atype *arg)     \
 385        {                                                               \
 386                return __raw_##name(sdev->ctrl, sdev->uid.target,       \
 387                                    sdev->uid.instance, arg);           \
 388        }
 389
 390/**
 391 * SSAM_DEFINE_SYNC_REQUEST_CL_R() - Define synchronous client-device SAM
 392 * request function with return value.
 393 * @name:  Name of the generated function.
 394 * @rtype: Type of the request's return value.
 395 * @spec:  Specification (&struct ssam_request_spec_md) defining the request.
 396 *
 397 * Defines a function executing the synchronous SAM request specified by
 398 * @spec, with the request taking no argument but having a return value of
 399 * type @rtype. Device specifying parameters are not hard-coded, but instead
 400 * are provided via the client device, specifically its UID, supplied when
 401 * calling this function. The generated function takes care of setting up the
 402 * request struct, buffer allocation, as well as execution of the request
 403 * itself, returning once the request has been fully completed. The required
 404 * transport buffer will be allocated on the stack.
 405 *
 406 * The generated function is defined as ``static int name(struct ssam_device
 407 * *sdev, rtype *ret)``, returning the status of the request, which is zero on
 408 * success and negative on failure. The ``sdev`` parameter specifies both the
 409 * target device of the request and by association the controller via which
 410 * the request is sent. The request's return value is written to the memory
 411 * pointed to by the ``ret`` parameter.
 412 *
 413 * Refer to ssam_request_sync_onstack() for more details on the behavior of
 414 * the generated function.
 415 */
 416#define SSAM_DEFINE_SYNC_REQUEST_CL_R(name, rtype, spec...)             \
 417        SSAM_DEFINE_SYNC_REQUEST_MD_R(__raw_##name, rtype, spec)        \
 418        static int name(struct ssam_device *sdev, rtype *ret)           \
 419        {                                                               \
 420                return __raw_##name(sdev->ctrl, sdev->uid.target,       \
 421                                    sdev->uid.instance, ret);           \
 422        }
 423
 424#endif /* _LINUX_SURFACE_AGGREGATOR_DEVICE_H */
 425