Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0+ |
| 2 | /* |
| 3 | * Surface System Aggregator Module (SSAM) client device registry. |
| 4 | * |
| 5 | * Registry for non-platform/non-ACPI SSAM client devices, i.e. devices that |
| 6 | * cannot be auto-detected. Provides device-hubs and performs instantiation |
| 7 | * for these devices. |
| 8 | * |
Maximilian Luz | 221756e | 2022-06-24 22:58:00 +0200 | [diff] [blame] | 9 | * Copyright (C) 2020-2022 Maximilian Luz <luzmaximilian@gmail.com> |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 10 | */ |
| 11 | |
| 12 | #include <linux/acpi.h> |
| 13 | #include <linux/kernel.h> |
| 14 | #include <linux/module.h> |
| 15 | #include <linux/platform_device.h> |
| 16 | #include <linux/property.h> |
Maximilian Luz | 797e785 | 2021-02-12 12:54:35 +0100 | [diff] [blame] | 17 | #include <linux/types.h> |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 18 | |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 19 | #include <linux/surface_aggregator/device.h> |
| 20 | |
| 21 | |
| 22 | /* -- Device registry. ------------------------------------------------------ */ |
| 23 | |
| 24 | /* |
| 25 | * SSAM device names follow the SSAM module alias, meaning they are prefixed |
| 26 | * with 'ssam:', followed by domain, category, target ID, instance ID, and |
| 27 | * function, each encoded as two-digit hexadecimal, separated by ':'. In other |
| 28 | * words, it follows the scheme |
| 29 | * |
| 30 | * ssam:dd:cc:tt:ii:ff |
| 31 | * |
| 32 | * Where, 'dd', 'cc', 'tt', 'ii', and 'ff' are the two-digit hexadecimal |
| 33 | * values mentioned above, respectively. |
| 34 | */ |
| 35 | |
| 36 | /* Root node. */ |
| 37 | static const struct software_node ssam_node_root = { |
| 38 | .name = "ssam_platform_hub", |
| 39 | }; |
| 40 | |
Maximilian Luz | 7518eef | 2022-05-27 04:34:47 +0200 | [diff] [blame] | 41 | /* KIP device hub (connects keyboard cover devices on Surface Pro 8). */ |
| 42 | static const struct software_node ssam_node_hub_kip = { |
| 43 | .name = "ssam:00:00:01:0e:00", |
| 44 | .parent = &ssam_node_root, |
| 45 | }; |
| 46 | |
Maximilian Luz | 797e785 | 2021-02-12 12:54:35 +0100 | [diff] [blame] | 47 | /* Base device hub (devices attached to Surface Book 3 base). */ |
| 48 | static const struct software_node ssam_node_hub_base = { |
Maximilian Luz | 58a4d88 | 2022-05-27 04:34:45 +0200 | [diff] [blame] | 49 | .name = "ssam:00:00:02:11:00", |
Maximilian Luz | 797e785 | 2021-02-12 12:54:35 +0100 | [diff] [blame] | 50 | .parent = &ssam_node_root, |
| 51 | }; |
| 52 | |
Maximilian Luz | 1759092 | 2021-02-12 12:54:36 +0100 | [diff] [blame] | 53 | /* AC adapter. */ |
| 54 | static const struct software_node ssam_node_bat_ac = { |
| 55 | .name = "ssam:01:02:01:01:01", |
| 56 | .parent = &ssam_node_root, |
| 57 | }; |
| 58 | |
| 59 | /* Primary battery. */ |
| 60 | static const struct software_node ssam_node_bat_main = { |
| 61 | .name = "ssam:01:02:01:01:00", |
| 62 | .parent = &ssam_node_root, |
| 63 | }; |
| 64 | |
| 65 | /* Secondary battery (Surface Book 3). */ |
| 66 | static const struct software_node ssam_node_bat_sb3base = { |
| 67 | .name = "ssam:01:02:02:01:00", |
| 68 | .parent = &ssam_node_hub_base, |
| 69 | }; |
| 70 | |
Maximilian Luz | 7b5ee8d | 2021-02-12 12:54:37 +0100 | [diff] [blame] | 71 | /* Platform profile / performance-mode device. */ |
| 72 | static const struct software_node ssam_node_tmp_pprof = { |
| 73 | .name = "ssam:01:03:01:00:01", |
| 74 | .parent = &ssam_node_root, |
| 75 | }; |
| 76 | |
Maximilian Luz | f9eb5c4 | 2022-06-24 20:36:41 +0200 | [diff] [blame] | 77 | /* Tablet-mode switch via KIP subsystem. */ |
| 78 | static const struct software_node ssam_node_kip_tablet_switch = { |
| 79 | .name = "ssam:01:0e:01:00:01", |
| 80 | .parent = &ssam_node_root, |
| 81 | }; |
| 82 | |
Maximilian Luz | f68aaf8 | 2021-02-12 12:54:38 +0100 | [diff] [blame] | 83 | /* DTX / detachment-system device (Surface Book 3). */ |
| 84 | static const struct software_node ssam_node_bas_dtx = { |
| 85 | .name = "ssam:01:11:01:00:00", |
| 86 | .parent = &ssam_node_root, |
| 87 | }; |
| 88 | |
Maximilian Luz | 0696455 | 2022-08-10 16:41:16 +0200 | [diff] [blame] | 89 | /* HID keyboard (SAM, TID=1). */ |
| 90 | static const struct software_node ssam_node_hid_sam_keyboard = { |
Maximilian Luz | 4f042e4 | 2021-10-21 15:09:02 +0200 | [diff] [blame] | 91 | .name = "ssam:01:15:01:01:00", |
| 92 | .parent = &ssam_node_root, |
| 93 | }; |
| 94 | |
Maximilian Luz | 0696455 | 2022-08-10 16:41:16 +0200 | [diff] [blame] | 95 | /* HID pen stash (SAM, TID=1; pen taken / stashed away evens). */ |
| 96 | static const struct software_node ssam_node_hid_sam_penstash = { |
Maximilian Luz | 4f042e4 | 2021-10-21 15:09:02 +0200 | [diff] [blame] | 97 | .name = "ssam:01:15:01:02:00", |
| 98 | .parent = &ssam_node_root, |
| 99 | }; |
| 100 | |
Maximilian Luz | 0696455 | 2022-08-10 16:41:16 +0200 | [diff] [blame] | 101 | /* HID touchpad (SAM, TID=1). */ |
| 102 | static const struct software_node ssam_node_hid_sam_touchpad = { |
Maximilian Luz | 4f042e4 | 2021-10-21 15:09:02 +0200 | [diff] [blame] | 103 | .name = "ssam:01:15:01:03:00", |
| 104 | .parent = &ssam_node_root, |
| 105 | }; |
| 106 | |
Maximilian Luz | 0696455 | 2022-08-10 16:41:16 +0200 | [diff] [blame] | 107 | /* HID device instance 6 (SAM, TID=1, HID sensor collection). */ |
| 108 | static const struct software_node ssam_node_hid_sam_sensors = { |
Maximilian Luz | 4f042e4 | 2021-10-21 15:09:02 +0200 | [diff] [blame] | 109 | .name = "ssam:01:15:01:06:00", |
| 110 | .parent = &ssam_node_root, |
| 111 | }; |
| 112 | |
Maximilian Luz | 0696455 | 2022-08-10 16:41:16 +0200 | [diff] [blame] | 113 | /* HID device instance 7 (SAM, TID=1, UCM UCSI HID client). */ |
| 114 | static const struct software_node ssam_node_hid_sam_ucm_ucsi = { |
Maximilian Luz | 4f042e4 | 2021-10-21 15:09:02 +0200 | [diff] [blame] | 115 | .name = "ssam:01:15:01:07:00", |
| 116 | .parent = &ssam_node_root, |
| 117 | }; |
| 118 | |
Maximilian Luz | 0696455 | 2022-08-10 16:41:16 +0200 | [diff] [blame] | 119 | /* HID system controls (SAM, TID=1). */ |
| 120 | static const struct software_node ssam_node_hid_sam_sysctrl = { |
Maximilian Luz | 4f042e4 | 2021-10-21 15:09:02 +0200 | [diff] [blame] | 121 | .name = "ssam:01:15:01:08:00", |
| 122 | .parent = &ssam_node_root, |
| 123 | }; |
| 124 | |
Maximilian Luz | aebf0a1 | 2021-02-12 12:54:39 +0100 | [diff] [blame] | 125 | /* HID keyboard. */ |
| 126 | static const struct software_node ssam_node_hid_main_keyboard = { |
| 127 | .name = "ssam:01:15:02:01:00", |
| 128 | .parent = &ssam_node_root, |
| 129 | }; |
| 130 | |
| 131 | /* HID touchpad. */ |
| 132 | static const struct software_node ssam_node_hid_main_touchpad = { |
| 133 | .name = "ssam:01:15:02:03:00", |
| 134 | .parent = &ssam_node_root, |
| 135 | }; |
| 136 | |
| 137 | /* HID device instance 5 (unknown HID device). */ |
| 138 | static const struct software_node ssam_node_hid_main_iid5 = { |
| 139 | .name = "ssam:01:15:02:05:00", |
| 140 | .parent = &ssam_node_root, |
| 141 | }; |
| 142 | |
| 143 | /* HID keyboard (base hub). */ |
| 144 | static const struct software_node ssam_node_hid_base_keyboard = { |
| 145 | .name = "ssam:01:15:02:01:00", |
| 146 | .parent = &ssam_node_hub_base, |
| 147 | }; |
| 148 | |
| 149 | /* HID touchpad (base hub). */ |
| 150 | static const struct software_node ssam_node_hid_base_touchpad = { |
| 151 | .name = "ssam:01:15:02:03:00", |
| 152 | .parent = &ssam_node_hub_base, |
| 153 | }; |
| 154 | |
| 155 | /* HID device instance 5 (unknown HID device, base hub). */ |
| 156 | static const struct software_node ssam_node_hid_base_iid5 = { |
| 157 | .name = "ssam:01:15:02:05:00", |
| 158 | .parent = &ssam_node_hub_base, |
| 159 | }; |
| 160 | |
| 161 | /* HID device instance 6 (unknown HID device, base hub). */ |
| 162 | static const struct software_node ssam_node_hid_base_iid6 = { |
| 163 | .name = "ssam:01:15:02:06:00", |
| 164 | .parent = &ssam_node_hub_base, |
| 165 | }; |
| 166 | |
Maximilian Luz | 7518eef | 2022-05-27 04:34:47 +0200 | [diff] [blame] | 167 | /* HID keyboard (KIP hub). */ |
| 168 | static const struct software_node ssam_node_hid_kip_keyboard = { |
| 169 | .name = "ssam:01:15:02:01:00", |
| 170 | .parent = &ssam_node_hub_kip, |
| 171 | }; |
| 172 | |
| 173 | /* HID pen stash (KIP hub; pen taken / stashed away evens). */ |
| 174 | static const struct software_node ssam_node_hid_kip_penstash = { |
| 175 | .name = "ssam:01:15:02:02:00", |
| 176 | .parent = &ssam_node_hub_kip, |
| 177 | }; |
| 178 | |
| 179 | /* HID touchpad (KIP hub). */ |
| 180 | static const struct software_node ssam_node_hid_kip_touchpad = { |
| 181 | .name = "ssam:01:15:02:03:00", |
| 182 | .parent = &ssam_node_hub_kip, |
| 183 | }; |
| 184 | |
Maximilian Luz | 6d6ea95 | 2022-08-10 16:41:15 +0200 | [diff] [blame] | 185 | /* HID device instance 5 (KIP hub, type-cover firmware update). */ |
| 186 | static const struct software_node ssam_node_hid_kip_fwupd = { |
Maximilian Luz | 7518eef | 2022-05-27 04:34:47 +0200 | [diff] [blame] | 187 | .name = "ssam:01:15:02:05:00", |
| 188 | .parent = &ssam_node_hub_kip, |
| 189 | }; |
| 190 | |
Maximilian Luz | 70e85eb | 2022-06-24 20:36:42 +0200 | [diff] [blame] | 191 | /* Tablet-mode switch via POS subsystem. */ |
| 192 | static const struct software_node ssam_node_pos_tablet_switch = { |
| 193 | .name = "ssam:01:26:01:00:01", |
| 194 | .parent = &ssam_node_root, |
| 195 | }; |
| 196 | |
Maximilian Luz | b6c3c6f | 2021-05-23 15:45:28 +0200 | [diff] [blame] | 197 | /* |
| 198 | * Devices for 5th- and 6th-generations models: |
| 199 | * - Surface Book 2, |
| 200 | * - Surface Laptop 1 and 2, |
| 201 | * - Surface Pro 5 and 6. |
| 202 | */ |
| 203 | static const struct software_node *ssam_node_group_gen5[] = { |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 204 | &ssam_node_root, |
Maximilian Luz | 7b5ee8d | 2021-02-12 12:54:37 +0100 | [diff] [blame] | 205 | &ssam_node_tmp_pprof, |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 206 | NULL, |
| 207 | }; |
| 208 | |
| 209 | /* Devices for Surface Book 3. */ |
| 210 | static const struct software_node *ssam_node_group_sb3[] = { |
| 211 | &ssam_node_root, |
Maximilian Luz | 797e785 | 2021-02-12 12:54:35 +0100 | [diff] [blame] | 212 | &ssam_node_hub_base, |
Maximilian Luz | 1759092 | 2021-02-12 12:54:36 +0100 | [diff] [blame] | 213 | &ssam_node_bat_ac, |
| 214 | &ssam_node_bat_main, |
| 215 | &ssam_node_bat_sb3base, |
Maximilian Luz | 7b5ee8d | 2021-02-12 12:54:37 +0100 | [diff] [blame] | 216 | &ssam_node_tmp_pprof, |
Maximilian Luz | f68aaf8 | 2021-02-12 12:54:38 +0100 | [diff] [blame] | 217 | &ssam_node_bas_dtx, |
Maximilian Luz | aebf0a1 | 2021-02-12 12:54:39 +0100 | [diff] [blame] | 218 | &ssam_node_hid_base_keyboard, |
| 219 | &ssam_node_hid_base_touchpad, |
| 220 | &ssam_node_hid_base_iid5, |
| 221 | &ssam_node_hid_base_iid6, |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 222 | NULL, |
| 223 | }; |
| 224 | |
Maximilian Luz | e978858 | 2021-05-23 15:45:26 +0200 | [diff] [blame] | 225 | /* Devices for Surface Laptop 3 and 4. */ |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 226 | static const struct software_node *ssam_node_group_sl3[] = { |
| 227 | &ssam_node_root, |
Maximilian Luz | 1759092 | 2021-02-12 12:54:36 +0100 | [diff] [blame] | 228 | &ssam_node_bat_ac, |
| 229 | &ssam_node_bat_main, |
Maximilian Luz | 7b5ee8d | 2021-02-12 12:54:37 +0100 | [diff] [blame] | 230 | &ssam_node_tmp_pprof, |
Maximilian Luz | aebf0a1 | 2021-02-12 12:54:39 +0100 | [diff] [blame] | 231 | &ssam_node_hid_main_keyboard, |
| 232 | &ssam_node_hid_main_touchpad, |
| 233 | &ssam_node_hid_main_iid5, |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 234 | NULL, |
| 235 | }; |
| 236 | |
Maximilian Luz | 4f042e4 | 2021-10-21 15:09:02 +0200 | [diff] [blame] | 237 | /* Devices for Surface Laptop Studio. */ |
| 238 | static const struct software_node *ssam_node_group_sls[] = { |
| 239 | &ssam_node_root, |
| 240 | &ssam_node_bat_ac, |
| 241 | &ssam_node_bat_main, |
| 242 | &ssam_node_tmp_pprof, |
Maximilian Luz | 70e85eb | 2022-06-24 20:36:42 +0200 | [diff] [blame] | 243 | &ssam_node_pos_tablet_switch, |
Maximilian Luz | 0696455 | 2022-08-10 16:41:16 +0200 | [diff] [blame] | 244 | &ssam_node_hid_sam_keyboard, |
| 245 | &ssam_node_hid_sam_penstash, |
| 246 | &ssam_node_hid_sam_touchpad, |
| 247 | &ssam_node_hid_sam_sensors, |
| 248 | &ssam_node_hid_sam_ucm_ucsi, |
| 249 | &ssam_node_hid_sam_sysctrl, |
Maximilian Luz | 4f042e4 | 2021-10-21 15:09:02 +0200 | [diff] [blame] | 250 | NULL, |
| 251 | }; |
| 252 | |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 253 | /* Devices for Surface Laptop Go. */ |
| 254 | static const struct software_node *ssam_node_group_slg1[] = { |
| 255 | &ssam_node_root, |
Maximilian Luz | 1759092 | 2021-02-12 12:54:36 +0100 | [diff] [blame] | 256 | &ssam_node_bat_ac, |
| 257 | &ssam_node_bat_main, |
Maximilian Luz | 7b5ee8d | 2021-02-12 12:54:37 +0100 | [diff] [blame] | 258 | &ssam_node_tmp_pprof, |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 259 | NULL, |
| 260 | }; |
| 261 | |
Maximilian Luz | fa31342 | 2021-03-09 17:25:50 +0100 | [diff] [blame] | 262 | /* Devices for Surface Pro 7 and Surface Pro 7+. */ |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 263 | static const struct software_node *ssam_node_group_sp7[] = { |
| 264 | &ssam_node_root, |
Maximilian Luz | 1759092 | 2021-02-12 12:54:36 +0100 | [diff] [blame] | 265 | &ssam_node_bat_ac, |
| 266 | &ssam_node_bat_main, |
Maximilian Luz | 7b5ee8d | 2021-02-12 12:54:37 +0100 | [diff] [blame] | 267 | &ssam_node_tmp_pprof, |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 268 | NULL, |
| 269 | }; |
| 270 | |
Maximilian Luz | d076f30 | 2022-11-13 19:59:51 +0100 | [diff] [blame^] | 271 | /* Devices for Surface Pro 8 */ |
Maximilian Luz | 025a2fb | 2021-10-28 03:28:45 +0200 | [diff] [blame] | 272 | static const struct software_node *ssam_node_group_sp8[] = { |
| 273 | &ssam_node_root, |
Maximilian Luz | 7518eef | 2022-05-27 04:34:47 +0200 | [diff] [blame] | 274 | &ssam_node_hub_kip, |
Maximilian Luz | 025a2fb | 2021-10-28 03:28:45 +0200 | [diff] [blame] | 275 | &ssam_node_bat_ac, |
| 276 | &ssam_node_bat_main, |
| 277 | &ssam_node_tmp_pprof, |
Maximilian Luz | f9eb5c4 | 2022-06-24 20:36:41 +0200 | [diff] [blame] | 278 | &ssam_node_kip_tablet_switch, |
Maximilian Luz | 7518eef | 2022-05-27 04:34:47 +0200 | [diff] [blame] | 279 | &ssam_node_hid_kip_keyboard, |
| 280 | &ssam_node_hid_kip_penstash, |
| 281 | &ssam_node_hid_kip_touchpad, |
Maximilian Luz | 6d6ea95 | 2022-08-10 16:41:15 +0200 | [diff] [blame] | 282 | &ssam_node_hid_kip_fwupd, |
Maximilian Luz | 6b2caaa | 2022-08-10 16:41:17 +0200 | [diff] [blame] | 283 | &ssam_node_hid_sam_sensors, |
| 284 | &ssam_node_hid_sam_ucm_ucsi, |
Maximilian Luz | 025a2fb | 2021-10-28 03:28:45 +0200 | [diff] [blame] | 285 | NULL, |
| 286 | }; |
| 287 | |
Maximilian Luz | d076f30 | 2022-11-13 19:59:51 +0100 | [diff] [blame^] | 288 | /* Devices for Surface Pro 9 */ |
| 289 | static const struct software_node *ssam_node_group_sp9[] = { |
| 290 | &ssam_node_root, |
| 291 | &ssam_node_hub_kip, |
| 292 | &ssam_node_bat_ac, |
| 293 | &ssam_node_bat_main, |
| 294 | &ssam_node_tmp_pprof, |
| 295 | /* TODO: Tablet mode switch (via POS subsystem) */ |
| 296 | &ssam_node_hid_kip_keyboard, |
| 297 | &ssam_node_hid_kip_penstash, |
| 298 | &ssam_node_hid_kip_touchpad, |
| 299 | &ssam_node_hid_kip_fwupd, |
| 300 | &ssam_node_hid_sam_sensors, |
| 301 | &ssam_node_hid_sam_ucm_ucsi, |
| 302 | NULL, |
| 303 | }; |
| 304 | |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 305 | |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 306 | /* -- SSAM platform/meta-hub driver. ---------------------------------------- */ |
| 307 | |
| 308 | static const struct acpi_device_id ssam_platform_hub_match[] = { |
| 309 | /* Surface Pro 4, 5, and 6 (OMBR < 0x10) */ |
Maximilian Luz | b6c3c6f | 2021-05-23 15:45:28 +0200 | [diff] [blame] | 310 | { "MSHW0081", (unsigned long)ssam_node_group_gen5 }, |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 311 | |
| 312 | /* Surface Pro 6 (OMBR >= 0x10) */ |
Maximilian Luz | b6c3c6f | 2021-05-23 15:45:28 +0200 | [diff] [blame] | 313 | { "MSHW0111", (unsigned long)ssam_node_group_gen5 }, |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 314 | |
| 315 | /* Surface Pro 7 */ |
| 316 | { "MSHW0116", (unsigned long)ssam_node_group_sp7 }, |
| 317 | |
Maximilian Luz | fa31342 | 2021-03-09 17:25:50 +0100 | [diff] [blame] | 318 | /* Surface Pro 7+ */ |
| 319 | { "MSHW0119", (unsigned long)ssam_node_group_sp7 }, |
| 320 | |
Maximilian Luz | 025a2fb | 2021-10-28 03:28:45 +0200 | [diff] [blame] | 321 | /* Surface Pro 8 */ |
| 322 | { "MSHW0263", (unsigned long)ssam_node_group_sp8 }, |
| 323 | |
Maximilian Luz | d076f30 | 2022-11-13 19:59:51 +0100 | [diff] [blame^] | 324 | /* Surface Pro 9 */ |
| 325 | { "MSHW0343", (unsigned long)ssam_node_group_sp9 }, |
| 326 | |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 327 | /* Surface Book 2 */ |
Maximilian Luz | b6c3c6f | 2021-05-23 15:45:28 +0200 | [diff] [blame] | 328 | { "MSHW0107", (unsigned long)ssam_node_group_gen5 }, |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 329 | |
| 330 | /* Surface Book 3 */ |
| 331 | { "MSHW0117", (unsigned long)ssam_node_group_sb3 }, |
| 332 | |
| 333 | /* Surface Laptop 1 */ |
Maximilian Luz | b6c3c6f | 2021-05-23 15:45:28 +0200 | [diff] [blame] | 334 | { "MSHW0086", (unsigned long)ssam_node_group_gen5 }, |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 335 | |
| 336 | /* Surface Laptop 2 */ |
Maximilian Luz | b6c3c6f | 2021-05-23 15:45:28 +0200 | [diff] [blame] | 337 | { "MSHW0112", (unsigned long)ssam_node_group_gen5 }, |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 338 | |
| 339 | /* Surface Laptop 3 (13", Intel) */ |
| 340 | { "MSHW0114", (unsigned long)ssam_node_group_sl3 }, |
| 341 | |
Maximilian Luz | e978858 | 2021-05-23 15:45:26 +0200 | [diff] [blame] | 342 | /* Surface Laptop 3 (15", AMD) and 4 (15", AMD) */ |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 343 | { "MSHW0110", (unsigned long)ssam_node_group_sl3 }, |
| 344 | |
Maximilian Luz | 460d740 | 2021-05-23 15:45:27 +0200 | [diff] [blame] | 345 | /* Surface Laptop 4 (13", Intel) */ |
| 346 | { "MSHW0250", (unsigned long)ssam_node_group_sl3 }, |
| 347 | |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 348 | /* Surface Laptop Go 1 */ |
| 349 | { "MSHW0118", (unsigned long)ssam_node_group_slg1 }, |
| 350 | |
Maximilian Luz | 84b8e403 | 2022-08-10 16:01:33 +0200 | [diff] [blame] | 351 | /* Surface Laptop Go 2 */ |
| 352 | { "MSHW0290", (unsigned long)ssam_node_group_slg1 }, |
| 353 | |
Maximilian Luz | 4f042e4 | 2021-10-21 15:09:02 +0200 | [diff] [blame] | 354 | /* Surface Laptop Studio */ |
| 355 | { "MSHW0123", (unsigned long)ssam_node_group_sls }, |
| 356 | |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 357 | { }, |
| 358 | }; |
| 359 | MODULE_DEVICE_TABLE(acpi, ssam_platform_hub_match); |
| 360 | |
| 361 | static int ssam_platform_hub_probe(struct platform_device *pdev) |
| 362 | { |
| 363 | const struct software_node **nodes; |
| 364 | struct ssam_controller *ctrl; |
| 365 | struct fwnode_handle *root; |
| 366 | int status; |
| 367 | |
| 368 | nodes = (const struct software_node **)acpi_device_get_match_data(&pdev->dev); |
| 369 | if (!nodes) |
| 370 | return -ENODEV; |
| 371 | |
| 372 | /* |
| 373 | * As we're adding the SSAM client devices as children under this device |
| 374 | * and not the SSAM controller, we need to add a device link to the |
| 375 | * controller to ensure that we remove all of our devices before the |
| 376 | * controller is removed. This also guarantees proper ordering for |
| 377 | * suspend/resume of the devices on this hub. |
| 378 | */ |
| 379 | ctrl = ssam_client_bind(&pdev->dev); |
| 380 | if (IS_ERR(ctrl)) |
| 381 | return PTR_ERR(ctrl) == -ENODEV ? -EPROBE_DEFER : PTR_ERR(ctrl); |
| 382 | |
| 383 | status = software_node_register_node_group(nodes); |
| 384 | if (status) |
| 385 | return status; |
| 386 | |
| 387 | root = software_node_fwnode(&ssam_node_root); |
| 388 | if (!root) { |
| 389 | software_node_unregister_node_group(nodes); |
| 390 | return -ENOENT; |
| 391 | } |
| 392 | |
| 393 | set_secondary_fwnode(&pdev->dev, root); |
| 394 | |
Maximilian Luz | 4a4ab61 | 2022-06-24 22:57:58 +0200 | [diff] [blame] | 395 | status = __ssam_register_clients(&pdev->dev, ctrl, root); |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 396 | if (status) { |
| 397 | set_secondary_fwnode(&pdev->dev, NULL); |
| 398 | software_node_unregister_node_group(nodes); |
| 399 | } |
| 400 | |
| 401 | platform_set_drvdata(pdev, nodes); |
| 402 | return status; |
| 403 | } |
| 404 | |
| 405 | static int ssam_platform_hub_remove(struct platform_device *pdev) |
| 406 | { |
| 407 | const struct software_node **nodes = platform_get_drvdata(pdev); |
| 408 | |
Maximilian Luz | acff7091 | 2021-10-28 02:22:42 +0200 | [diff] [blame] | 409 | ssam_remove_clients(&pdev->dev); |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 410 | set_secondary_fwnode(&pdev->dev, NULL); |
| 411 | software_node_unregister_node_group(nodes); |
| 412 | return 0; |
| 413 | } |
| 414 | |
| 415 | static struct platform_driver ssam_platform_hub_driver = { |
| 416 | .probe = ssam_platform_hub_probe, |
| 417 | .remove = ssam_platform_hub_remove, |
| 418 | .driver = { |
| 419 | .name = "surface_aggregator_platform_hub", |
| 420 | .acpi_match_table = ssam_platform_hub_match, |
| 421 | .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
| 422 | }, |
| 423 | }; |
Maximilian Luz | 993a9e2 | 2022-06-24 22:57:59 +0200 | [diff] [blame] | 424 | module_platform_driver(ssam_platform_hub_driver); |
Maximilian Luz | fc622b3 | 2021-02-12 12:54:34 +0100 | [diff] [blame] | 425 | |
| 426 | MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>"); |
| 427 | MODULE_DESCRIPTION("Device-registry for Surface System Aggregator Module"); |
| 428 | MODULE_LICENSE("GPL"); |