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-2020 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 = ((tid) != SSAM_ANY_TID) ? (tid) : 0, \ 102 .instance = ((iid) != SSAM_ANY_IID) ? (iid) : 0, \ 103 .function = ((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 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