0007-surface-sam.patch 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337
  1. From 4dd4e50694677d063eceb17e44b24fd0473df390 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 c476d884356db..b47a277978a0b 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.1
  69. From f467f4373c2620fbf27c1ce0246bad8437034e33 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 ba550eaa06fcf..797d0645bd77f 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.1
  186. From aa3d6b4b41566cbb68ba342463fee27924238b30 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 7fc602e01487d..7e89f547999b2 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.1
  232. From dd4678d91fa59cdf247be667fa64b8959029123d 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 035d6b4105cd6..74688a2ed4b2e 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.1
  259. From 3598d00445216e0b1b0b3e4141c5a2f359bf19c4 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 74688a2ed4b2e..f02a933160ff2 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.1
  321. From eab61a4d3b4de4f3f61789748ecff660b07fbf8b 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 f02a933160ff2..34df1bdad83bd 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.1
  371. From 1b6e5187d5961bd4bf4aa939426f0dfa9f01abd8 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 83945397b6eb1..338ef73c96a3a 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 5c31808f6378d..de8bc99719e63 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 0000000000000..48c3e826713f6
  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.1
  593. From 5e8b9e18c1502bd5371a42014b104e91467a3437 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 48c3e826713f6..4c08926139dbf 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.1
  772. From 1e3af9982108daf50b030c5672df1f2791107608 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 34df1bdad83bd..c0bf0cadcd258 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.1
  810. From fe8e2664ddcf80418be9e2f4ae3b9211257b6647 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 c0bf0cadcd258..07a4c4e1120d3 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 a5a3941b3f43a..e54d0a8f7daa5 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.1
  1109. From a36158d7724a8799dc53a8605f22d368d52d3bc5 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 07a4c4e1120d3..4dc79f791d390 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.1
  1135. From ed9d1558fb33c0654e51457081b231e24bab480e 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 4dc79f791d390..77f903a04d128 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.1
  1161. From 72c97a89faddb83b43940ae213db3d96bbd14210 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 77f903a04d128..7d01d989d2a49 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.1