0006-surface-sam.patch 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163
  1. From 1336f715db65f12890442d46d85b6afbd28ffa38 Mon Sep 17 00:00:00 2001
  2. From: Maximilian Luz <luzmaximilian@gmail.com>
  3. Date: Sun, 22 Oct 2023 14:57:11 +0200
  4. Subject: [PATCH] platform/surface: aggregator_registry: Add support for
  5. Surface Laptop Go 3
  6. Add SAM client device nodes for the Surface Laptop Go 3. It seems to use
  7. the same SAM client devices as the Surface Laptop Go 1 and 2, so re-use
  8. their node group.
  9. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  10. Patchset: surface-sam
  11. ---
  12. drivers/platform/surface/surface_aggregator_registry.c | 3 +++
  13. 1 file changed, 3 insertions(+)
  14. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  15. index 0fe5be539652..0d8c8395c588 100644
  16. --- a/drivers/platform/surface/surface_aggregator_registry.c
  17. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  18. @@ -367,6 +367,9 @@ static const struct acpi_device_id ssam_platform_hub_match[] = {
  19. /* Surface Laptop Go 2 */
  20. { "MSHW0290", (unsigned long)ssam_node_group_slg1 },
  21. + /* Surface Laptop Go 3 */
  22. + { "MSHW0440", (unsigned long)ssam_node_group_slg1 },
  23. +
  24. /* Surface Laptop Studio */
  25. { "MSHW0123", (unsigned long)ssam_node_group_sls },
  26. --
  27. 2.44.0
  28. From 04a113aa335b566860380818090ed0ce606377c0 Mon Sep 17 00:00:00 2001
  29. From: Maximilian Luz <luzmaximilian@gmail.com>
  30. Date: Mon, 20 Nov 2023 19:47:00 +0100
  31. Subject: [PATCH] platform/surface: aggregator_registry: Add support for
  32. Surface Laptop Studio 2
  33. Add SAM client device nodes for the Surface Laptop Studio 2 (SLS2). The
  34. SLS2 is quite similar to the SLS1, but it does not provide the touchpad
  35. as a SAM-HID device. Therefore, add a new node group for the SLS2 and
  36. update the comments accordingly
  37. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  38. Patchset: surface-sam
  39. ---
  40. .../surface/surface_aggregator_registry.c | 25 ++++++++++++++++---
  41. 1 file changed, 21 insertions(+), 4 deletions(-)
  42. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  43. index 0d8c8395c588..530db4db71ab 100644
  44. --- a/drivers/platform/surface/surface_aggregator_registry.c
  45. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  46. @@ -247,8 +247,8 @@ static const struct software_node *ssam_node_group_sl5[] = {
  47. NULL,
  48. };
  49. -/* Devices for Surface Laptop Studio. */
  50. -static const struct software_node *ssam_node_group_sls[] = {
  51. +/* Devices for Surface Laptop Studio 1. */
  52. +static const struct software_node *ssam_node_group_sls1[] = {
  53. &ssam_node_root,
  54. &ssam_node_bat_ac,
  55. &ssam_node_bat_main,
  56. @@ -263,6 +263,20 @@ static const struct software_node *ssam_node_group_sls[] = {
  57. NULL,
  58. };
  59. +/* Devices for Surface Laptop Studio 2. */
  60. +static const struct software_node *ssam_node_group_sls2[] = {
  61. + &ssam_node_root,
  62. + &ssam_node_bat_ac,
  63. + &ssam_node_bat_main,
  64. + &ssam_node_tmp_pprof,
  65. + &ssam_node_pos_tablet_switch,
  66. + &ssam_node_hid_sam_keyboard,
  67. + &ssam_node_hid_sam_penstash,
  68. + &ssam_node_hid_sam_sensors,
  69. + &ssam_node_hid_sam_ucm_ucsi,
  70. + NULL,
  71. +};
  72. +
  73. /* Devices for Surface Laptop Go. */
  74. static const struct software_node *ssam_node_group_slg1[] = {
  75. &ssam_node_root,
  76. @@ -370,8 +384,11 @@ static const struct acpi_device_id ssam_platform_hub_match[] = {
  77. /* Surface Laptop Go 3 */
  78. { "MSHW0440", (unsigned long)ssam_node_group_slg1 },
  79. - /* Surface Laptop Studio */
  80. - { "MSHW0123", (unsigned long)ssam_node_group_sls },
  81. + /* Surface Laptop Studio 1 */
  82. + { "MSHW0123", (unsigned long)ssam_node_group_sls1 },
  83. +
  84. + /* Surface Laptop Studio 2 */
  85. + { "MSHW0360", (unsigned long)ssam_node_group_sls2 },
  86. { },
  87. };
  88. --
  89. 2.44.0
  90. From 31253c1714eef54d147ff70886be3e0b86301656 Mon Sep 17 00:00:00 2001
  91. From: Ivor Wanders <ivor@iwanders.net>
  92. Date: Mon, 18 Dec 2023 19:21:32 -0500
  93. Subject: [PATCH] platform/surface: aggregator_registry: add entry for fan
  94. speed
  95. Add an entry for the fan speed function.
  96. Add this new entry to the Surface Pro 9 group.
  97. Signed-off-by: Ivor Wanders <ivor@iwanders.net>
  98. Link: https://github.com/linux-surface/kernel/pull/144
  99. Reviewed-by: Maximilian Luz <luzmaximilian@gmail.com>
  100. Patchset: surface-sam
  101. ---
  102. drivers/platform/surface/surface_aggregator_registry.c | 7 +++++++
  103. 1 file changed, 7 insertions(+)
  104. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  105. index 530db4db71ab..b0db25886c99 100644
  106. --- a/drivers/platform/surface/surface_aggregator_registry.c
  107. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  108. @@ -74,6 +74,12 @@ static const struct software_node ssam_node_tmp_pprof = {
  109. .parent = &ssam_node_root,
  110. };
  111. +/* Fan speed function. */
  112. +static const struct software_node ssam_node_fan_speed = {
  113. + .name = "ssam:01:05:01:01:01",
  114. + .parent = &ssam_node_root,
  115. +};
  116. +
  117. /* Tablet-mode switch via KIP subsystem. */
  118. static const struct software_node ssam_node_kip_tablet_switch = {
  119. .name = "ssam:01:0e:01:00:01",
  120. @@ -319,6 +325,7 @@ static const struct software_node *ssam_node_group_sp9[] = {
  121. &ssam_node_bat_ac,
  122. &ssam_node_bat_main,
  123. &ssam_node_tmp_pprof,
  124. + &ssam_node_fan_speed,
  125. &ssam_node_pos_tablet_switch,
  126. &ssam_node_hid_kip_keyboard,
  127. &ssam_node_hid_kip_penstash,
  128. --
  129. 2.44.0
  130. From ba442037211d245c84dcd4cd1ec81a09468305e6 Mon Sep 17 00:00:00 2001
  131. From: Ivor Wanders <ivor@iwanders.net>
  132. Date: Thu, 30 Nov 2023 20:20:24 -0500
  133. Subject: [PATCH] hwmon: add fan speed monitoring driver for Surface devices
  134. Adds a driver that provides read only access to the fan speed for Microsoft
  135. Surface Pro devices. The fan speed is always regulated by the EC and cannot
  136. be influenced directly.
  137. Signed-off-by: Ivor Wanders <ivor@iwanders.net>
  138. Link: https://github.com/linux-surface/kernel/pull/144
  139. Patchset: surface-sam
  140. ---
  141. Documentation/hwmon/index.rst | 1 +
  142. Documentation/hwmon/surface_fan.rst | 25 ++++++++
  143. MAINTAINERS | 8 +++
  144. drivers/hwmon/Kconfig | 13 ++++
  145. drivers/hwmon/Makefile | 1 +
  146. drivers/hwmon/surface_fan.c | 93 +++++++++++++++++++++++++++++
  147. 6 files changed, 141 insertions(+)
  148. create mode 100644 Documentation/hwmon/surface_fan.rst
  149. create mode 100644 drivers/hwmon/surface_fan.c
  150. diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
  151. index 88dadea85cfc..266edff78972 100644
  152. --- a/Documentation/hwmon/index.rst
  153. +++ b/Documentation/hwmon/index.rst
  154. @@ -202,6 +202,7 @@ Hardware Monitoring Kernel Drivers
  155. smsc47m1
  156. sparx5-temp
  157. stpddc60
  158. + surface_fan
  159. sy7636a-hwmon
  160. tc654
  161. tc74
  162. diff --git a/Documentation/hwmon/surface_fan.rst b/Documentation/hwmon/surface_fan.rst
  163. new file mode 100644
  164. index 000000000000..07942574c4f0
  165. --- /dev/null
  166. +++ b/Documentation/hwmon/surface_fan.rst
  167. @@ -0,0 +1,25 @@
  168. +.. SPDX-License-Identifier: GPL-2.0-or-later
  169. +
  170. +Kernel driver surface_fan
  171. +=========================
  172. +
  173. +Supported Devices:
  174. +
  175. + * Microsoft Surface Pro 9
  176. +
  177. +Author: Ivor Wanders <ivor@iwanders.net>
  178. +
  179. +Description
  180. +-----------
  181. +
  182. +This provides monitoring of the fan found in some Microsoft Surface Pro devices,
  183. +like the Surface Pro 9. The fan is always controlled by the onboard controller.
  184. +
  185. +Sysfs interface
  186. +---------------
  187. +
  188. +======================= ======= =========================================
  189. +Name Perm Description
  190. +======================= ======= =========================================
  191. +``fan1_input`` RO Current fan speed in RPM.
  192. +======================= ======= =========================================
  193. diff --git a/MAINTAINERS b/MAINTAINERS
  194. index dd5de540ec0b..63c3f9327927 100644
  195. --- a/MAINTAINERS
  196. +++ b/MAINTAINERS
  197. @@ -14203,6 +14203,14 @@ F: Documentation/driver-api/surface_aggregator/clients/dtx.rst
  198. F: drivers/platform/surface/surface_dtx.c
  199. F: include/uapi/linux/surface_aggregator/dtx.h
  200. +MICROSOFT SURFACE SENSOR FAN DRIVER
  201. +M: Maximilian Luz <luzmaximilian@gmail.com>
  202. +M: Ivor Wanders <ivor@iwanders.net>
  203. +L: linux-hwmon@vger.kernel.org
  204. +S: Maintained
  205. +F: Documentation/hwmon/surface_fan.rst
  206. +F: drivers/hwmon/surface_fan.c
  207. +
  208. MICROSOFT SURFACE GPE LID SUPPORT DRIVER
  209. M: Maximilian Luz <luzmaximilian@gmail.com>
  210. L: platform-driver-x86@vger.kernel.org
  211. diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
  212. index ec38c8892158..b5267a2fbe5f 100644
  213. --- a/drivers/hwmon/Kconfig
  214. +++ b/drivers/hwmon/Kconfig
  215. @@ -1961,6 +1961,19 @@ config SENSORS_SFCTEMP
  216. This driver can also be built as a module. If so, the module
  217. will be called sfctemp.
  218. +config SENSORS_SURFACE_FAN
  219. + tristate "Surface Fan Driver"
  220. + depends on SURFACE_AGGREGATOR
  221. + help
  222. + Driver that provides monitoring of the fan on Surface Pro devices that
  223. + have a fan, like the Surface Pro 9.
  224. +
  225. + This makes the fan's current speed accessible through the hwmon
  226. + system. It does not provide control over the fan, the firmware is
  227. + responsible for that, this driver merely provides monitoring.
  228. +
  229. + Select M or Y here, if you want to be able to read the fan's speed.
  230. +
  231. config SENSORS_ADC128D818
  232. tristate "Texas Instruments ADC128D818"
  233. depends on I2C
  234. diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
  235. index 4ac9452b5430..208f7345f296 100644
  236. --- a/drivers/hwmon/Makefile
  237. +++ b/drivers/hwmon/Makefile
  238. @@ -198,6 +198,7 @@ obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
  239. obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
  240. obj-$(CONFIG_SENSORS_SPARX5) += sparx5-temp.o
  241. obj-$(CONFIG_SENSORS_STTS751) += stts751.o
  242. +obj-$(CONFIG_SENSORS_SURFACE_FAN)+= surface_fan.o
  243. obj-$(CONFIG_SENSORS_SY7636A) += sy7636a-hwmon.o
  244. obj-$(CONFIG_SENSORS_AMC6821) += amc6821.o
  245. obj-$(CONFIG_SENSORS_TC74) += tc74.o
  246. diff --git a/drivers/hwmon/surface_fan.c b/drivers/hwmon/surface_fan.c
  247. new file mode 100644
  248. index 000000000000..7c2e3ae3eb40
  249. --- /dev/null
  250. +++ b/drivers/hwmon/surface_fan.c
  251. @@ -0,0 +1,93 @@
  252. +// SPDX-License-Identifier: GPL-2.0+
  253. +/*
  254. + * Surface Fan driver for Surface System Aggregator Module. It provides access
  255. + * to the fan's rpm through the hwmon system.
  256. + *
  257. + * Copyright (C) 2023 Ivor Wanders <ivor@iwanders.net>
  258. + */
  259. +
  260. +#include <linux/hwmon.h>
  261. +#include <linux/kernel.h>
  262. +#include <linux/module.h>
  263. +#include <linux/surface_aggregator/device.h>
  264. +#include <linux/types.h>
  265. +
  266. +// SSAM
  267. +SSAM_DEFINE_SYNC_REQUEST_CL_R(__ssam_fan_rpm_get, __le16, {
  268. + .target_category = SSAM_SSH_TC_FAN,
  269. + .command_id = 0x01,
  270. +});
  271. +
  272. +// hwmon
  273. +umode_t surface_fan_hwmon_is_visible(const void *drvdata,
  274. + enum hwmon_sensor_types type, u32 attr,
  275. + int channel)
  276. +{
  277. + return 0444;
  278. +}
  279. +
  280. +static int surface_fan_hwmon_read(struct device *dev,
  281. + enum hwmon_sensor_types type, u32 attr,
  282. + int channel, long *val)
  283. +{
  284. + struct ssam_device *sdev = dev_get_drvdata(dev);
  285. + int ret;
  286. + __le16 value;
  287. +
  288. + ret = __ssam_fan_rpm_get(sdev, &value);
  289. + if (ret)
  290. + return ret;
  291. +
  292. + *val = le16_to_cpu(value);
  293. +
  294. + return ret;
  295. +}
  296. +
  297. +static const struct hwmon_channel_info *const surface_fan_info[] = {
  298. + HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT),
  299. + NULL
  300. +};
  301. +
  302. +static const struct hwmon_ops surface_fan_hwmon_ops = {
  303. + .is_visible = surface_fan_hwmon_is_visible,
  304. + .read = surface_fan_hwmon_read,
  305. +};
  306. +
  307. +static const struct hwmon_chip_info surface_fan_chip_info = {
  308. + .ops = &surface_fan_hwmon_ops,
  309. + .info = surface_fan_info,
  310. +};
  311. +
  312. +static int surface_fan_probe(struct ssam_device *sdev)
  313. +{
  314. + struct device *hdev;
  315. +
  316. + hdev = devm_hwmon_device_register_with_info(&sdev->dev,
  317. + "surface_fan", sdev,
  318. + &surface_fan_chip_info,
  319. + NULL);
  320. + if (IS_ERR(hdev))
  321. + return PTR_ERR(hdev);
  322. +
  323. + return 0;
  324. +}
  325. +
  326. +static const struct ssam_device_id ssam_fan_match[] = {
  327. + { SSAM_SDEV(FAN, SAM, 0x01, 0x01) },
  328. + {},
  329. +};
  330. +MODULE_DEVICE_TABLE(ssam, ssam_fan_match);
  331. +
  332. +static struct ssam_device_driver surface_fan = {
  333. + .probe = surface_fan_probe,
  334. + .match_table = ssam_fan_match,
  335. + .driver = {
  336. + .name = "surface_fan",
  337. + .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  338. + },
  339. +};
  340. +module_ssam_device_driver(surface_fan);
  341. +
  342. +MODULE_AUTHOR("Ivor Wanders <ivor@iwanders.net>");
  343. +MODULE_DESCRIPTION("Fan Driver for Surface System Aggregator Module");
  344. +MODULE_LICENSE("GPL");
  345. --
  346. 2.44.0
  347. From e44dd763f976360449d9f15ed2bb756cc18d843b Mon Sep 17 00:00:00 2001
  348. From: Maximilian Luz <luzmaximilian@gmail.com>
  349. Date: Sat, 30 Dec 2023 18:07:54 +0100
  350. Subject: [PATCH] hwmon: Add thermal sensor driver for Surface Aggregator
  351. Module
  352. Some of the newer Microsoft Surface devices (such as the Surface Book
  353. 3 and Pro 9) have thermal sensors connected via the Surface Aggregator
  354. Module (the embedded controller on those devices). Add a basic driver
  355. to read out the temperature values of those sensors.
  356. Link: https://github.com/linux-surface/surface-aggregator-module/issues/59
  357. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  358. Patchset: surface-sam
  359. ---
  360. drivers/hwmon/Kconfig | 10 +++
  361. drivers/hwmon/Makefile | 1 +
  362. drivers/hwmon/surface_temp.c | 165 +++++++++++++++++++++++++++++++++++
  363. 3 files changed, 176 insertions(+)
  364. create mode 100644 drivers/hwmon/surface_temp.c
  365. diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
  366. index b5267a2fbe5f..2eedbe85d18a 100644
  367. --- a/drivers/hwmon/Kconfig
  368. +++ b/drivers/hwmon/Kconfig
  369. @@ -1974,6 +1974,16 @@ config SENSORS_SURFACE_FAN
  370. Select M or Y here, if you want to be able to read the fan's speed.
  371. +config SENSORS_SURFACE_TEMP
  372. + tristate "Microsoft Surface Thermal Sensor Driver"
  373. + depends on SURFACE_AGGREGATOR
  374. + help
  375. + Driver for monitoring thermal sensors connected via the Surface
  376. + Aggregator Module (embedded controller) on Microsoft Surface devices.
  377. +
  378. + This driver can also be built as a module. If so, the module
  379. + will be called surface_temp.
  380. +
  381. config SENSORS_ADC128D818
  382. tristate "Texas Instruments ADC128D818"
  383. depends on I2C
  384. diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
  385. index 208f7345f296..310d7a2e0f06 100644
  386. --- a/drivers/hwmon/Makefile
  387. +++ b/drivers/hwmon/Makefile
  388. @@ -199,6 +199,7 @@ obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
  389. obj-$(CONFIG_SENSORS_SPARX5) += sparx5-temp.o
  390. obj-$(CONFIG_SENSORS_STTS751) += stts751.o
  391. obj-$(CONFIG_SENSORS_SURFACE_FAN)+= surface_fan.o
  392. +obj-$(CONFIG_SENSORS_SURFACE_TEMP)+= surface_temp.o
  393. obj-$(CONFIG_SENSORS_SY7636A) += sy7636a-hwmon.o
  394. obj-$(CONFIG_SENSORS_AMC6821) += amc6821.o
  395. obj-$(CONFIG_SENSORS_TC74) += tc74.o
  396. diff --git a/drivers/hwmon/surface_temp.c b/drivers/hwmon/surface_temp.c
  397. new file mode 100644
  398. index 000000000000..48c3e826713f
  399. --- /dev/null
  400. +++ b/drivers/hwmon/surface_temp.c
  401. @@ -0,0 +1,165 @@
  402. +// SPDX-License-Identifier: GPL-2.0+
  403. +/*
  404. + * Thermal sensor subsystem driver for Surface System Aggregator Module (SSAM).
  405. + *
  406. + * Copyright (C) 2022-2023 Maximilian Luz <luzmaximilian@gmail.com>
  407. + */
  408. +
  409. +#include <linux/bitops.h>
  410. +#include <linux/hwmon.h>
  411. +#include <linux/kernel.h>
  412. +#include <linux/module.h>
  413. +#include <linux/types.h>
  414. +
  415. +#include <linux/surface_aggregator/controller.h>
  416. +#include <linux/surface_aggregator/device.h>
  417. +
  418. +
  419. +/* -- SAM interface. -------------------------------------------------------- */
  420. +
  421. +SSAM_DEFINE_SYNC_REQUEST_CL_R(__ssam_tmp_get_available_sensors, __le16, {
  422. + .target_category = SSAM_SSH_TC_TMP,
  423. + .command_id = 0x04,
  424. +});
  425. +
  426. +SSAM_DEFINE_SYNC_REQUEST_MD_R(__ssam_tmp_get_temperature, __le16, {
  427. + .target_category = SSAM_SSH_TC_TMP,
  428. + .command_id = 0x01,
  429. +});
  430. +
  431. +static int ssam_tmp_get_available_sensors(struct ssam_device *sdev, s16 *sensors)
  432. +{
  433. + __le16 sensors_le;
  434. + int status;
  435. +
  436. + status = __ssam_tmp_get_available_sensors(sdev, &sensors_le);
  437. + if (status)
  438. + return status;
  439. +
  440. + *sensors = le16_to_cpu(sensors_le);
  441. + return 0;
  442. +}
  443. +
  444. +static int ssam_tmp_get_temperature(struct ssam_device *sdev, u8 iid, long *temperature)
  445. +{
  446. + __le16 temp_le;
  447. + int status;
  448. +
  449. + status = __ssam_tmp_get_temperature(sdev->ctrl, sdev->uid.target, iid, &temp_le);
  450. + if (status)
  451. + return status;
  452. +
  453. + /* Convert 1/10 °K to 1/1000 °C */
  454. + *temperature = (le16_to_cpu(temp_le) - 2731) * 100L;
  455. + return 0;
  456. +}
  457. +
  458. +
  459. +/* -- Driver.---------------------------------------------------------------- */
  460. +
  461. +struct ssam_temp {
  462. + struct ssam_device *sdev;
  463. + s16 sensors;
  464. +};
  465. +
  466. +static umode_t ssam_temp_hwmon_is_visible(const void *data,
  467. + enum hwmon_sensor_types type,
  468. + u32 attr, int channel)
  469. +{
  470. + const struct ssam_temp *ssam_temp = data;
  471. +
  472. + if (!(ssam_temp->sensors & BIT(channel)))
  473. + return 0;
  474. +
  475. + return 0444;
  476. +}
  477. +
  478. +static int ssam_temp_hwmon_read(struct device *dev,
  479. + enum hwmon_sensor_types type,
  480. + u32 attr, int channel, long *value)
  481. +{
  482. + const struct ssam_temp *ssam_temp = dev_get_drvdata(dev);
  483. +
  484. + return ssam_tmp_get_temperature(ssam_temp->sdev, channel + 1, value);
  485. +}
  486. +
  487. +static const struct hwmon_channel_info * const ssam_temp_hwmon_info[] = {
  488. + HWMON_CHANNEL_INFO(chip,
  489. + HWMON_C_REGISTER_TZ),
  490. + /* We have at most 16 thermal sensor channels. */
  491. + HWMON_CHANNEL_INFO(temp,
  492. + HWMON_T_INPUT,
  493. + HWMON_T_INPUT,
  494. + HWMON_T_INPUT,
  495. + HWMON_T_INPUT,
  496. + HWMON_T_INPUT,
  497. + HWMON_T_INPUT,
  498. + HWMON_T_INPUT,
  499. + HWMON_T_INPUT,
  500. + HWMON_T_INPUT,
  501. + HWMON_T_INPUT,
  502. + HWMON_T_INPUT,
  503. + HWMON_T_INPUT,
  504. + HWMON_T_INPUT,
  505. + HWMON_T_INPUT,
  506. + HWMON_T_INPUT,
  507. + HWMON_T_INPUT),
  508. + NULL
  509. +};
  510. +
  511. +static const struct hwmon_ops ssam_temp_hwmon_ops = {
  512. + .is_visible = ssam_temp_hwmon_is_visible,
  513. + .read = ssam_temp_hwmon_read,
  514. +};
  515. +
  516. +static const struct hwmon_chip_info ssam_temp_hwmon_chip_info = {
  517. + .ops = &ssam_temp_hwmon_ops,
  518. + .info = ssam_temp_hwmon_info,
  519. +};
  520. +
  521. +static int ssam_temp_probe(struct ssam_device *sdev)
  522. +{
  523. + struct ssam_temp *ssam_temp;
  524. + struct device *hwmon_dev;
  525. + s16 sensors;
  526. + int status;
  527. +
  528. + status = ssam_tmp_get_available_sensors(sdev, &sensors);
  529. + if (status)
  530. + return status;
  531. +
  532. + ssam_temp = devm_kzalloc(&sdev->dev, sizeof(*ssam_temp), GFP_KERNEL);
  533. + if (!ssam_temp)
  534. + return -ENOMEM;
  535. +
  536. + ssam_temp->sdev = sdev;
  537. + ssam_temp->sensors = sensors;
  538. +
  539. + hwmon_dev = devm_hwmon_device_register_with_info(&sdev->dev,
  540. + "surface_thermal", ssam_temp, &ssam_temp_hwmon_chip_info,
  541. + NULL);
  542. + if (IS_ERR(hwmon_dev))
  543. + return PTR_ERR(hwmon_dev);
  544. +
  545. + return 0;
  546. +}
  547. +
  548. +static const struct ssam_device_id ssam_temp_match[] = {
  549. + { SSAM_SDEV(TMP, SAM, 0x00, 0x02) },
  550. + { },
  551. +};
  552. +MODULE_DEVICE_TABLE(ssam, ssam_temp_match);
  553. +
  554. +static struct ssam_device_driver ssam_temp = {
  555. + .probe = ssam_temp_probe,
  556. + .match_table = ssam_temp_match,
  557. + .driver = {
  558. + .name = "surface_temp",
  559. + .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  560. + },
  561. +};
  562. +module_ssam_device_driver(ssam_temp);
  563. +
  564. +MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
  565. +MODULE_DESCRIPTION("Thermal sensor subsystem driver for Surface System Aggregator Module");
  566. +MODULE_LICENSE("GPL");
  567. --
  568. 2.44.0
  569. From 41399077b077cff19e9b9133955ed81b6d7aa527 Mon Sep 17 00:00:00 2001
  570. From: Maximilian Luz <luzmaximilian@gmail.com>
  571. Date: Sat, 30 Dec 2023 18:12:23 +0100
  572. Subject: [PATCH] hwmon: surface_temp: Add support for sensor names
  573. The thermal subsystem of the Surface Aggregator Module allows us to
  574. query the names of the respective thermal sensors. Forward those to
  575. userspace.
  576. Signed-off-by: Ivor Wanders <ivor@iwanders.net>
  577. Co-Developed-by: Maximilian Luz <luzmaximilian@gmail.com>
  578. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  579. Patchset: surface-sam
  580. ---
  581. drivers/hwmon/surface_temp.c | 113 +++++++++++++++++++++++++++++------
  582. 1 file changed, 96 insertions(+), 17 deletions(-)
  583. diff --git a/drivers/hwmon/surface_temp.c b/drivers/hwmon/surface_temp.c
  584. index 48c3e826713f..4c08926139db 100644
  585. --- a/drivers/hwmon/surface_temp.c
  586. +++ b/drivers/hwmon/surface_temp.c
  587. @@ -17,6 +17,27 @@
  588. /* -- SAM interface. -------------------------------------------------------- */
  589. +/*
  590. + * Available sensors are indicated by a 16-bit bitfield, where a 1 marks the
  591. + * presence of a sensor. So we have at most 16 possible sensors/channels.
  592. + */
  593. +#define SSAM_TMP_SENSOR_MAX_COUNT 16
  594. +
  595. +/*
  596. + * All names observed so far are 6 characters long, but there's only
  597. + * zeros after the name, so perhaps they can be longer. This number reflects
  598. + * the maximum zero-padded space observed in the returned buffer.
  599. + */
  600. +#define SSAM_TMP_SENSOR_NAME_LENGTH 18
  601. +
  602. +struct ssam_tmp_get_name_rsp {
  603. + __le16 unknown1;
  604. + char unknown2;
  605. + char name[SSAM_TMP_SENSOR_NAME_LENGTH];
  606. +} __packed;
  607. +
  608. +static_assert(sizeof(struct ssam_tmp_get_name_rsp) == 21);
  609. +
  610. SSAM_DEFINE_SYNC_REQUEST_CL_R(__ssam_tmp_get_available_sensors, __le16, {
  611. .target_category = SSAM_SSH_TC_TMP,
  612. .command_id = 0x04,
  613. @@ -27,6 +48,11 @@ SSAM_DEFINE_SYNC_REQUEST_MD_R(__ssam_tmp_get_temperature, __le16, {
  614. .command_id = 0x01,
  615. });
  616. +SSAM_DEFINE_SYNC_REQUEST_MD_R(__ssam_tmp_get_name, struct ssam_tmp_get_name_rsp, {
  617. + .target_category = SSAM_SSH_TC_TMP,
  618. + .command_id = 0x0e,
  619. +});
  620. +
  621. static int ssam_tmp_get_available_sensors(struct ssam_device *sdev, s16 *sensors)
  622. {
  623. __le16 sensors_le;
  624. @@ -54,12 +80,37 @@ static int ssam_tmp_get_temperature(struct ssam_device *sdev, u8 iid, long *temp
  625. return 0;
  626. }
  627. +static int ssam_tmp_get_name(struct ssam_device *sdev, u8 iid, char *buf, size_t buf_len)
  628. +{
  629. + struct ssam_tmp_get_name_rsp name_rsp;
  630. + int status;
  631. +
  632. + status = __ssam_tmp_get_name(sdev->ctrl, sdev->uid.target, iid, &name_rsp);
  633. + if (status)
  634. + return status;
  635. +
  636. + /*
  637. + * This should not fail unless the name in the returned struct is not
  638. + * null-terminated or someone changed something in the struct
  639. + * definitions above, since our buffer and struct have the same
  640. + * capacity by design. So if this fails blow this up with a warning.
  641. + * Since the more likely cause is that the returned string isn't
  642. + * null-terminated, we might have received garbage (as opposed to just
  643. + * an incomplete string), so also fail the function.
  644. + */
  645. + status = strscpy(buf, name_rsp.name, buf_len);
  646. + WARN_ON(status < 0);
  647. +
  648. + return status < 0 ? status : 0;
  649. +}
  650. +
  651. /* -- Driver.---------------------------------------------------------------- */
  652. struct ssam_temp {
  653. struct ssam_device *sdev;
  654. s16 sensors;
  655. + char names[SSAM_TMP_SENSOR_MAX_COUNT][SSAM_TMP_SENSOR_NAME_LENGTH];
  656. };
  657. static umode_t ssam_temp_hwmon_is_visible(const void *data,
  658. @@ -83,33 +134,47 @@ static int ssam_temp_hwmon_read(struct device *dev,
  659. return ssam_tmp_get_temperature(ssam_temp->sdev, channel + 1, value);
  660. }
  661. +static int ssam_temp_hwmon_read_string(struct device *dev,
  662. + enum hwmon_sensor_types type,
  663. + u32 attr, int channel, const char **str)
  664. +{
  665. + const struct ssam_temp *ssam_temp = dev_get_drvdata(dev);
  666. +
  667. + *str = ssam_temp->names[channel];
  668. + return 0;
  669. +}
  670. +
  671. static const struct hwmon_channel_info * const ssam_temp_hwmon_info[] = {
  672. HWMON_CHANNEL_INFO(chip,
  673. HWMON_C_REGISTER_TZ),
  674. - /* We have at most 16 thermal sensor channels. */
  675. + /*
  676. + * We have at most SSAM_TMP_SENSOR_MAX_COUNT = 16 thermal sensor
  677. + * channels.
  678. + */
  679. HWMON_CHANNEL_INFO(temp,
  680. - HWMON_T_INPUT,
  681. - HWMON_T_INPUT,
  682. - HWMON_T_INPUT,
  683. - HWMON_T_INPUT,
  684. - HWMON_T_INPUT,
  685. - HWMON_T_INPUT,
  686. - HWMON_T_INPUT,
  687. - HWMON_T_INPUT,
  688. - HWMON_T_INPUT,
  689. - HWMON_T_INPUT,
  690. - HWMON_T_INPUT,
  691. - HWMON_T_INPUT,
  692. - HWMON_T_INPUT,
  693. - HWMON_T_INPUT,
  694. - HWMON_T_INPUT,
  695. - HWMON_T_INPUT),
  696. + HWMON_T_INPUT | HWMON_T_LABEL,
  697. + HWMON_T_INPUT | HWMON_T_LABEL,
  698. + HWMON_T_INPUT | HWMON_T_LABEL,
  699. + HWMON_T_INPUT | HWMON_T_LABEL,
  700. + HWMON_T_INPUT | HWMON_T_LABEL,
  701. + HWMON_T_INPUT | HWMON_T_LABEL,
  702. + HWMON_T_INPUT | HWMON_T_LABEL,
  703. + HWMON_T_INPUT | HWMON_T_LABEL,
  704. + HWMON_T_INPUT | HWMON_T_LABEL,
  705. + HWMON_T_INPUT | HWMON_T_LABEL,
  706. + HWMON_T_INPUT | HWMON_T_LABEL,
  707. + HWMON_T_INPUT | HWMON_T_LABEL,
  708. + HWMON_T_INPUT | HWMON_T_LABEL,
  709. + HWMON_T_INPUT | HWMON_T_LABEL,
  710. + HWMON_T_INPUT | HWMON_T_LABEL,
  711. + HWMON_T_INPUT | HWMON_T_LABEL),
  712. NULL
  713. };
  714. static const struct hwmon_ops ssam_temp_hwmon_ops = {
  715. .is_visible = ssam_temp_hwmon_is_visible,
  716. .read = ssam_temp_hwmon_read,
  717. + .read_string = ssam_temp_hwmon_read_string,
  718. };
  719. static const struct hwmon_chip_info ssam_temp_hwmon_chip_info = {
  720. @@ -122,6 +187,7 @@ static int ssam_temp_probe(struct ssam_device *sdev)
  721. struct ssam_temp *ssam_temp;
  722. struct device *hwmon_dev;
  723. s16 sensors;
  724. + int channel;
  725. int status;
  726. status = ssam_tmp_get_available_sensors(sdev, &sensors);
  727. @@ -135,6 +201,19 @@ static int ssam_temp_probe(struct ssam_device *sdev)
  728. ssam_temp->sdev = sdev;
  729. ssam_temp->sensors = sensors;
  730. + /* Retrieve the name for each available sensor. */
  731. + for (channel = 0; channel < SSAM_TMP_SENSOR_MAX_COUNT; channel++)
  732. + {
  733. + if (!(sensors & BIT(channel)))
  734. + continue;
  735. +
  736. + status = ssam_tmp_get_name(sdev, channel + 1,
  737. + ssam_temp->names[channel],
  738. + SSAM_TMP_SENSOR_NAME_LENGTH);
  739. + if (status)
  740. + return status;
  741. + }
  742. +
  743. hwmon_dev = devm_hwmon_device_register_with_info(&sdev->dev,
  744. "surface_thermal", ssam_temp, &ssam_temp_hwmon_chip_info,
  745. NULL);
  746. --
  747. 2.44.0
  748. From 37894568dd6a0bfb6422ce7c18df757fcb449512 Mon Sep 17 00:00:00 2001
  749. From: Maximilian Luz <luzmaximilian@gmail.com>
  750. Date: Sat, 30 Dec 2023 18:21:12 +0100
  751. Subject: [PATCH] platform/surface: aggregator_registry: Add support for
  752. thermal sensors on the Surface Pro 9
  753. The Surface Pro 9 has thermal sensors connected via the Surface
  754. Aggregator Module. Add a device node to support those.
  755. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  756. Patchset: surface-sam
  757. ---
  758. drivers/platform/surface/surface_aggregator_registry.c | 7 +++++++
  759. 1 file changed, 7 insertions(+)
  760. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  761. index b0db25886c99..797802d16f31 100644
  762. --- a/drivers/platform/surface/surface_aggregator_registry.c
  763. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  764. @@ -74,6 +74,12 @@ static const struct software_node ssam_node_tmp_pprof = {
  765. .parent = &ssam_node_root,
  766. };
  767. +/* Thermal sensors. */
  768. +static const struct software_node ssam_node_tmp_sensors = {
  769. + .name = "ssam:01:03:01:00:02",
  770. + .parent = &ssam_node_root,
  771. +};
  772. +
  773. /* Fan speed function. */
  774. static const struct software_node ssam_node_fan_speed = {
  775. .name = "ssam:01:05:01:01:01",
  776. @@ -325,6 +331,7 @@ static const struct software_node *ssam_node_group_sp9[] = {
  777. &ssam_node_bat_ac,
  778. &ssam_node_bat_main,
  779. &ssam_node_tmp_pprof,
  780. + &ssam_node_tmp_sensors,
  781. &ssam_node_fan_speed,
  782. &ssam_node_pos_tablet_switch,
  783. &ssam_node_hid_kip_keyboard,
  784. --
  785. 2.44.0
  786. From b4fd0fc401f445f3946a53e94a94d8bc8386a91f Mon Sep 17 00:00:00 2001
  787. From: Ivor Wanders <ivor@iwanders.net>
  788. Date: Sat, 16 Dec 2023 15:56:39 -0500
  789. Subject: [PATCH] platform/surface: platform_profile: add fan profile switching
  790. Change naming from tmp to platform profile to clarify the module may
  791. interact with both the TMP and FAN subystems. Add functionality that
  792. switches the fan profile when the platform profile is changed.
  793. Signed-off-by: Ivor Wanders <ivor@iwanders.net>
  794. ---
  795. .../surface/surface_aggregator_registry.c | 38 +++++---
  796. .../surface/surface_platform_profile.c | 86 ++++++++++++++++---
  797. 2 files changed, 100 insertions(+), 24 deletions(-)
  798. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  799. index 797802d16f31..7540d8736664 100644
  800. --- a/drivers/platform/surface/surface_aggregator_registry.c
  801. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  802. @@ -68,8 +68,8 @@ static const struct software_node ssam_node_bat_sb3base = {
  803. .parent = &ssam_node_hub_base,
  804. };
  805. -/* Platform profile / performance-mode device. */
  806. -static const struct software_node ssam_node_tmp_pprof = {
  807. +/* Platform profile / performance-mode device without a fan. */
  808. +static const struct software_node ssam_node_tmp_perf_profile = {
  809. .name = "ssam:01:03:01:00:01",
  810. .parent = &ssam_node_root,
  811. };
  812. @@ -86,6 +86,20 @@ static const struct software_node ssam_node_fan_speed = {
  813. .parent = &ssam_node_root,
  814. };
  815. +/* Platform profile / performance-mode device with a fan, such that
  816. + * the fan controller profile can also be switched.
  817. + */
  818. +static const struct property_entry ssam_node_tmp_perf_profile_has_fan[] = {
  819. + PROPERTY_ENTRY_BOOL("has_fan"),
  820. + { }
  821. +};
  822. +
  823. +static const struct software_node ssam_node_tmp_perf_profile_with_fan = {
  824. + .name = "ssam:01:03:01:00:01",
  825. + .parent = &ssam_node_root,
  826. + .properties = ssam_node_tmp_perf_profile_has_fan,
  827. +};
  828. +
  829. /* Tablet-mode switch via KIP subsystem. */
  830. static const struct software_node ssam_node_kip_tablet_switch = {
  831. .name = "ssam:01:0e:01:00:01",
  832. @@ -214,7 +228,7 @@ static const struct software_node ssam_node_pos_tablet_switch = {
  833. */
  834. static const struct software_node *ssam_node_group_gen5[] = {
  835. &ssam_node_root,
  836. - &ssam_node_tmp_pprof,
  837. + &ssam_node_tmp_perf_profile,
  838. NULL,
  839. };
  840. @@ -225,7 +239,7 @@ static const struct software_node *ssam_node_group_sb3[] = {
  841. &ssam_node_bat_ac,
  842. &ssam_node_bat_main,
  843. &ssam_node_bat_sb3base,
  844. - &ssam_node_tmp_pprof,
  845. + &ssam_node_tmp_perf_profile,
  846. &ssam_node_bas_dtx,
  847. &ssam_node_hid_base_keyboard,
  848. &ssam_node_hid_base_touchpad,
  849. @@ -239,7 +253,7 @@ static const struct software_node *ssam_node_group_sl3[] = {
  850. &ssam_node_root,
  851. &ssam_node_bat_ac,
  852. &ssam_node_bat_main,
  853. - &ssam_node_tmp_pprof,
  854. + &ssam_node_tmp_perf_profile,
  855. &ssam_node_hid_main_keyboard,
  856. &ssam_node_hid_main_touchpad,
  857. &ssam_node_hid_main_iid5,
  858. @@ -251,7 +265,7 @@ static const struct software_node *ssam_node_group_sl5[] = {
  859. &ssam_node_root,
  860. &ssam_node_bat_ac,
  861. &ssam_node_bat_main,
  862. - &ssam_node_tmp_pprof,
  863. + &ssam_node_tmp_perf_profile,
  864. &ssam_node_hid_main_keyboard,
  865. &ssam_node_hid_main_touchpad,
  866. &ssam_node_hid_main_iid5,
  867. @@ -264,7 +278,7 @@ static const struct software_node *ssam_node_group_sls1[] = {
  868. &ssam_node_root,
  869. &ssam_node_bat_ac,
  870. &ssam_node_bat_main,
  871. - &ssam_node_tmp_pprof,
  872. + &ssam_node_tmp_perf_profile,
  873. &ssam_node_pos_tablet_switch,
  874. &ssam_node_hid_sam_keyboard,
  875. &ssam_node_hid_sam_penstash,
  876. @@ -280,7 +294,7 @@ static const struct software_node *ssam_node_group_sls2[] = {
  877. &ssam_node_root,
  878. &ssam_node_bat_ac,
  879. &ssam_node_bat_main,
  880. - &ssam_node_tmp_pprof,
  881. + &ssam_node_tmp_perf_profile,
  882. &ssam_node_pos_tablet_switch,
  883. &ssam_node_hid_sam_keyboard,
  884. &ssam_node_hid_sam_penstash,
  885. @@ -294,7 +308,7 @@ static const struct software_node *ssam_node_group_slg1[] = {
  886. &ssam_node_root,
  887. &ssam_node_bat_ac,
  888. &ssam_node_bat_main,
  889. - &ssam_node_tmp_pprof,
  890. + &ssam_node_tmp_perf_profile,
  891. NULL,
  892. };
  893. @@ -303,7 +317,7 @@ static const struct software_node *ssam_node_group_sp7[] = {
  894. &ssam_node_root,
  895. &ssam_node_bat_ac,
  896. &ssam_node_bat_main,
  897. - &ssam_node_tmp_pprof,
  898. + &ssam_node_tmp_perf_profile,
  899. NULL,
  900. };
  901. @@ -313,7 +327,7 @@ static const struct software_node *ssam_node_group_sp8[] = {
  902. &ssam_node_hub_kip,
  903. &ssam_node_bat_ac,
  904. &ssam_node_bat_main,
  905. - &ssam_node_tmp_pprof,
  906. + &ssam_node_tmp_perf_profile,
  907. &ssam_node_kip_tablet_switch,
  908. &ssam_node_hid_kip_keyboard,
  909. &ssam_node_hid_kip_penstash,
  910. @@ -330,7 +344,7 @@ static const struct software_node *ssam_node_group_sp9[] = {
  911. &ssam_node_hub_kip,
  912. &ssam_node_bat_ac,
  913. &ssam_node_bat_main,
  914. - &ssam_node_tmp_pprof,
  915. + &ssam_node_tmp_perf_profile_with_fan,
  916. &ssam_node_tmp_sensors,
  917. &ssam_node_fan_speed,
  918. &ssam_node_pos_tablet_switch,
  919. diff --git a/drivers/platform/surface/surface_platform_profile.c b/drivers/platform/surface/surface_platform_profile.c
  920. index a5a3941b3f43..e54d0a8f7daa 100644
  921. --- a/drivers/platform/surface/surface_platform_profile.c
  922. +++ b/drivers/platform/surface/surface_platform_profile.c
  923. @@ -1,7 +1,7 @@
  924. // SPDX-License-Identifier: GPL-2.0+
  925. /*
  926. * Surface Platform Profile / Performance Mode driver for Surface System
  927. - * Aggregator Module (thermal subsystem).
  928. + * Aggregator Module (thermal and fan subsystem).
  929. *
  930. * Copyright (C) 2021-2022 Maximilian Luz <luzmaximilian@gmail.com>
  931. */
  932. @@ -14,6 +14,7 @@
  933. #include <linux/surface_aggregator/device.h>
  934. +// Enum for the platform performance profile sent to the TMP module.
  935. enum ssam_tmp_profile {
  936. SSAM_TMP_PROFILE_NORMAL = 1,
  937. SSAM_TMP_PROFILE_BATTERY_SAVER = 2,
  938. @@ -21,15 +22,26 @@ enum ssam_tmp_profile {
  939. SSAM_TMP_PROFILE_BEST_PERFORMANCE = 4,
  940. };
  941. +// Enum for the fan profile sent to the FAN module. This fan profile is
  942. +// only sent to the EC if the 'has_fan' property is set. The integers are
  943. +// not a typo, they differ from the performance profile indices.
  944. +enum ssam_fan_profile {
  945. + SSAM_FAN_PROFILE_NORMAL = 2,
  946. + SSAM_FAN_PROFILE_BATTERY_SAVER = 1,
  947. + SSAM_FAN_PROFILE_BETTER_PERFORMANCE = 3,
  948. + SSAM_FAN_PROFILE_BEST_PERFORMANCE = 4,
  949. +};
  950. +
  951. struct ssam_tmp_profile_info {
  952. __le32 profile;
  953. __le16 unknown1;
  954. __le16 unknown2;
  955. } __packed;
  956. -struct ssam_tmp_profile_device {
  957. +struct ssam_platform_profile_device {
  958. struct ssam_device *sdev;
  959. struct platform_profile_handler handler;
  960. + bool has_fan;
  961. };
  962. SSAM_DEFINE_SYNC_REQUEST_CL_R(__ssam_tmp_profile_get, struct ssam_tmp_profile_info, {
  963. @@ -42,6 +54,13 @@ SSAM_DEFINE_SYNC_REQUEST_CL_W(__ssam_tmp_profile_set, __le32, {
  964. .command_id = 0x03,
  965. });
  966. +SSAM_DEFINE_SYNC_REQUEST_W(__ssam_fan_profile_set, char, {
  967. + .target_category = SSAM_SSH_TC_FAN,
  968. + .target_id = SSAM_SSH_TID_SAM,
  969. + .command_id = 0x0e,
  970. + .instance_id = 0x01,
  971. +});
  972. +
  973. static int ssam_tmp_profile_get(struct ssam_device *sdev, enum ssam_tmp_profile *p)
  974. {
  975. struct ssam_tmp_profile_info info;
  976. @@ -62,7 +81,14 @@ static int ssam_tmp_profile_set(struct ssam_device *sdev, enum ssam_tmp_profile
  977. return ssam_retry(__ssam_tmp_profile_set, sdev, &profile_le);
  978. }
  979. -static int convert_ssam_to_profile(struct ssam_device *sdev, enum ssam_tmp_profile p)
  980. +static int ssam_fan_profile_set(struct ssam_device *sdev, enum ssam_fan_profile p)
  981. +{
  982. + char profile = p;
  983. +
  984. + return ssam_retry(__ssam_fan_profile_set, sdev->ctrl, &profile);
  985. +}
  986. +
  987. +static int convert_ssam_tmp_to_profile(struct ssam_device *sdev, enum ssam_tmp_profile p)
  988. {
  989. switch (p) {
  990. case SSAM_TMP_PROFILE_NORMAL:
  991. @@ -83,7 +109,8 @@ static int convert_ssam_to_profile(struct ssam_device *sdev, enum ssam_tmp_profi
  992. }
  993. }
  994. -static int convert_profile_to_ssam(struct ssam_device *sdev, enum platform_profile_option p)
  995. +
  996. +static int convert_profile_to_ssam_tmp(struct ssam_device *sdev, enum platform_profile_option p)
  997. {
  998. switch (p) {
  999. case PLATFORM_PROFILE_LOW_POWER:
  1000. @@ -105,20 +132,42 @@ static int convert_profile_to_ssam(struct ssam_device *sdev, enum platform_profi
  1001. }
  1002. }
  1003. +static int convert_profile_to_ssam_fan(struct ssam_device *sdev, enum platform_profile_option p)
  1004. +{
  1005. + switch (p) {
  1006. + case PLATFORM_PROFILE_LOW_POWER:
  1007. + return SSAM_FAN_PROFILE_BATTERY_SAVER;
  1008. +
  1009. + case PLATFORM_PROFILE_BALANCED:
  1010. + return SSAM_FAN_PROFILE_NORMAL;
  1011. +
  1012. + case PLATFORM_PROFILE_BALANCED_PERFORMANCE:
  1013. + return SSAM_FAN_PROFILE_BETTER_PERFORMANCE;
  1014. +
  1015. + case PLATFORM_PROFILE_PERFORMANCE:
  1016. + return SSAM_FAN_PROFILE_BEST_PERFORMANCE;
  1017. +
  1018. + default:
  1019. + /* This should have already been caught by platform_profile_store(). */
  1020. + WARN(true, "unsupported platform profile");
  1021. + return -EOPNOTSUPP;
  1022. + }
  1023. +}
  1024. +
  1025. static int ssam_platform_profile_get(struct platform_profile_handler *pprof,
  1026. enum platform_profile_option *profile)
  1027. {
  1028. - struct ssam_tmp_profile_device *tpd;
  1029. + struct ssam_platform_profile_device *tpd;
  1030. enum ssam_tmp_profile tp;
  1031. int status;
  1032. - tpd = container_of(pprof, struct ssam_tmp_profile_device, handler);
  1033. + tpd = container_of(pprof, struct ssam_platform_profile_device, handler);
  1034. status = ssam_tmp_profile_get(tpd->sdev, &tp);
  1035. if (status)
  1036. return status;
  1037. - status = convert_ssam_to_profile(tpd->sdev, tp);
  1038. + status = convert_ssam_tmp_to_profile(tpd->sdev, tp);
  1039. if (status < 0)
  1040. return status;
  1041. @@ -129,21 +178,32 @@ static int ssam_platform_profile_get(struct platform_profile_handler *pprof,
  1042. static int ssam_platform_profile_set(struct platform_profile_handler *pprof,
  1043. enum platform_profile_option profile)
  1044. {
  1045. - struct ssam_tmp_profile_device *tpd;
  1046. + struct ssam_platform_profile_device *tpd;
  1047. int tp;
  1048. - tpd = container_of(pprof, struct ssam_tmp_profile_device, handler);
  1049. + tpd = container_of(pprof, struct ssam_platform_profile_device, handler);
  1050. +
  1051. + tp = convert_profile_to_ssam_tmp(tpd->sdev, profile);
  1052. + if (tp < 0)
  1053. + return tp;
  1054. - tp = convert_profile_to_ssam(tpd->sdev, profile);
  1055. + tp = ssam_tmp_profile_set(tpd->sdev, tp);
  1056. if (tp < 0)
  1057. return tp;
  1058. - return ssam_tmp_profile_set(tpd->sdev, tp);
  1059. + if (tpd->has_fan) {
  1060. + tp = convert_profile_to_ssam_fan(tpd->sdev, profile);
  1061. + if (tp < 0)
  1062. + return tp;
  1063. + tp = ssam_fan_profile_set(tpd->sdev, tp);
  1064. + }
  1065. +
  1066. + return tp;
  1067. }
  1068. static int surface_platform_profile_probe(struct ssam_device *sdev)
  1069. {
  1070. - struct ssam_tmp_profile_device *tpd;
  1071. + struct ssam_platform_profile_device *tpd;
  1072. tpd = devm_kzalloc(&sdev->dev, sizeof(*tpd), GFP_KERNEL);
  1073. if (!tpd)
  1074. @@ -154,6 +214,8 @@ static int surface_platform_profile_probe(struct ssam_device *sdev)
  1075. tpd->handler.profile_get = ssam_platform_profile_get;
  1076. tpd->handler.profile_set = ssam_platform_profile_set;
  1077. + tpd->has_fan = device_property_read_bool(&sdev->dev, "has_fan");
  1078. +
  1079. set_bit(PLATFORM_PROFILE_LOW_POWER, tpd->handler.choices);
  1080. set_bit(PLATFORM_PROFILE_BALANCED, tpd->handler.choices);
  1081. set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, tpd->handler.choices);
  1082. --
  1083. 2.44.0