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 <[email protected]> 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 #ifdef CONFIG_SURFACE_AGGREGATOR_BUS 181 182 extern struct bus_type ssam_bus_type; 183 extern const struct device_type ssam_device_type; 184 185 /** 186 * is_ssam_device() - Check if the given device is a SSAM client device. 187 * @d: The device to test the type of. 188 * 189 * Return: Returns %true if the specified device is of type &struct 190 * ssam_device, i.e. the device type points to %ssam_device_type, and %false 191 * otherwise. 192 */ 193 static inline bool is_ssam_device(struct device *d) 194 { 195 return d->type == &ssam_device_type; 196 } 197 198 #else /* CONFIG_SURFACE_AGGREGATOR_BUS */ 199 200 static inline bool is_ssam_device(struct device *d) 201 { 202 return false; 203 } 204 205 #endif /* CONFIG_SURFACE_AGGREGATOR_BUS */ 206 207 /** 208 * to_ssam_device() - Casts the given device to a SSAM client device. 209 * @d: The device to cast. 210 * 211 * Casts the given &struct device to a &struct ssam_device. The caller has to 212 * ensure that the given device is actually enclosed in a &struct ssam_device, 213 * e.g. by calling is_ssam_device(). 214 * 215 * Return: Returns a pointer to the &struct ssam_device wrapping the given 216 * device @d. 217 */ 218 static inline struct ssam_device *to_ssam_device(struct device *d) 219 { 220 return container_of(d, struct ssam_device, dev); 221 } 222 223 /** 224 * to_ssam_device_driver() - Casts the given device driver to a SSAM client 225 * device driver. 226 * @d: The driver to cast. 227 * 228 * Casts the given &struct device_driver to a &struct ssam_device_driver. The 229 * caller has to ensure that the given driver is actually enclosed in a 230 * &struct ssam_device_driver. 231 * 232 * Return: Returns the pointer to the &struct ssam_device_driver wrapping the 233 * given device driver @d. 234 */ 235 static inline 236 struct ssam_device_driver *to_ssam_device_driver(struct device_driver *d) 237 { 238 return container_of(d, struct ssam_device_driver, driver); 239 } 240 241 const struct ssam_device_id *ssam_device_id_match(const struct ssam_device_id *table, 242 const struct ssam_device_uid uid); 243 244 const struct ssam_device_id *ssam_device_get_match(const struct ssam_device *dev); 245 246 const void *ssam_device_get_match_data(const struct ssam_device *dev); 247 248 struct ssam_device *ssam_device_alloc(struct ssam_controller *ctrl, 249 struct ssam_device_uid uid); 250 251 int ssam_device_add(struct ssam_device *sdev); 252 void ssam_device_remove(struct ssam_device *sdev); 253 254 /** 255 * ssam_device_get() - Increment reference count of SSAM client device. 256 * @sdev: The device to increment the reference count of. 257 * 258 * Increments the reference count of the given SSAM client device by 259 * incrementing the reference count of the enclosed &struct device via 260 * get_device(). 261 * 262 * See ssam_device_put() for the counter-part of this function. 263 * 264 * Return: Returns the device provided as input. 265 */ 266 static inline struct ssam_device *ssam_device_get(struct ssam_device *sdev) 267 { 268 return sdev ? to_ssam_device(get_device(&sdev->dev)) : NULL; 269 } 270 271 /** 272 * ssam_device_put() - Decrement reference count of SSAM client device. 273 * @sdev: The device to decrement the reference count of. 274 * 275 * Decrements the reference count of the given SSAM client device by 276 * decrementing the reference count of the enclosed &struct device via 277 * put_device(). 278 * 279 * See ssam_device_get() for the counter-part of this function. 280 */ 281 static inline void ssam_device_put(struct ssam_device *sdev) 282 { 283 if (sdev) 284 put_device(&sdev->dev); 285 } 286 287 /** 288 * ssam_device_get_drvdata() - Get driver-data of SSAM client device. 289 * @sdev: The device to get the driver-data from. 290 * 291 * Return: Returns the driver-data of the given device, previously set via 292 * ssam_device_set_drvdata(). 293 */ 294 static inline void *ssam_device_get_drvdata(struct ssam_device *sdev) 295 { 296 return dev_get_drvdata(&sdev->dev); 297 } 298 299 /** 300 * ssam_device_set_drvdata() - Set driver-data of SSAM client device. 301 * @sdev: The device to set the driver-data of. 302 * @data: The data to set the device's driver-data pointer to. 303 */ 304 static inline void ssam_device_set_drvdata(struct ssam_device *sdev, void *data) 305 { 306 dev_set_drvdata(&sdev->dev, data); 307 } 308 309 int __ssam_device_driver_register(struct ssam_device_driver *d, struct module *o); 310 void ssam_device_driver_unregister(struct ssam_device_driver *d); 311 312 /** 313 * ssam_device_driver_register() - Register a SSAM client device driver. 314 * @drv: The driver to register. 315 */ 316 #define ssam_device_driver_register(drv) \ 317 __ssam_device_driver_register(drv, THIS_MODULE) 318 319 /** 320 * module_ssam_device_driver() - Helper macro for SSAM device driver 321 * registration. 322 * @drv: The driver managed by this module. 323 * 324 * Helper macro to register a SSAM device driver via module_init() and 325 * module_exit(). This macro may only be used once per module and replaces the 326 * aforementioned definitions. 327 */ 328 #define module_ssam_device_driver(drv) \ 329 module_driver(drv, ssam_device_driver_register, \ 330 ssam_device_driver_unregister) 331 332 333 /* -- Helpers for controller and hub devices. ------------------------------- */ 334 335 #ifdef CONFIG_SURFACE_AGGREGATOR_BUS 336 void ssam_remove_clients(struct device *dev); 337 #else /* CONFIG_SURFACE_AGGREGATOR_BUS */ 338 static inline void ssam_remove_clients(struct device *dev) {} 339 #endif /* CONFIG_SURFACE_AGGREGATOR_BUS */ 340 341 342 /* -- Helpers for client-device requests. ----------------------------------- */ 343 344 /** 345 * SSAM_DEFINE_SYNC_REQUEST_CL_N() - Define synchronous client-device SAM 346 * request function with neither argument nor return value. 347 * @name: Name of the generated function. 348 * @spec: Specification (&struct ssam_request_spec_md) defining the request. 349 * 350 * Defines a function executing the synchronous SAM request specified by 351 * @spec, with the request having neither argument nor return value. Device 352 * specifying parameters are not hard-coded, but instead are provided via the 353 * client device, specifically its UID, supplied when calling this function. 354 * The generated function takes care of setting up the request struct, buffer 355 * allocation, as well as execution of the request itself, returning once the 356 * request has been fully completed. The required transport buffer will be 357 * allocated on the stack. 358 * 359 * The generated function is defined as ``static int name(struct ssam_device 360 * *sdev)``, returning the status of the request, which is zero on success and 361 * negative on failure. The ``sdev`` parameter specifies both the target 362 * device of the request and by association the controller via which the 363 * request is sent. 364 * 365 * Refer to ssam_request_sync_onstack() for more details on the behavior of 366 * the generated function. 367 */ 368 #define SSAM_DEFINE_SYNC_REQUEST_CL_N(name, spec...) \ 369 SSAM_DEFINE_SYNC_REQUEST_MD_N(__raw_##name, spec) \ 370 static int name(struct ssam_device *sdev) \ 371 { \ 372 return __raw_##name(sdev->ctrl, sdev->uid.target, \ 373 sdev->uid.instance); \ 374 } 375 376 /** 377 * SSAM_DEFINE_SYNC_REQUEST_CL_W() - Define synchronous client-device SAM 378 * request function with argument. 379 * @name: Name of the generated function. 380 * @atype: Type of the request's argument. 381 * @spec: Specification (&struct ssam_request_spec_md) defining the request. 382 * 383 * Defines a function executing the synchronous SAM request specified by 384 * @spec, with the request taking an argument of type @atype and having no 385 * return value. Device specifying parameters are not hard-coded, but instead 386 * are provided via the client device, specifically its UID, supplied when 387 * calling this function. The generated function takes care of setting up the 388 * request struct, buffer allocation, as well as execution of the request 389 * itself, returning once the request has been fully completed. The required 390 * transport buffer will be allocated on the stack. 391 * 392 * The generated function is defined as ``static int name(struct ssam_device 393 * *sdev, const atype *arg)``, returning the status of the request, which is 394 * zero on success and negative on failure. The ``sdev`` parameter specifies 395 * both the target device of the request and by association the controller via 396 * which the request is sent. The request's argument is specified via the 397 * ``arg`` pointer. 398 * 399 * Refer to ssam_request_sync_onstack() for more details on the behavior of 400 * the generated function. 401 */ 402 #define SSAM_DEFINE_SYNC_REQUEST_CL_W(name, atype, spec...) \ 403 SSAM_DEFINE_SYNC_REQUEST_MD_W(__raw_##name, atype, spec) \ 404 static int name(struct ssam_device *sdev, const atype *arg) \ 405 { \ 406 return __raw_##name(sdev->ctrl, sdev->uid.target, \ 407 sdev->uid.instance, arg); \ 408 } 409 410 /** 411 * SSAM_DEFINE_SYNC_REQUEST_CL_R() - Define synchronous client-device SAM 412 * request function with return value. 413 * @name: Name of the generated function. 414 * @rtype: Type of the request's return value. 415 * @spec: Specification (&struct ssam_request_spec_md) defining the request. 416 * 417 * Defines a function executing the synchronous SAM request specified by 418 * @spec, with the request taking no argument but having a return value of 419 * type @rtype. Device specifying parameters are not hard-coded, but instead 420 * are provided via the client device, specifically its UID, supplied when 421 * calling this function. The generated function takes care of setting up the 422 * request struct, buffer allocation, as well as execution of the request 423 * itself, returning once the request has been fully completed. The required 424 * transport buffer will be allocated on the stack. 425 * 426 * The generated function is defined as ``static int name(struct ssam_device 427 * *sdev, rtype *ret)``, returning the status of the request, which is zero on 428 * success and negative on failure. The ``sdev`` parameter specifies both the 429 * target device of the request and by association the controller via which 430 * the request is sent. The request's return value is written to the memory 431 * pointed to by the ``ret`` parameter. 432 * 433 * Refer to ssam_request_sync_onstack() for more details on the behavior of 434 * the generated function. 435 */ 436 #define SSAM_DEFINE_SYNC_REQUEST_CL_R(name, rtype, spec...) \ 437 SSAM_DEFINE_SYNC_REQUEST_MD_R(__raw_##name, rtype, spec) \ 438 static int name(struct ssam_device *sdev, rtype *ret) \ 439 { \ 440 return __raw_##name(sdev->ctrl, sdev->uid.target, \ 441 sdev->uid.instance, ret); \ 442 } 443 444 #endif /* _LINUX_SURFACE_AGGREGATOR_DEVICE_H */ 445