0007-surface-sam.patch 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337
  1. From cebca0467ba24265a1e51432ac35beac33891a6e Mon Sep 17 00:00:00 2001
  2. From: Hans de Goede <hdegoede@redhat.com>
  3. Date: Thu, 9 May 2024 16:15:49 +0200
  4. Subject: [PATCH] serial: Clear UPF_DEAD before calling
  5. tty_port_register_device_attr_serdev()
  6. If a serdev_device_driver is already loaded for a serdev_tty_port when it
  7. gets registered by tty_port_register_device_attr_serdev() then that
  8. driver's probe() method will be called immediately.
  9. The serdev_device_driver's probe() method should then be able to call
  10. serdev_device_open() successfully, but because UPF_DEAD is still dead
  11. serdev_device_open() will fail with -ENXIO in this scenario:
  12. serdev_device_open()
  13. ctrl->ops->open() /* this callback being ttyport_open() */
  14. tty->ops->open() /* this callback being uart_open() */
  15. tty_port_open()
  16. port->ops->activate() /* this callback being uart_port_activate() */
  17. Find bit UPF_DEAD is set in uport->flags and fail with errno -ENXIO.
  18. Fix this be clearing UPF_DEAD before tty_port_register_device_attr_serdev()
  19. note this only moves up the UPD_DEAD clearing a small bit, before:
  20. tty_port_register_device_attr_serdev();
  21. mutex_unlock(&tty_port.mutex);
  22. uart_port.flags &= ~UPF_DEAD;
  23. mutex_unlock(&port_mutex);
  24. after:
  25. uart_port.flags &= ~UPF_DEAD;
  26. tty_port_register_device_attr_serdev();
  27. mutex_unlock(&tty_port.mutex);
  28. mutex_unlock(&port_mutex);
  29. Reported-by: Weifeng Liu <weifeng.liu.z@gmail.com>
  30. Closes: https://lore.kernel.org/platform-driver-x86/20240505130800.2546640-1-weifeng.liu.z@gmail.com/
  31. Tested-by: Weifeng Liu <weifeng.liu.z@gmail.com>
  32. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  33. Link: https://lore.kernel.org/r/20240509141549.63704-1-hdegoede@redhat.com
  34. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  35. Patchset: surface-sam
  36. ---
  37. drivers/tty/serial/serial_core.c | 6 ++++--
  38. 1 file changed, 4 insertions(+), 2 deletions(-)
  39. diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
  40. index c476d884356d..b47a277978a0 100644
  41. --- a/drivers/tty/serial/serial_core.c
  42. +++ b/drivers/tty/serial/serial_core.c
  43. @@ -3211,6 +3211,9 @@ static int serial_core_add_one_port(struct uart_driver *drv, struct uart_port *u
  44. if (uport->attr_group)
  45. uport->tty_groups[1] = uport->attr_group;
  46. + /* Ensure serdev drivers can call serdev_device_open() right away */
  47. + uport->flags &= ~UPF_DEAD;
  48. +
  49. /*
  50. * Register the port whether it's detected or not. This allows
  51. * setserial to be used to alter this port's parameters.
  52. @@ -3221,6 +3224,7 @@ static int serial_core_add_one_port(struct uart_driver *drv, struct uart_port *u
  53. if (!IS_ERR(tty_dev)) {
  54. device_set_wakeup_capable(tty_dev, 1);
  55. } else {
  56. + uport->flags |= UPF_DEAD;
  57. dev_err(uport->dev, "Cannot register tty device on line %d\n",
  58. uport->line);
  59. }
  60. @@ -3426,8 +3430,6 @@ int serial_core_register_port(struct uart_driver *drv, struct uart_port *port)
  61. if (ret)
  62. goto err_unregister_port_dev;
  63. - port->flags &= ~UPF_DEAD;
  64. -
  65. mutex_unlock(&port_mutex);
  66. return 0;
  67. --
  68. 2.45.2
  69. From e453ab926ce00cd87c30f55342031d4f3bf78e53 Mon Sep 17 00:00:00 2001
  70. From: Weifeng Liu <weifeng.liu.z@gmail.com>
  71. Date: Sun, 5 May 2024 21:07:50 +0800
  72. Subject: [PATCH] platform/surface: aggregator: Log critical errors during SAM
  73. probing
  74. Emits messages upon errors during probing of SAM. Hopefully this could
  75. provide useful context to user for the purpose of diagnosis when
  76. something miserable happen.
  77. Reviewed-by: Maximilian Luz <luzmaximilian@gmail.com>
  78. Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
  79. Signed-off-by: Weifeng Liu <weifeng.liu.z@gmail.com>
  80. Link: https://lore.kernel.org/r/20240505130800.2546640-3-weifeng.liu.z@gmail.com
  81. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  82. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  83. Patchset: surface-sam
  84. ---
  85. drivers/platform/surface/aggregator/core.c | 42 ++++++++++++++--------
  86. 1 file changed, 28 insertions(+), 14 deletions(-)
  87. diff --git a/drivers/platform/surface/aggregator/core.c b/drivers/platform/surface/aggregator/core.c
  88. index ba550eaa06fc..797d0645bd77 100644
  89. --- a/drivers/platform/surface/aggregator/core.c
  90. +++ b/drivers/platform/surface/aggregator/core.c
  91. @@ -618,15 +618,17 @@ static const struct acpi_gpio_mapping ssam_acpi_gpios[] = {
  92. static int ssam_serial_hub_probe(struct serdev_device *serdev)
  93. {
  94. - struct acpi_device *ssh = ACPI_COMPANION(&serdev->dev);
  95. + struct device *dev = &serdev->dev;
  96. + struct acpi_device *ssh = ACPI_COMPANION(dev);
  97. struct ssam_controller *ctrl;
  98. acpi_status astatus;
  99. int status;
  100. - if (gpiod_count(&serdev->dev, NULL) < 0)
  101. - return -ENODEV;
  102. + status = gpiod_count(dev, NULL);
  103. + if (status < 0)
  104. + return dev_err_probe(dev, status, "no GPIO found\n");
  105. - status = devm_acpi_dev_add_driver_gpios(&serdev->dev, ssam_acpi_gpios);
  106. + status = devm_acpi_dev_add_driver_gpios(dev, ssam_acpi_gpios);
  107. if (status)
  108. return status;
  109. @@ -637,8 +639,10 @@ static int ssam_serial_hub_probe(struct serdev_device *serdev)
  110. /* Initialize controller. */
  111. status = ssam_controller_init(ctrl, serdev);
  112. - if (status)
  113. + if (status) {
  114. + dev_err_probe(dev, status, "failed to initialize ssam controller\n");
  115. goto err_ctrl_init;
  116. + }
  117. ssam_controller_lock(ctrl);
  118. @@ -646,12 +650,14 @@ static int ssam_serial_hub_probe(struct serdev_device *serdev)
  119. serdev_device_set_drvdata(serdev, ctrl);
  120. serdev_device_set_client_ops(serdev, &ssam_serdev_ops);
  121. status = serdev_device_open(serdev);
  122. - if (status)
  123. + if (status) {
  124. + dev_err_probe(dev, status, "failed to open serdev device\n");
  125. goto err_devopen;
  126. + }
  127. astatus = ssam_serdev_setup_via_acpi(ssh->handle, serdev);
  128. if (ACPI_FAILURE(astatus)) {
  129. - status = -ENXIO;
  130. + status = dev_err_probe(dev, -ENXIO, "failed to setup serdev\n");
  131. goto err_devinit;
  132. }
  133. @@ -667,25 +673,33 @@ static int ssam_serial_hub_probe(struct serdev_device *serdev)
  134. * states.
  135. */
  136. status = ssam_log_firmware_version(ctrl);
  137. - if (status)
  138. + if (status) {
  139. + dev_err_probe(dev, status, "failed to get firmware version\n");
  140. goto err_initrq;
  141. + }
  142. status = ssam_ctrl_notif_d0_entry(ctrl);
  143. - if (status)
  144. + if (status) {
  145. + dev_err_probe(dev, status, "D0-entry notification failed\n");
  146. goto err_initrq;
  147. + }
  148. status = ssam_ctrl_notif_display_on(ctrl);
  149. - if (status)
  150. + if (status) {
  151. + dev_err_probe(dev, status, "display-on notification failed\n");
  152. goto err_initrq;
  153. + }
  154. - status = sysfs_create_group(&serdev->dev.kobj, &ssam_sam_group);
  155. + status = sysfs_create_group(&dev->kobj, &ssam_sam_group);
  156. if (status)
  157. goto err_initrq;
  158. /* Set up IRQ. */
  159. status = ssam_irq_setup(ctrl);
  160. - if (status)
  161. + if (status) {
  162. + dev_err_probe(dev, status, "failed to setup IRQ\n");
  163. goto err_irq;
  164. + }
  165. /* Finally, set main controller reference. */
  166. status = ssam_try_set_controller(ctrl);
  167. @@ -702,7 +716,7 @@ static int ssam_serial_hub_probe(struct serdev_device *serdev)
  168. * resumed. In short, this causes some spurious unwanted wake-ups.
  169. * For now let's thus default power/wakeup to false.
  170. */
  171. - device_set_wakeup_capable(&serdev->dev, true);
  172. + device_set_wakeup_capable(dev, true);
  173. acpi_dev_clear_dependencies(ssh);
  174. return 0;
  175. @@ -710,7 +724,7 @@ static int ssam_serial_hub_probe(struct serdev_device *serdev)
  176. err_mainref:
  177. ssam_irq_free(ctrl);
  178. err_irq:
  179. - sysfs_remove_group(&serdev->dev.kobj, &ssam_sam_group);
  180. + sysfs_remove_group(&dev->kobj, &ssam_sam_group);
  181. err_initrq:
  182. ssam_controller_lock(ctrl);
  183. ssam_controller_shutdown(ctrl);
  184. --
  185. 2.45.2
  186. From d3ddbc07009ade7bd60e9575b4d280e44c8c2f63 Mon Sep 17 00:00:00 2001
  187. From: Maximilian Luz <luzmaximilian@gmail.com>
  188. Date: Fri, 19 Apr 2024 20:41:47 +0200
  189. Subject: [PATCH] platform/surface: aggregator: Fix warning when controller is
  190. destroyed in probe
  191. There is a small window in ssam_serial_hub_probe() where the controller
  192. is initialized but has not been started yet. Specifically, between
  193. ssam_controller_init() and ssam_controller_start(). Any failure in this
  194. window, for example caused by a failure of serdev_device_open(),
  195. currently results in an incorrect warning being emitted.
  196. In particular, any failure in this window results in the controller
  197. being destroyed via ssam_controller_destroy(). This function checks the
  198. state of the controller and, in an attempt to validate that the
  199. controller has been cleanly shut down before we try and deallocate any
  200. resources, emits a warning if that state is not SSAM_CONTROLLER_STOPPED.
  201. However, since we have only just initialized the controller and have not
  202. yet started it, its state is SSAM_CONTROLLER_INITIALIZED. Note that this
  203. is the only point at which the controller has this state, as it will
  204. change after we start the controller with ssam_controller_start() and
  205. never revert back. Further, at this point no communication has taken
  206. place and the sender and receiver threads have not been started yet (and
  207. we may not even have an open serdev device either).
  208. Therefore, it is perfectly safe to call ssam_controller_destroy() with a
  209. state of SSAM_CONTROLLER_INITIALIZED. This, however, means that the
  210. warning currently being emitted is incorrect. Fix it by extending the
  211. check.
  212. Fixes: c167b9c7e3d6 ("platform/surface: Add Surface Aggregator subsystem")
  213. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  214. Patchset: surface-sam
  215. ---
  216. drivers/platform/surface/aggregator/controller.c | 3 ++-
  217. 1 file changed, 2 insertions(+), 1 deletion(-)
  218. diff --git a/drivers/platform/surface/aggregator/controller.c b/drivers/platform/surface/aggregator/controller.c
  219. index 7fc602e01487..7e89f547999b 100644
  220. --- a/drivers/platform/surface/aggregator/controller.c
  221. +++ b/drivers/platform/surface/aggregator/controller.c
  222. @@ -1354,7 +1354,8 @@ void ssam_controller_destroy(struct ssam_controller *ctrl)
  223. if (ctrl->state == SSAM_CONTROLLER_UNINITIALIZED)
  224. return;
  225. - WARN_ON(ctrl->state != SSAM_CONTROLLER_STOPPED);
  226. + WARN_ON(ctrl->state != SSAM_CONTROLLER_STOPPED &&
  227. + ctrl->state != SSAM_CONTROLLER_INITIALIZED);
  228. /*
  229. * Note: New events could still have been received after the previous
  230. --
  231. 2.45.2
  232. From 46aeacf7b116bd6e1711b1678f8c8c9d631e95c9 Mon Sep 17 00:00:00 2001
  233. From: Maximilian Luz <luzmaximilian@gmail.com>
  234. Date: Sun, 22 Oct 2023 14:57:11 +0200
  235. Subject: [PATCH] platform/surface: aggregator_registry: Add support for
  236. Surface Laptop Go 3
  237. Add SAM client device nodes for the Surface Laptop Go 3. It seems to use
  238. the same SAM client devices as the Surface Laptop Go 1 and 2, so re-use
  239. their node group.
  240. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  241. Patchset: surface-sam
  242. ---
  243. drivers/platform/surface/surface_aggregator_registry.c | 3 +++
  244. 1 file changed, 3 insertions(+)
  245. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  246. index 035d6b4105cd..74688a2ed4b2 100644
  247. --- a/drivers/platform/surface/surface_aggregator_registry.c
  248. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  249. @@ -374,6 +374,9 @@ static const struct acpi_device_id ssam_platform_hub_match[] = {
  250. /* Surface Laptop Go 2 */
  251. { "MSHW0290", (unsigned long)ssam_node_group_slg1 },
  252. + /* Surface Laptop Go 3 */
  253. + { "MSHW0440", (unsigned long)ssam_node_group_slg1 },
  254. +
  255. /* Surface Laptop Studio */
  256. { "MSHW0123", (unsigned long)ssam_node_group_sls },
  257. --
  258. 2.45.2
  259. From e42a81ec22305c91f44562c0386f651dfdc48db1 Mon Sep 17 00:00:00 2001
  260. From: Maximilian Luz <luzmaximilian@gmail.com>
  261. Date: Mon, 20 Nov 2023 19:47:00 +0100
  262. Subject: [PATCH] platform/surface: aggregator_registry: Add support for
  263. Surface Laptop Studio 2
  264. Add SAM client device nodes for the Surface Laptop Studio 2 (SLS2). The
  265. SLS2 is quite similar to the SLS1, but it does not provide the touchpad
  266. as a SAM-HID device. Therefore, add a new node group for the SLS2 and
  267. update the comments accordingly
  268. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  269. Patchset: surface-sam
  270. ---
  271. .../surface/surface_aggregator_registry.c | 25 ++++++++++++++++---
  272. 1 file changed, 21 insertions(+), 4 deletions(-)
  273. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  274. index 74688a2ed4b2..f02a933160ff 100644
  275. --- a/drivers/platform/surface/surface_aggregator_registry.c
  276. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  277. @@ -253,8 +253,8 @@ static const struct software_node *ssam_node_group_sl5[] = {
  278. NULL,
  279. };
  280. -/* Devices for Surface Laptop Studio. */
  281. -static const struct software_node *ssam_node_group_sls[] = {
  282. +/* Devices for Surface Laptop Studio 1. */
  283. +static const struct software_node *ssam_node_group_sls1[] = {
  284. &ssam_node_root,
  285. &ssam_node_bat_ac,
  286. &ssam_node_bat_main,
  287. @@ -269,6 +269,20 @@ static const struct software_node *ssam_node_group_sls[] = {
  288. NULL,
  289. };
  290. +/* Devices for Surface Laptop Studio 2. */
  291. +static const struct software_node *ssam_node_group_sls2[] = {
  292. + &ssam_node_root,
  293. + &ssam_node_bat_ac,
  294. + &ssam_node_bat_main,
  295. + &ssam_node_tmp_pprof,
  296. + &ssam_node_pos_tablet_switch,
  297. + &ssam_node_hid_sam_keyboard,
  298. + &ssam_node_hid_sam_penstash,
  299. + &ssam_node_hid_sam_sensors,
  300. + &ssam_node_hid_sam_ucm_ucsi,
  301. + NULL,
  302. +};
  303. +
  304. /* Devices for Surface Laptop Go. */
  305. static const struct software_node *ssam_node_group_slg1[] = {
  306. &ssam_node_root,
  307. @@ -377,8 +391,11 @@ static const struct acpi_device_id ssam_platform_hub_match[] = {
  308. /* Surface Laptop Go 3 */
  309. { "MSHW0440", (unsigned long)ssam_node_group_slg1 },
  310. - /* Surface Laptop Studio */
  311. - { "MSHW0123", (unsigned long)ssam_node_group_sls },
  312. + /* Surface Laptop Studio 1 */
  313. + { "MSHW0123", (unsigned long)ssam_node_group_sls1 },
  314. +
  315. + /* Surface Laptop Studio 2 */
  316. + { "MSHW0360", (unsigned long)ssam_node_group_sls2 },
  317. { },
  318. };
  319. --
  320. 2.45.2
  321. From 779ad78ae568b1bf03927655133b23bdee5fc77c Mon Sep 17 00:00:00 2001
  322. From: Maximilian Luz <luzmaximilian@gmail.com>
  323. Date: Sun, 9 Jun 2024 20:05:57 +0200
  324. Subject: [PATCH] platform/surface: aggregator_registry: Add support for
  325. Surface Laptop 6
  326. Add SAM client device nodes for the Surface Laptop Studio 6 (SL6). The
  327. SL6 is similar to the SL5, with the typical battery/AC, platform
  328. profile, and HID nodes. It also has support for the newly supported fan
  329. interface.
  330. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  331. Patchset: surface-sam
  332. ---
  333. .../surface/surface_aggregator_registry.c | 19 +++++++++++++++++++
  334. 1 file changed, 19 insertions(+)
  335. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  336. index f02a933160ff..34df1bdad83b 100644
  337. --- a/drivers/platform/surface/surface_aggregator_registry.c
  338. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  339. @@ -253,6 +253,22 @@ static const struct software_node *ssam_node_group_sl5[] = {
  340. NULL,
  341. };
  342. +/* Devices for Surface Laptop 6. */
  343. +static const struct software_node *ssam_node_group_sl6[] = {
  344. + &ssam_node_root,
  345. + &ssam_node_bat_ac,
  346. + &ssam_node_bat_main,
  347. + &ssam_node_tmp_perf_profile_with_fan,
  348. + &ssam_node_tmp_sensors,
  349. + &ssam_node_fan_speed,
  350. + &ssam_node_hid_main_keyboard,
  351. + &ssam_node_hid_main_touchpad,
  352. + &ssam_node_hid_main_iid5,
  353. + &ssam_node_hid_sam_sensors,
  354. + &ssam_node_hid_sam_ucm_ucsi,
  355. + NULL,
  356. +};
  357. +
  358. /* Devices for Surface Laptop Studio 1. */
  359. static const struct software_node *ssam_node_group_sls1[] = {
  360. &ssam_node_root,
  361. @@ -382,6 +398,9 @@ static const struct acpi_device_id ssam_platform_hub_match[] = {
  362. /* Surface Laptop 5 */
  363. { "MSHW0350", (unsigned long)ssam_node_group_sl5 },
  364. + /* Surface Laptop 6 */
  365. + { "MSHW0530", (unsigned long)ssam_node_group_sl5 },
  366. +
  367. /* Surface Laptop Go 1 */
  368. { "MSHW0118", (unsigned long)ssam_node_group_slg1 },
  369. --
  370. 2.45.2
  371. From 4a7f3f74a7d92f3e0567f7e876e77bf7c8bbcf6d Mon Sep 17 00:00:00 2001
  372. From: Maximilian Luz <luzmaximilian@gmail.com>
  373. Date: Sat, 30 Dec 2023 18:07:54 +0100
  374. Subject: [PATCH] hwmon: Add thermal sensor driver for Surface Aggregator
  375. Module
  376. Some of the newer Microsoft Surface devices (such as the Surface Book
  377. 3 and Pro 9) have thermal sensors connected via the Surface Aggregator
  378. Module (the embedded controller on those devices). Add a basic driver
  379. to read out the temperature values of those sensors.
  380. Link: https://github.com/linux-surface/surface-aggregator-module/issues/59
  381. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  382. Patchset: surface-sam
  383. ---
  384. drivers/hwmon/Kconfig | 10 +++
  385. drivers/hwmon/Makefile | 1 +
  386. drivers/hwmon/surface_temp.c | 165 +++++++++++++++++++++++++++++++++++
  387. 3 files changed, 176 insertions(+)
  388. create mode 100644 drivers/hwmon/surface_temp.c
  389. diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
  390. index 83945397b6eb..338ef73c96a3 100644
  391. --- a/drivers/hwmon/Kconfig
  392. +++ b/drivers/hwmon/Kconfig
  393. @@ -2070,6 +2070,16 @@ config SENSORS_SURFACE_FAN
  394. Select M or Y here, if you want to be able to read the fan's speed.
  395. +config SENSORS_SURFACE_TEMP
  396. + tristate "Microsoft Surface Thermal Sensor Driver"
  397. + depends on SURFACE_AGGREGATOR
  398. + help
  399. + Driver for monitoring thermal sensors connected via the Surface
  400. + Aggregator Module (embedded controller) on Microsoft Surface devices.
  401. +
  402. + This driver can also be built as a module. If so, the module
  403. + will be called surface_temp.
  404. +
  405. config SENSORS_ADC128D818
  406. tristate "Texas Instruments ADC128D818"
  407. depends on I2C
  408. diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
  409. index 5c31808f6378..de8bc99719e6 100644
  410. --- a/drivers/hwmon/Makefile
  411. +++ b/drivers/hwmon/Makefile
  412. @@ -208,6 +208,7 @@ obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
  413. obj-$(CONFIG_SENSORS_SPARX5) += sparx5-temp.o
  414. obj-$(CONFIG_SENSORS_STTS751) += stts751.o
  415. obj-$(CONFIG_SENSORS_SURFACE_FAN)+= surface_fan.o
  416. +obj-$(CONFIG_SENSORS_SURFACE_TEMP)+= surface_temp.o
  417. obj-$(CONFIG_SENSORS_SY7636A) += sy7636a-hwmon.o
  418. obj-$(CONFIG_SENSORS_AMC6821) += amc6821.o
  419. obj-$(CONFIG_SENSORS_TC74) += tc74.o
  420. diff --git a/drivers/hwmon/surface_temp.c b/drivers/hwmon/surface_temp.c
  421. new file mode 100644
  422. index 000000000000..48c3e826713f
  423. --- /dev/null
  424. +++ b/drivers/hwmon/surface_temp.c
  425. @@ -0,0 +1,165 @@
  426. +// SPDX-License-Identifier: GPL-2.0+
  427. +/*
  428. + * Thermal sensor subsystem driver for Surface System Aggregator Module (SSAM).
  429. + *
  430. + * Copyright (C) 2022-2023 Maximilian Luz <luzmaximilian@gmail.com>
  431. + */
  432. +
  433. +#include <linux/bitops.h>
  434. +#include <linux/hwmon.h>
  435. +#include <linux/kernel.h>
  436. +#include <linux/module.h>
  437. +#include <linux/types.h>
  438. +
  439. +#include <linux/surface_aggregator/controller.h>
  440. +#include <linux/surface_aggregator/device.h>
  441. +
  442. +
  443. +/* -- SAM interface. -------------------------------------------------------- */
  444. +
  445. +SSAM_DEFINE_SYNC_REQUEST_CL_R(__ssam_tmp_get_available_sensors, __le16, {
  446. + .target_category = SSAM_SSH_TC_TMP,
  447. + .command_id = 0x04,
  448. +});
  449. +
  450. +SSAM_DEFINE_SYNC_REQUEST_MD_R(__ssam_tmp_get_temperature, __le16, {
  451. + .target_category = SSAM_SSH_TC_TMP,
  452. + .command_id = 0x01,
  453. +});
  454. +
  455. +static int ssam_tmp_get_available_sensors(struct ssam_device *sdev, s16 *sensors)
  456. +{
  457. + __le16 sensors_le;
  458. + int status;
  459. +
  460. + status = __ssam_tmp_get_available_sensors(sdev, &sensors_le);
  461. + if (status)
  462. + return status;
  463. +
  464. + *sensors = le16_to_cpu(sensors_le);
  465. + return 0;
  466. +}
  467. +
  468. +static int ssam_tmp_get_temperature(struct ssam_device *sdev, u8 iid, long *temperature)
  469. +{
  470. + __le16 temp_le;
  471. + int status;
  472. +
  473. + status = __ssam_tmp_get_temperature(sdev->ctrl, sdev->uid.target, iid, &temp_le);
  474. + if (status)
  475. + return status;
  476. +
  477. + /* Convert 1/10 °K to 1/1000 °C */
  478. + *temperature = (le16_to_cpu(temp_le) - 2731) * 100L;
  479. + return 0;
  480. +}
  481. +
  482. +
  483. +/* -- Driver.---------------------------------------------------------------- */
  484. +
  485. +struct ssam_temp {
  486. + struct ssam_device *sdev;
  487. + s16 sensors;
  488. +};
  489. +
  490. +static umode_t ssam_temp_hwmon_is_visible(const void *data,
  491. + enum hwmon_sensor_types type,
  492. + u32 attr, int channel)
  493. +{
  494. + const struct ssam_temp *ssam_temp = data;
  495. +
  496. + if (!(ssam_temp->sensors & BIT(channel)))
  497. + return 0;
  498. +
  499. + return 0444;
  500. +}
  501. +
  502. +static int ssam_temp_hwmon_read(struct device *dev,
  503. + enum hwmon_sensor_types type,
  504. + u32 attr, int channel, long *value)
  505. +{
  506. + const struct ssam_temp *ssam_temp = dev_get_drvdata(dev);
  507. +
  508. + return ssam_tmp_get_temperature(ssam_temp->sdev, channel + 1, value);
  509. +}
  510. +
  511. +static const struct hwmon_channel_info * const ssam_temp_hwmon_info[] = {
  512. + HWMON_CHANNEL_INFO(chip,
  513. + HWMON_C_REGISTER_TZ),
  514. + /* We have at most 16 thermal sensor channels. */
  515. + HWMON_CHANNEL_INFO(temp,
  516. + HWMON_T_INPUT,
  517. + HWMON_T_INPUT,
  518. + HWMON_T_INPUT,
  519. + HWMON_T_INPUT,
  520. + HWMON_T_INPUT,
  521. + HWMON_T_INPUT,
  522. + HWMON_T_INPUT,
  523. + HWMON_T_INPUT,
  524. + HWMON_T_INPUT,
  525. + HWMON_T_INPUT,
  526. + HWMON_T_INPUT,
  527. + HWMON_T_INPUT,
  528. + HWMON_T_INPUT,
  529. + HWMON_T_INPUT,
  530. + HWMON_T_INPUT,
  531. + HWMON_T_INPUT),
  532. + NULL
  533. +};
  534. +
  535. +static const struct hwmon_ops ssam_temp_hwmon_ops = {
  536. + .is_visible = ssam_temp_hwmon_is_visible,
  537. + .read = ssam_temp_hwmon_read,
  538. +};
  539. +
  540. +static const struct hwmon_chip_info ssam_temp_hwmon_chip_info = {
  541. + .ops = &ssam_temp_hwmon_ops,
  542. + .info = ssam_temp_hwmon_info,
  543. +};
  544. +
  545. +static int ssam_temp_probe(struct ssam_device *sdev)
  546. +{
  547. + struct ssam_temp *ssam_temp;
  548. + struct device *hwmon_dev;
  549. + s16 sensors;
  550. + int status;
  551. +
  552. + status = ssam_tmp_get_available_sensors(sdev, &sensors);
  553. + if (status)
  554. + return status;
  555. +
  556. + ssam_temp = devm_kzalloc(&sdev->dev, sizeof(*ssam_temp), GFP_KERNEL);
  557. + if (!ssam_temp)
  558. + return -ENOMEM;
  559. +
  560. + ssam_temp->sdev = sdev;
  561. + ssam_temp->sensors = sensors;
  562. +
  563. + hwmon_dev = devm_hwmon_device_register_with_info(&sdev->dev,
  564. + "surface_thermal", ssam_temp, &ssam_temp_hwmon_chip_info,
  565. + NULL);
  566. + if (IS_ERR(hwmon_dev))
  567. + return PTR_ERR(hwmon_dev);
  568. +
  569. + return 0;
  570. +}
  571. +
  572. +static const struct ssam_device_id ssam_temp_match[] = {
  573. + { SSAM_SDEV(TMP, SAM, 0x00, 0x02) },
  574. + { },
  575. +};
  576. +MODULE_DEVICE_TABLE(ssam, ssam_temp_match);
  577. +
  578. +static struct ssam_device_driver ssam_temp = {
  579. + .probe = ssam_temp_probe,
  580. + .match_table = ssam_temp_match,
  581. + .driver = {
  582. + .name = "surface_temp",
  583. + .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  584. + },
  585. +};
  586. +module_ssam_device_driver(ssam_temp);
  587. +
  588. +MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
  589. +MODULE_DESCRIPTION("Thermal sensor subsystem driver for Surface System Aggregator Module");
  590. +MODULE_LICENSE("GPL");
  591. --
  592. 2.45.2
  593. From 98e9eaae15a93f4dbe3898d3c188e710b791528a Mon Sep 17 00:00:00 2001
  594. From: Maximilian Luz <luzmaximilian@gmail.com>
  595. Date: Sat, 30 Dec 2023 18:12:23 +0100
  596. Subject: [PATCH] hwmon: surface_temp: Add support for sensor names
  597. The thermal subsystem of the Surface Aggregator Module allows us to
  598. query the names of the respective thermal sensors. Forward those to
  599. userspace.
  600. Signed-off-by: Ivor Wanders <ivor@iwanders.net>
  601. Co-Developed-by: Maximilian Luz <luzmaximilian@gmail.com>
  602. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  603. Patchset: surface-sam
  604. ---
  605. drivers/hwmon/surface_temp.c | 113 +++++++++++++++++++++++++++++------
  606. 1 file changed, 96 insertions(+), 17 deletions(-)
  607. diff --git a/drivers/hwmon/surface_temp.c b/drivers/hwmon/surface_temp.c
  608. index 48c3e826713f..4c08926139db 100644
  609. --- a/drivers/hwmon/surface_temp.c
  610. +++ b/drivers/hwmon/surface_temp.c
  611. @@ -17,6 +17,27 @@
  612. /* -- SAM interface. -------------------------------------------------------- */
  613. +/*
  614. + * Available sensors are indicated by a 16-bit bitfield, where a 1 marks the
  615. + * presence of a sensor. So we have at most 16 possible sensors/channels.
  616. + */
  617. +#define SSAM_TMP_SENSOR_MAX_COUNT 16
  618. +
  619. +/*
  620. + * All names observed so far are 6 characters long, but there's only
  621. + * zeros after the name, so perhaps they can be longer. This number reflects
  622. + * the maximum zero-padded space observed in the returned buffer.
  623. + */
  624. +#define SSAM_TMP_SENSOR_NAME_LENGTH 18
  625. +
  626. +struct ssam_tmp_get_name_rsp {
  627. + __le16 unknown1;
  628. + char unknown2;
  629. + char name[SSAM_TMP_SENSOR_NAME_LENGTH];
  630. +} __packed;
  631. +
  632. +static_assert(sizeof(struct ssam_tmp_get_name_rsp) == 21);
  633. +
  634. SSAM_DEFINE_SYNC_REQUEST_CL_R(__ssam_tmp_get_available_sensors, __le16, {
  635. .target_category = SSAM_SSH_TC_TMP,
  636. .command_id = 0x04,
  637. @@ -27,6 +48,11 @@ SSAM_DEFINE_SYNC_REQUEST_MD_R(__ssam_tmp_get_temperature, __le16, {
  638. .command_id = 0x01,
  639. });
  640. +SSAM_DEFINE_SYNC_REQUEST_MD_R(__ssam_tmp_get_name, struct ssam_tmp_get_name_rsp, {
  641. + .target_category = SSAM_SSH_TC_TMP,
  642. + .command_id = 0x0e,
  643. +});
  644. +
  645. static int ssam_tmp_get_available_sensors(struct ssam_device *sdev, s16 *sensors)
  646. {
  647. __le16 sensors_le;
  648. @@ -54,12 +80,37 @@ static int ssam_tmp_get_temperature(struct ssam_device *sdev, u8 iid, long *temp
  649. return 0;
  650. }
  651. +static int ssam_tmp_get_name(struct ssam_device *sdev, u8 iid, char *buf, size_t buf_len)
  652. +{
  653. + struct ssam_tmp_get_name_rsp name_rsp;
  654. + int status;
  655. +
  656. + status = __ssam_tmp_get_name(sdev->ctrl, sdev->uid.target, iid, &name_rsp);
  657. + if (status)
  658. + return status;
  659. +
  660. + /*
  661. + * This should not fail unless the name in the returned struct is not
  662. + * null-terminated or someone changed something in the struct
  663. + * definitions above, since our buffer and struct have the same
  664. + * capacity by design. So if this fails blow this up with a warning.
  665. + * Since the more likely cause is that the returned string isn't
  666. + * null-terminated, we might have received garbage (as opposed to just
  667. + * an incomplete string), so also fail the function.
  668. + */
  669. + status = strscpy(buf, name_rsp.name, buf_len);
  670. + WARN_ON(status < 0);
  671. +
  672. + return status < 0 ? status : 0;
  673. +}
  674. +
  675. /* -- Driver.---------------------------------------------------------------- */
  676. struct ssam_temp {
  677. struct ssam_device *sdev;
  678. s16 sensors;
  679. + char names[SSAM_TMP_SENSOR_MAX_COUNT][SSAM_TMP_SENSOR_NAME_LENGTH];
  680. };
  681. static umode_t ssam_temp_hwmon_is_visible(const void *data,
  682. @@ -83,33 +134,47 @@ static int ssam_temp_hwmon_read(struct device *dev,
  683. return ssam_tmp_get_temperature(ssam_temp->sdev, channel + 1, value);
  684. }
  685. +static int ssam_temp_hwmon_read_string(struct device *dev,
  686. + enum hwmon_sensor_types type,
  687. + u32 attr, int channel, const char **str)
  688. +{
  689. + const struct ssam_temp *ssam_temp = dev_get_drvdata(dev);
  690. +
  691. + *str = ssam_temp->names[channel];
  692. + return 0;
  693. +}
  694. +
  695. static const struct hwmon_channel_info * const ssam_temp_hwmon_info[] = {
  696. HWMON_CHANNEL_INFO(chip,
  697. HWMON_C_REGISTER_TZ),
  698. - /* We have at most 16 thermal sensor channels. */
  699. + /*
  700. + * We have at most SSAM_TMP_SENSOR_MAX_COUNT = 16 thermal sensor
  701. + * channels.
  702. + */
  703. HWMON_CHANNEL_INFO(temp,
  704. - HWMON_T_INPUT,
  705. - HWMON_T_INPUT,
  706. - HWMON_T_INPUT,
  707. - HWMON_T_INPUT,
  708. - HWMON_T_INPUT,
  709. - HWMON_T_INPUT,
  710. - HWMON_T_INPUT,
  711. - HWMON_T_INPUT,
  712. - HWMON_T_INPUT,
  713. - HWMON_T_INPUT,
  714. - HWMON_T_INPUT,
  715. - HWMON_T_INPUT,
  716. - HWMON_T_INPUT,
  717. - HWMON_T_INPUT,
  718. - HWMON_T_INPUT,
  719. - HWMON_T_INPUT),
  720. + HWMON_T_INPUT | HWMON_T_LABEL,
  721. + HWMON_T_INPUT | HWMON_T_LABEL,
  722. + HWMON_T_INPUT | HWMON_T_LABEL,
  723. + HWMON_T_INPUT | HWMON_T_LABEL,
  724. + HWMON_T_INPUT | HWMON_T_LABEL,
  725. + HWMON_T_INPUT | HWMON_T_LABEL,
  726. + HWMON_T_INPUT | HWMON_T_LABEL,
  727. + HWMON_T_INPUT | HWMON_T_LABEL,
  728. + HWMON_T_INPUT | HWMON_T_LABEL,
  729. + HWMON_T_INPUT | HWMON_T_LABEL,
  730. + HWMON_T_INPUT | HWMON_T_LABEL,
  731. + HWMON_T_INPUT | HWMON_T_LABEL,
  732. + HWMON_T_INPUT | HWMON_T_LABEL,
  733. + HWMON_T_INPUT | HWMON_T_LABEL,
  734. + HWMON_T_INPUT | HWMON_T_LABEL,
  735. + HWMON_T_INPUT | HWMON_T_LABEL),
  736. NULL
  737. };
  738. static const struct hwmon_ops ssam_temp_hwmon_ops = {
  739. .is_visible = ssam_temp_hwmon_is_visible,
  740. .read = ssam_temp_hwmon_read,
  741. + .read_string = ssam_temp_hwmon_read_string,
  742. };
  743. static const struct hwmon_chip_info ssam_temp_hwmon_chip_info = {
  744. @@ -122,6 +187,7 @@ static int ssam_temp_probe(struct ssam_device *sdev)
  745. struct ssam_temp *ssam_temp;
  746. struct device *hwmon_dev;
  747. s16 sensors;
  748. + int channel;
  749. int status;
  750. status = ssam_tmp_get_available_sensors(sdev, &sensors);
  751. @@ -135,6 +201,19 @@ static int ssam_temp_probe(struct ssam_device *sdev)
  752. ssam_temp->sdev = sdev;
  753. ssam_temp->sensors = sensors;
  754. + /* Retrieve the name for each available sensor. */
  755. + for (channel = 0; channel < SSAM_TMP_SENSOR_MAX_COUNT; channel++)
  756. + {
  757. + if (!(sensors & BIT(channel)))
  758. + continue;
  759. +
  760. + status = ssam_tmp_get_name(sdev, channel + 1,
  761. + ssam_temp->names[channel],
  762. + SSAM_TMP_SENSOR_NAME_LENGTH);
  763. + if (status)
  764. + return status;
  765. + }
  766. +
  767. hwmon_dev = devm_hwmon_device_register_with_info(&sdev->dev,
  768. "surface_thermal", ssam_temp, &ssam_temp_hwmon_chip_info,
  769. NULL);
  770. --
  771. 2.45.2
  772. From fdf1850fe9d4ee229a5602361be23c126ce65c8a Mon Sep 17 00:00:00 2001
  773. From: Maximilian Luz <luzmaximilian@gmail.com>
  774. Date: Sat, 30 Dec 2023 18:21:12 +0100
  775. Subject: [PATCH] platform/surface: aggregator_registry: Add support for
  776. thermal sensors on the Surface Pro 9
  777. The Surface Pro 9 has thermal sensors connected via the Surface
  778. Aggregator Module. Add a device node to support those.
  779. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  780. Patchset: surface-sam
  781. ---
  782. drivers/platform/surface/surface_aggregator_registry.c | 7 +++++++
  783. 1 file changed, 7 insertions(+)
  784. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  785. index 34df1bdad83b..c0bf0cadcd25 100644
  786. --- a/drivers/platform/surface/surface_aggregator_registry.c
  787. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  788. @@ -74,6 +74,12 @@ static const struct software_node ssam_node_tmp_pprof = {
  789. .parent = &ssam_node_root,
  790. };
  791. +/* Thermal sensors. */
  792. +static const struct software_node ssam_node_tmp_sensors = {
  793. + .name = "ssam:01:03:01:00:02",
  794. + .parent = &ssam_node_root,
  795. +};
  796. +
  797. /* Fan speed function. */
  798. static const struct software_node ssam_node_fan_speed = {
  799. .name = "ssam:01:05:01:01:01",
  800. @@ -341,6 +347,7 @@ static const struct software_node *ssam_node_group_sp9[] = {
  801. &ssam_node_bat_ac,
  802. &ssam_node_bat_main,
  803. &ssam_node_tmp_pprof,
  804. + &ssam_node_tmp_sensors,
  805. &ssam_node_fan_speed,
  806. &ssam_node_pos_tablet_switch,
  807. &ssam_node_hid_kip_keyboard,
  808. --
  809. 2.45.2
  810. From c98dd80f6541a1bd7108324f65d77a04a6978e39 Mon Sep 17 00:00:00 2001
  811. From: Ivor Wanders <ivor@iwanders.net>
  812. Date: Sat, 16 Dec 2023 15:56:39 -0500
  813. Subject: [PATCH] platform/surface: platform_profile: add fan profile switching
  814. Change naming from tmp to platform profile to clarify the module may
  815. interact with both the TMP and FAN subystems. Add functionality that
  816. switches the fan profile when the platform profile is changed.
  817. Signed-off-by: Ivor Wanders <ivor@iwanders.net>
  818. Patchset: surface-sam
  819. ---
  820. .../surface/surface_aggregator_registry.c | 38 +++++---
  821. .../surface/surface_platform_profile.c | 86 ++++++++++++++++---
  822. 2 files changed, 100 insertions(+), 24 deletions(-)
  823. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  824. index c0bf0cadcd25..07a4c4e1120d 100644
  825. --- a/drivers/platform/surface/surface_aggregator_registry.c
  826. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  827. @@ -68,8 +68,8 @@ static const struct software_node ssam_node_bat_sb3base = {
  828. .parent = &ssam_node_hub_base,
  829. };
  830. -/* Platform profile / performance-mode device. */
  831. -static const struct software_node ssam_node_tmp_pprof = {
  832. +/* Platform profile / performance-mode device without a fan. */
  833. +static const struct software_node ssam_node_tmp_perf_profile = {
  834. .name = "ssam:01:03:01:00:01",
  835. .parent = &ssam_node_root,
  836. };
  837. @@ -86,6 +86,20 @@ static const struct software_node ssam_node_fan_speed = {
  838. .parent = &ssam_node_root,
  839. };
  840. +/* Platform profile / performance-mode device with a fan, such that
  841. + * the fan controller profile can also be switched.
  842. + */
  843. +static const struct property_entry ssam_node_tmp_perf_profile_has_fan[] = {
  844. + PROPERTY_ENTRY_BOOL("has_fan"),
  845. + { }
  846. +};
  847. +
  848. +static const struct software_node ssam_node_tmp_perf_profile_with_fan = {
  849. + .name = "ssam:01:03:01:00:01",
  850. + .parent = &ssam_node_root,
  851. + .properties = ssam_node_tmp_perf_profile_has_fan,
  852. +};
  853. +
  854. /* Tablet-mode switch via KIP subsystem. */
  855. static const struct software_node ssam_node_kip_tablet_switch = {
  856. .name = "ssam:01:0e:01:00:01",
  857. @@ -214,7 +228,7 @@ static const struct software_node ssam_node_pos_tablet_switch = {
  858. */
  859. static const struct software_node *ssam_node_group_gen5[] = {
  860. &ssam_node_root,
  861. - &ssam_node_tmp_pprof,
  862. + &ssam_node_tmp_perf_profile,
  863. NULL,
  864. };
  865. @@ -225,7 +239,7 @@ static const struct software_node *ssam_node_group_sb3[] = {
  866. &ssam_node_bat_ac,
  867. &ssam_node_bat_main,
  868. &ssam_node_bat_sb3base,
  869. - &ssam_node_tmp_pprof,
  870. + &ssam_node_tmp_perf_profile,
  871. &ssam_node_bas_dtx,
  872. &ssam_node_hid_base_keyboard,
  873. &ssam_node_hid_base_touchpad,
  874. @@ -239,7 +253,7 @@ static const struct software_node *ssam_node_group_sl3[] = {
  875. &ssam_node_root,
  876. &ssam_node_bat_ac,
  877. &ssam_node_bat_main,
  878. - &ssam_node_tmp_pprof,
  879. + &ssam_node_tmp_perf_profile,
  880. &ssam_node_hid_main_keyboard,
  881. &ssam_node_hid_main_touchpad,
  882. &ssam_node_hid_main_iid5,
  883. @@ -251,7 +265,7 @@ static const struct software_node *ssam_node_group_sl5[] = {
  884. &ssam_node_root,
  885. &ssam_node_bat_ac,
  886. &ssam_node_bat_main,
  887. - &ssam_node_tmp_pprof,
  888. + &ssam_node_tmp_perf_profile,
  889. &ssam_node_hid_main_keyboard,
  890. &ssam_node_hid_main_touchpad,
  891. &ssam_node_hid_main_iid5,
  892. @@ -280,7 +294,7 @@ static const struct software_node *ssam_node_group_sls1[] = {
  893. &ssam_node_root,
  894. &ssam_node_bat_ac,
  895. &ssam_node_bat_main,
  896. - &ssam_node_tmp_pprof,
  897. + &ssam_node_tmp_perf_profile,
  898. &ssam_node_pos_tablet_switch,
  899. &ssam_node_hid_sam_keyboard,
  900. &ssam_node_hid_sam_penstash,
  901. @@ -296,7 +310,7 @@ static const struct software_node *ssam_node_group_sls2[] = {
  902. &ssam_node_root,
  903. &ssam_node_bat_ac,
  904. &ssam_node_bat_main,
  905. - &ssam_node_tmp_pprof,
  906. + &ssam_node_tmp_perf_profile,
  907. &ssam_node_pos_tablet_switch,
  908. &ssam_node_hid_sam_keyboard,
  909. &ssam_node_hid_sam_penstash,
  910. @@ -310,7 +324,7 @@ static const struct software_node *ssam_node_group_slg1[] = {
  911. &ssam_node_root,
  912. &ssam_node_bat_ac,
  913. &ssam_node_bat_main,
  914. - &ssam_node_tmp_pprof,
  915. + &ssam_node_tmp_perf_profile,
  916. NULL,
  917. };
  918. @@ -319,7 +333,7 @@ static const struct software_node *ssam_node_group_sp7[] = {
  919. &ssam_node_root,
  920. &ssam_node_bat_ac,
  921. &ssam_node_bat_main,
  922. - &ssam_node_tmp_pprof,
  923. + &ssam_node_tmp_perf_profile,
  924. NULL,
  925. };
  926. @@ -329,7 +343,7 @@ static const struct software_node *ssam_node_group_sp8[] = {
  927. &ssam_node_hub_kip,
  928. &ssam_node_bat_ac,
  929. &ssam_node_bat_main,
  930. - &ssam_node_tmp_pprof,
  931. + &ssam_node_tmp_perf_profile,
  932. &ssam_node_kip_tablet_switch,
  933. &ssam_node_hid_kip_keyboard,
  934. &ssam_node_hid_kip_penstash,
  935. @@ -346,7 +360,7 @@ static const struct software_node *ssam_node_group_sp9[] = {
  936. &ssam_node_hub_kip,
  937. &ssam_node_bat_ac,
  938. &ssam_node_bat_main,
  939. - &ssam_node_tmp_pprof,
  940. + &ssam_node_tmp_perf_profile_with_fan,
  941. &ssam_node_tmp_sensors,
  942. &ssam_node_fan_speed,
  943. &ssam_node_pos_tablet_switch,
  944. diff --git a/drivers/platform/surface/surface_platform_profile.c b/drivers/platform/surface/surface_platform_profile.c
  945. index a5a3941b3f43..e54d0a8f7daa 100644
  946. --- a/drivers/platform/surface/surface_platform_profile.c
  947. +++ b/drivers/platform/surface/surface_platform_profile.c
  948. @@ -1,7 +1,7 @@
  949. // SPDX-License-Identifier: GPL-2.0+
  950. /*
  951. * Surface Platform Profile / Performance Mode driver for Surface System
  952. - * Aggregator Module (thermal subsystem).
  953. + * Aggregator Module (thermal and fan subsystem).
  954. *
  955. * Copyright (C) 2021-2022 Maximilian Luz <luzmaximilian@gmail.com>
  956. */
  957. @@ -14,6 +14,7 @@
  958. #include <linux/surface_aggregator/device.h>
  959. +// Enum for the platform performance profile sent to the TMP module.
  960. enum ssam_tmp_profile {
  961. SSAM_TMP_PROFILE_NORMAL = 1,
  962. SSAM_TMP_PROFILE_BATTERY_SAVER = 2,
  963. @@ -21,15 +22,26 @@ enum ssam_tmp_profile {
  964. SSAM_TMP_PROFILE_BEST_PERFORMANCE = 4,
  965. };
  966. +// Enum for the fan profile sent to the FAN module. This fan profile is
  967. +// only sent to the EC if the 'has_fan' property is set. The integers are
  968. +// not a typo, they differ from the performance profile indices.
  969. +enum ssam_fan_profile {
  970. + SSAM_FAN_PROFILE_NORMAL = 2,
  971. + SSAM_FAN_PROFILE_BATTERY_SAVER = 1,
  972. + SSAM_FAN_PROFILE_BETTER_PERFORMANCE = 3,
  973. + SSAM_FAN_PROFILE_BEST_PERFORMANCE = 4,
  974. +};
  975. +
  976. struct ssam_tmp_profile_info {
  977. __le32 profile;
  978. __le16 unknown1;
  979. __le16 unknown2;
  980. } __packed;
  981. -struct ssam_tmp_profile_device {
  982. +struct ssam_platform_profile_device {
  983. struct ssam_device *sdev;
  984. struct platform_profile_handler handler;
  985. + bool has_fan;
  986. };
  987. SSAM_DEFINE_SYNC_REQUEST_CL_R(__ssam_tmp_profile_get, struct ssam_tmp_profile_info, {
  988. @@ -42,6 +54,13 @@ SSAM_DEFINE_SYNC_REQUEST_CL_W(__ssam_tmp_profile_set, __le32, {
  989. .command_id = 0x03,
  990. });
  991. +SSAM_DEFINE_SYNC_REQUEST_W(__ssam_fan_profile_set, char, {
  992. + .target_category = SSAM_SSH_TC_FAN,
  993. + .target_id = SSAM_SSH_TID_SAM,
  994. + .command_id = 0x0e,
  995. + .instance_id = 0x01,
  996. +});
  997. +
  998. static int ssam_tmp_profile_get(struct ssam_device *sdev, enum ssam_tmp_profile *p)
  999. {
  1000. struct ssam_tmp_profile_info info;
  1001. @@ -62,7 +81,14 @@ static int ssam_tmp_profile_set(struct ssam_device *sdev, enum ssam_tmp_profile
  1002. return ssam_retry(__ssam_tmp_profile_set, sdev, &profile_le);
  1003. }
  1004. -static int convert_ssam_to_profile(struct ssam_device *sdev, enum ssam_tmp_profile p)
  1005. +static int ssam_fan_profile_set(struct ssam_device *sdev, enum ssam_fan_profile p)
  1006. +{
  1007. + char profile = p;
  1008. +
  1009. + return ssam_retry(__ssam_fan_profile_set, sdev->ctrl, &profile);
  1010. +}
  1011. +
  1012. +static int convert_ssam_tmp_to_profile(struct ssam_device *sdev, enum ssam_tmp_profile p)
  1013. {
  1014. switch (p) {
  1015. case SSAM_TMP_PROFILE_NORMAL:
  1016. @@ -83,7 +109,8 @@ static int convert_ssam_to_profile(struct ssam_device *sdev, enum ssam_tmp_profi
  1017. }
  1018. }
  1019. -static int convert_profile_to_ssam(struct ssam_device *sdev, enum platform_profile_option p)
  1020. +
  1021. +static int convert_profile_to_ssam_tmp(struct ssam_device *sdev, enum platform_profile_option p)
  1022. {
  1023. switch (p) {
  1024. case PLATFORM_PROFILE_LOW_POWER:
  1025. @@ -105,20 +132,42 @@ static int convert_profile_to_ssam(struct ssam_device *sdev, enum platform_profi
  1026. }
  1027. }
  1028. +static int convert_profile_to_ssam_fan(struct ssam_device *sdev, enum platform_profile_option p)
  1029. +{
  1030. + switch (p) {
  1031. + case PLATFORM_PROFILE_LOW_POWER:
  1032. + return SSAM_FAN_PROFILE_BATTERY_SAVER;
  1033. +
  1034. + case PLATFORM_PROFILE_BALANCED:
  1035. + return SSAM_FAN_PROFILE_NORMAL;
  1036. +
  1037. + case PLATFORM_PROFILE_BALANCED_PERFORMANCE:
  1038. + return SSAM_FAN_PROFILE_BETTER_PERFORMANCE;
  1039. +
  1040. + case PLATFORM_PROFILE_PERFORMANCE:
  1041. + return SSAM_FAN_PROFILE_BEST_PERFORMANCE;
  1042. +
  1043. + default:
  1044. + /* This should have already been caught by platform_profile_store(). */
  1045. + WARN(true, "unsupported platform profile");
  1046. + return -EOPNOTSUPP;
  1047. + }
  1048. +}
  1049. +
  1050. static int ssam_platform_profile_get(struct platform_profile_handler *pprof,
  1051. enum platform_profile_option *profile)
  1052. {
  1053. - struct ssam_tmp_profile_device *tpd;
  1054. + struct ssam_platform_profile_device *tpd;
  1055. enum ssam_tmp_profile tp;
  1056. int status;
  1057. - tpd = container_of(pprof, struct ssam_tmp_profile_device, handler);
  1058. + tpd = container_of(pprof, struct ssam_platform_profile_device, handler);
  1059. status = ssam_tmp_profile_get(tpd->sdev, &tp);
  1060. if (status)
  1061. return status;
  1062. - status = convert_ssam_to_profile(tpd->sdev, tp);
  1063. + status = convert_ssam_tmp_to_profile(tpd->sdev, tp);
  1064. if (status < 0)
  1065. return status;
  1066. @@ -129,21 +178,32 @@ static int ssam_platform_profile_get(struct platform_profile_handler *pprof,
  1067. static int ssam_platform_profile_set(struct platform_profile_handler *pprof,
  1068. enum platform_profile_option profile)
  1069. {
  1070. - struct ssam_tmp_profile_device *tpd;
  1071. + struct ssam_platform_profile_device *tpd;
  1072. int tp;
  1073. - tpd = container_of(pprof, struct ssam_tmp_profile_device, handler);
  1074. + tpd = container_of(pprof, struct ssam_platform_profile_device, handler);
  1075. +
  1076. + tp = convert_profile_to_ssam_tmp(tpd->sdev, profile);
  1077. + if (tp < 0)
  1078. + return tp;
  1079. - tp = convert_profile_to_ssam(tpd->sdev, profile);
  1080. + tp = ssam_tmp_profile_set(tpd->sdev, tp);
  1081. if (tp < 0)
  1082. return tp;
  1083. - return ssam_tmp_profile_set(tpd->sdev, tp);
  1084. + if (tpd->has_fan) {
  1085. + tp = convert_profile_to_ssam_fan(tpd->sdev, profile);
  1086. + if (tp < 0)
  1087. + return tp;
  1088. + tp = ssam_fan_profile_set(tpd->sdev, tp);
  1089. + }
  1090. +
  1091. + return tp;
  1092. }
  1093. static int surface_platform_profile_probe(struct ssam_device *sdev)
  1094. {
  1095. - struct ssam_tmp_profile_device *tpd;
  1096. + struct ssam_platform_profile_device *tpd;
  1097. tpd = devm_kzalloc(&sdev->dev, sizeof(*tpd), GFP_KERNEL);
  1098. if (!tpd)
  1099. @@ -154,6 +214,8 @@ static int surface_platform_profile_probe(struct ssam_device *sdev)
  1100. tpd->handler.profile_get = ssam_platform_profile_get;
  1101. tpd->handler.profile_set = ssam_platform_profile_set;
  1102. + tpd->has_fan = device_property_read_bool(&sdev->dev, "has_fan");
  1103. +
  1104. set_bit(PLATFORM_PROFILE_LOW_POWER, tpd->handler.choices);
  1105. set_bit(PLATFORM_PROFILE_BALANCED, tpd->handler.choices);
  1106. set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, tpd->handler.choices);
  1107. --
  1108. 2.45.2
  1109. From 4adc9fe7e3e43927845ff1711d8f0a7c0a3c7e74 Mon Sep 17 00:00:00 2001
  1110. From: Maximilian Luz <luzmaximilian@gmail.com>
  1111. Date: Mon, 10 Jun 2024 21:47:47 +0200
  1112. Subject: [PATCH] platform/surface: aggregator_registry: Add fan and thermal
  1113. sensor support for Surface Laptop 5
  1114. Patchset: surface-sam
  1115. ---
  1116. drivers/platform/surface/surface_aggregator_registry.c | 4 +++-
  1117. 1 file changed, 3 insertions(+), 1 deletion(-)
  1118. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  1119. index 07a4c4e1120d..4dc79f791d39 100644
  1120. --- a/drivers/platform/surface/surface_aggregator_registry.c
  1121. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  1122. @@ -265,7 +265,9 @@ static const struct software_node *ssam_node_group_sl5[] = {
  1123. &ssam_node_root,
  1124. &ssam_node_bat_ac,
  1125. &ssam_node_bat_main,
  1126. - &ssam_node_tmp_perf_profile,
  1127. + &ssam_node_tmp_perf_profile_with_fan,
  1128. + &ssam_node_tmp_sensors,
  1129. + &ssam_node_fan_speed,
  1130. &ssam_node_hid_main_keyboard,
  1131. &ssam_node_hid_main_touchpad,
  1132. &ssam_node_hid_main_iid5,
  1133. --
  1134. 2.45.2
  1135. From df74cd4f195731eec0d7423b9b5ac5ad54e66206 Mon Sep 17 00:00:00 2001
  1136. From: Maximilian Luz <luzmaximilian@gmail.com>
  1137. Date: Mon, 10 Jun 2024 21:48:02 +0200
  1138. Subject: [PATCH] platform/surface: aggregator_registry: Add fan and thermal
  1139. sensor support for Surface Laptop Studio 2
  1140. Patchset: surface-sam
  1141. ---
  1142. drivers/platform/surface/surface_aggregator_registry.c | 4 +++-
  1143. 1 file changed, 3 insertions(+), 1 deletion(-)
  1144. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  1145. index 4dc79f791d39..77f903a04d12 100644
  1146. --- a/drivers/platform/surface/surface_aggregator_registry.c
  1147. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  1148. @@ -312,7 +312,9 @@ static const struct software_node *ssam_node_group_sls2[] = {
  1149. &ssam_node_root,
  1150. &ssam_node_bat_ac,
  1151. &ssam_node_bat_main,
  1152. - &ssam_node_tmp_perf_profile,
  1153. + &ssam_node_tmp_perf_profile_with_fan,
  1154. + &ssam_node_tmp_sensors,
  1155. + &ssam_node_fan_speed,
  1156. &ssam_node_pos_tablet_switch,
  1157. &ssam_node_hid_sam_keyboard,
  1158. &ssam_node_hid_sam_penstash,
  1159. --
  1160. 2.45.2
  1161. From fbda016e6525668c554714feb8aa09e1baa3d174 Mon Sep 17 00:00:00 2001
  1162. From: Maximilian Luz <luzmaximilian@gmail.com>
  1163. Date: Fri, 28 Jun 2024 22:31:37 +0200
  1164. Subject: [PATCH] platform/surface: aggregator_registry: Add Support for
  1165. Surface Pro 10
  1166. Patchset: surface-sam
  1167. ---
  1168. .../surface/surface_aggregator_registry.c | 22 +++++++++++++++++++
  1169. 1 file changed, 22 insertions(+)
  1170. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  1171. index 77f903a04d12..7d01d989d2a4 100644
  1172. --- a/drivers/platform/surface/surface_aggregator_registry.c
  1173. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  1174. @@ -377,6 +377,25 @@ static const struct software_node *ssam_node_group_sp9[] = {
  1175. NULL,
  1176. };
  1177. +/* Devices for Surface Pro 10 */
  1178. +static const struct software_node *ssam_node_group_sp10[] = {
  1179. + &ssam_node_root,
  1180. + &ssam_node_hub_kip,
  1181. + &ssam_node_bat_ac,
  1182. + &ssam_node_bat_main,
  1183. + &ssam_node_tmp_perf_profile_with_fan,
  1184. + &ssam_node_tmp_sensors,
  1185. + &ssam_node_fan_speed,
  1186. + &ssam_node_pos_tablet_switch,
  1187. + &ssam_node_hid_kip_keyboard,
  1188. + &ssam_node_hid_kip_penstash,
  1189. + &ssam_node_hid_kip_touchpad,
  1190. + &ssam_node_hid_kip_fwupd,
  1191. + &ssam_node_hid_sam_sensors,
  1192. + &ssam_node_hid_sam_ucm_ucsi,
  1193. + NULL,
  1194. +};
  1195. +
  1196. /* -- SSAM platform/meta-hub driver. ---------------------------------------- */
  1197. @@ -399,6 +418,9 @@ static const struct acpi_device_id ssam_platform_hub_match[] = {
  1198. /* Surface Pro 9 */
  1199. { "MSHW0343", (unsigned long)ssam_node_group_sp9 },
  1200. + /* Surface Pro 10 */
  1201. + { "MSHW0510", (unsigned long)ssam_node_group_sp10 },
  1202. +
  1203. /* Surface Book 2 */
  1204. { "MSHW0107", (unsigned long)ssam_node_group_gen5 },
  1205. --
  1206. 2.45.2