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 */ 30 enum 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 */ 39 enum 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 */ 54 struct 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 */ 157 struct 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 */ 171 struct 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 180 extern struct bus_type ssam_bus_type; 181 extern 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 */ 191 static 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 */ 207 static 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 */ 224 static inline 225 struct ssam_device_driver *to_ssam_device_driver(struct device_driver *d) 226 { 227 return container_of(d, struct ssam_device_driver, driver); 228 } 229 230 const struct ssam_device_id *ssam_device_id_match(const struct ssam_device_id *table, 231 const struct ssam_device_uid uid); 232 233 const struct ssam_device_id *ssam_device_get_match(const struct ssam_device *dev); 234 235 const void *ssam_device_get_match_data(const struct ssam_device *dev); 236 237 struct ssam_device *ssam_device_alloc(struct ssam_controller *ctrl, 238 struct ssam_device_uid uid); 239 240 int ssam_device_add(struct ssam_device *sdev); 241 void 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 */ 255 static 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 */ 270 static 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 */ 283 static 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 */ 293 static inline void ssam_device_set_drvdata(struct ssam_device *sdev, void *data) 294 { 295 dev_set_drvdata(&sdev->dev, data); 296 } 297 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); 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 controller and hub devices. ------------------------------- */ 323 324 #ifdef CONFIG_SURFACE_AGGREGATOR_BUS 325 void ssam_remove_clients(struct device *dev); 326 #else /* CONFIG_SURFACE_AGGREGATOR_BUS */ 327 static inline void ssam_remove_clients(struct device *dev) {} 328 #endif /* CONFIG_SURFACE_AGGREGATOR_BUS */ 329 330 331 /* -- Helpers for client-device requests. ----------------------------------- */ 332 333 /** 334 * SSAM_DEFINE_SYNC_REQUEST_CL_N() - Define synchronous client-device SAM 335 * request function with neither argument nor return value. 336 * @name: Name of the generated function. 337 * @spec: Specification (&struct ssam_request_spec_md) defining the request. 338 * 339 * Defines a function executing the synchronous SAM request specified by 340 * @spec, with the request having neither argument nor return value. Device 341 * specifying parameters are not hard-coded, but instead are provided via the 342 * client device, specifically its UID, supplied when calling this function. 343 * The generated function takes care of setting up the request struct, buffer 344 * allocation, as well as execution of the request itself, returning once the 345 * request has been fully completed. The required transport buffer will be 346 * allocated on the stack. 347 * 348 * The generated function is defined as ``static int name(struct ssam_device 349 * *sdev)``, returning the status of the request, which is zero on success and 350 * negative on failure. The ``sdev`` parameter specifies both the target 351 * device of the request and by association the controller via which the 352 * request is sent. 353 * 354 * Refer to ssam_request_sync_onstack() for more details on the behavior of 355 * the generated function. 356 */ 357 #define SSAM_DEFINE_SYNC_REQUEST_CL_N(name, spec...) \ 358 SSAM_DEFINE_SYNC_REQUEST_MD_N(__raw_##name, spec) \ 359 static int name(struct ssam_device *sdev) \ 360 { \ 361 return __raw_##name(sdev->ctrl, sdev->uid.target, \ 362 sdev->uid.instance); \ 363 } 364 365 /** 366 * SSAM_DEFINE_SYNC_REQUEST_CL_W() - Define synchronous client-device SAM 367 * request function with argument. 368 * @name: Name of the generated function. 369 * @atype: Type of the request's argument. 370 * @spec: Specification (&struct ssam_request_spec_md) defining the request. 371 * 372 * Defines a function executing the synchronous SAM request specified by 373 * @spec, with the request taking an argument of type @atype and having no 374 * return value. Device specifying parameters are not hard-coded, but instead 375 * are provided via the client device, specifically its UID, supplied when 376 * calling this function. The generated function takes care of setting up the 377 * request struct, buffer allocation, as well as execution of the request 378 * itself, returning once the request has been fully completed. The required 379 * transport buffer will be allocated on the stack. 380 * 381 * The generated function is defined as ``static int name(struct ssam_device 382 * *sdev, const atype *arg)``, returning the status of the request, which is 383 * zero on success and negative on failure. The ``sdev`` parameter specifies 384 * both the target device of the request and by association the controller via 385 * which the request is sent. The request's argument is specified via the 386 * ``arg`` pointer. 387 * 388 * Refer to ssam_request_sync_onstack() for more details on the behavior of 389 * the generated function. 390 */ 391 #define SSAM_DEFINE_SYNC_REQUEST_CL_W(name, atype, spec...) \ 392 SSAM_DEFINE_SYNC_REQUEST_MD_W(__raw_##name, atype, spec) \ 393 static int name(struct ssam_device *sdev, const atype *arg) \ 394 { \ 395 return __raw_##name(sdev->ctrl, sdev->uid.target, \ 396 sdev->uid.instance, arg); \ 397 } 398 399 /** 400 * SSAM_DEFINE_SYNC_REQUEST_CL_R() - Define synchronous client-device SAM 401 * request function with return value. 402 * @name: Name of the generated function. 403 * @rtype: Type of the request's return value. 404 * @spec: Specification (&struct ssam_request_spec_md) defining the request. 405 * 406 * Defines a function executing the synchronous SAM request specified by 407 * @spec, with the request taking no argument but having a return value of 408 * type @rtype. Device specifying parameters are not hard-coded, but instead 409 * are provided via the client device, specifically its UID, supplied when 410 * calling this function. The generated function takes care of setting up the 411 * request struct, buffer allocation, as well as execution of the request 412 * itself, returning once the request has been fully completed. The required 413 * transport buffer will be allocated on the stack. 414 * 415 * The generated function is defined as ``static int name(struct ssam_device 416 * *sdev, rtype *ret)``, returning the status of the request, which is zero on 417 * success and negative on failure. The ``sdev`` parameter specifies both the 418 * target device of the request and by association the controller via which 419 * the request is sent. The request's return value is written to the memory 420 * pointed to by the ``ret`` parameter. 421 * 422 * Refer to ssam_request_sync_onstack() for more details on the behavior of 423 * the generated function. 424 */ 425 #define SSAM_DEFINE_SYNC_REQUEST_CL_R(name, rtype, spec...) \ 426 SSAM_DEFINE_SYNC_REQUEST_MD_R(__raw_##name, rtype, spec) \ 427 static int name(struct ssam_device *sdev, rtype *ret) \ 428 { \ 429 return __raw_##name(sdev->ctrl, sdev->uid.target, \ 430 sdev->uid.instance, ret); \ 431 } 432 433 #endif /* _LINUX_SURFACE_AGGREGATOR_DEVICE_H */ 434