Message ID | 20240330112409.3402943-2-luzmaximilian@gmail.com (mailing list archive) |
---|---|
State | Changes Requested |
Headers | show |
Series | Add thermal sensor driver for Surface Aggregator | expand |
On 3/30/24 04:24, Maximilian Luz wrote: > Some of the newer Microsoft Surface devices (such as the Surface Book > 3 and Pro 9) have thermal sensors connected via the Surface Aggregator > Module (the embedded controller on those devices). Add a basic driver > to read out the temperature values of those sensors. > > Link: https://github.com/linux-surface/surface-aggregator-module/issues/59 > Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com> I very much dislike the idea of having multiple drivers for hardware monitoring on the same system. Please explain in detail why this and the fan driver for the same system need separate drivers. I'll also very much want to know if we will see submissions for separate voltage, current, power, energy, humidity, and/or other hardware monitoring entities for the same system later on. Guenter
On 3/30/24 12:58, Guenter Roeck wrote: > On 3/30/24 04:24, Maximilian Luz wrote: >> Some of the newer Microsoft Surface devices (such as the Surface Book >> 3 and Pro 9) have thermal sensors connected via the Surface Aggregator >> Module (the embedded controller on those devices). Add a basic driver >> to read out the temperature values of those sensors. >> >> Link: https://github.com/linux-surface/surface-aggregator-module/issues/59 >> Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com> > > I very much dislike the idea of having multiple drivers for hardware > monitoring on the same system. Please explain in detail why this and > the fan driver for the same system need separate drivers. > > I'll also very much want to know if we will see submissions for separate > voltage, current, power, energy, humidity, and/or other hardware monitoring > entities for the same system later on. The Surface Aggregator EC is not really a single device, but rather a collection of subsystems. For example, there's one for the battery, one for thermal sensors, and a separate one for the fan. Not all subsystems are present on all devices with that EC, so we have modeled them as separate subdevices of the parent EC controller. This makes it quite a bit easier to maintain. Especially, since I haven't found any reliable way to auto-detect the active/supported subsystems. For example: The Surface Book 3 has thermal sensors that can be accessed via this driver as well as a fan. As far as I know, however, the fan subsystem has been introduced later and the Surface Book 3 doesn't support that yet. So there's (as far as I know) no fan-monitoring support. Trying to access that will fail with a timeout. For that reason (but not specifically for that device), we have introduced the split into subystem devices, which are maunally registered in surface_aggregator_registry.c based on what we know the device actually supports. Further, the devices created for these subsystems also act as a binding mechanism to the subsystem, speficying the subsystem ID/category used for making requests to it. For example, this driver probes for SSAM_SDEV(TMP, SAM, 0x00, 0x02) meaning it looks for a device of the TMP subsystem on the SAM target ID (which can be seen as a bus number) with instance 0 and function 2. This (in particular subsystem ID and target ID) are directly used when making requests to the EC. So if we find out down the line that temperature sensors can be accessed on target ID KIP in addition to SAM, it's as easy as adding a new device match to the driver. I believe that this would be more difficult if the driver is merged together: Doing so would require us to figure out what's present and what we can or should access inside of the driver (instead of via the already established registry). So it would either require us to do a certain amount of hardcoding and if/else branches or we would have to introduce a bunch of device properties and a meta-device just to bundle all monitoring-related subsystems together, and again use a bunch of if/else branches... And in both cases, the direct subsystem binding originally intended in the device structure of the Surface Aggregator bus goes out of the window. So, in my opinion at least, having separate smaller but specific drivers and leaving that "logic" to the registry driver makes this much more maintainable. Regarding other monitoring entities: In short, I don't know. I am not aware of any other (current/power/...) monitoring capabilities of the EC right now, but I can't guarantee that MS won't introduce a new subsystem for those down the line (or that there already is one and we just don't know about it). At which point, it will quite likely only be supported on some (probably newer) devices again. Best regards, Max
Hi, On 3/30/24 1:58 PM, Maximilian Luz wrote: > On 3/30/24 12:58, Guenter Roeck wrote: >> On 3/30/24 04:24, Maximilian Luz wrote: >>> Some of the newer Microsoft Surface devices (such as the Surface Book >>> 3 and Pro 9) have thermal sensors connected via the Surface Aggregator >>> Module (the embedded controller on those devices). Add a basic driver >>> to read out the temperature values of those sensors. >>> >>> Link: https://github.com/linux-surface/surface-aggregator-module/issues/59 >>> Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com> >> >> I very much dislike the idea of having multiple drivers for hardware >> monitoring on the same system. Please explain in detail why this and >> the fan driver for the same system need separate drivers. >> >> I'll also very much want to know if we will see submissions for separate >> voltage, current, power, energy, humidity, and/or other hardware monitoring >> entities for the same system later on. > > The Surface Aggregator EC is not really a single device, but rather a > collection of subsystems. For example, there's one for the battery, one > for thermal sensors, and a separate one for the fan. Not all subsystems > are present on all devices with that EC, so we have modeled them as > separate subdevices of the parent EC controller. This makes it quite a > bit easier to maintain. Especially, since I haven't found any reliable > way to auto-detect the active/supported subsystems. > > For example: The Surface Book 3 has thermal sensors that can be accessed > via this driver as well as a fan. As far as I know, however, the fan > subsystem has been introduced later and the Surface Book 3 doesn't > support that yet. So there's (as far as I know) no fan-monitoring > support. Trying to access that will fail with a timeout. For that reason > (but not specifically for that device), we have introduced the split > into subystem devices, which are maunally registered in > surface_aggregator_registry.c based on what we know the device actually > supports. > > Further, the devices created for these subsystems also act as a binding > mechanism to the subsystem, speficying the subsystem ID/category used > for making requests to it. For example, this driver probes for > > SSAM_SDEV(TMP, SAM, 0x00, 0x02) > > meaning it looks for a device of the TMP subsystem on the SAM target ID > (which can be seen as a bus number) with instance 0 and function 2. This > (in particular subsystem ID and target ID) are directly used when making > requests to the EC. So if we find out down the line that temperature > sensors can be accessed on target ID KIP in addition to SAM, it's as easy > as adding a new device match to the driver. <snip> Right this is all working as designed, it is just that Microsoft has gone a pretty custom route with the Surface devices. Guenter another way of looking at this is if there were 2 ACPI devices describing the fan vs the temperature monitoring capabilities that too would result in 2 drivers even though the underlying ACPI AML code might end up talking to the same monitoring-IC in the end. I'll go and merge patch 3/3 of this series. I'll leave merging 1/3 and 2/3 up to the hwmon subsystem of course. Regards, Hans
Hi, On 3/30/24 12:24 PM, Maximilian Luz wrote: > Some of the newer Microsoft Surface devices (such as the Surface Book > 3 and Pro 9) have thermal sensors connected via the Surface Aggregator > Module (the embedded controller on those devices). Add a basic driver > to read out the temperature values of those sensors. > > Link: https://github.com/linux-surface/surface-aggregator-module/issues/59 > Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com> Thanks, patch looks good to me: Reviewed-by: Hans de Goede <hdegoede@redhat.com> Regards, Hans > --- > MAINTAINERS | 6 ++ > drivers/hwmon/Kconfig | 10 +++ > drivers/hwmon/Makefile | 1 + > drivers/hwmon/surface_temp.c | 165 +++++++++++++++++++++++++++++++++++ > 4 files changed, 182 insertions(+) > create mode 100644 drivers/hwmon/surface_temp.c > > diff --git a/MAINTAINERS b/MAINTAINERS > index d36c19c1bf811..bc5bc418ed479 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -14738,6 +14738,12 @@ S: Maintained > F: Documentation/hwmon/surface_fan.rst > F: drivers/hwmon/surface_fan.c > > +MICROSOFT SURFACE SENSOR THERMAL DRIVER > +M: Maximilian Luz <luzmaximilian@gmail.com> > +L: linux-hwmon@vger.kernel.org > +S: Maintained > +F: drivers/hwmon/surface_temp.c > + > MICROSOFT SURFACE GPE LID SUPPORT DRIVER > M: Maximilian Luz <luzmaximilian@gmail.com> > L: platform-driver-x86@vger.kernel.org > diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig > index 83945397b6eb1..338ef73c96a3a 100644 > --- a/drivers/hwmon/Kconfig > +++ b/drivers/hwmon/Kconfig > @@ -2070,6 +2070,16 @@ config SENSORS_SURFACE_FAN > > Select M or Y here, if you want to be able to read the fan's speed. > > +config SENSORS_SURFACE_TEMP > + tristate "Microsoft Surface Thermal Sensor Driver" > + depends on SURFACE_AGGREGATOR > + help > + Driver for monitoring thermal sensors connected via the Surface > + Aggregator Module (embedded controller) on Microsoft Surface devices. > + > + This driver can also be built as a module. If so, the module > + will be called surface_temp. > + > config SENSORS_ADC128D818 > tristate "Texas Instruments ADC128D818" > depends on I2C > diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile > index 5c31808f6378d..de8bc99719e63 100644 > --- a/drivers/hwmon/Makefile > +++ b/drivers/hwmon/Makefile > @@ -208,6 +208,7 @@ obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o > obj-$(CONFIG_SENSORS_SPARX5) += sparx5-temp.o > obj-$(CONFIG_SENSORS_STTS751) += stts751.o > obj-$(CONFIG_SENSORS_SURFACE_FAN)+= surface_fan.o > +obj-$(CONFIG_SENSORS_SURFACE_TEMP)+= surface_temp.o > obj-$(CONFIG_SENSORS_SY7636A) += sy7636a-hwmon.o > obj-$(CONFIG_SENSORS_AMC6821) += amc6821.o > obj-$(CONFIG_SENSORS_TC74) += tc74.o > diff --git a/drivers/hwmon/surface_temp.c b/drivers/hwmon/surface_temp.c > new file mode 100644 > index 0000000000000..48c3e826713f6 > --- /dev/null > +++ b/drivers/hwmon/surface_temp.c > @@ -0,0 +1,165 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * Thermal sensor subsystem driver for Surface System Aggregator Module (SSAM). > + * > + * Copyright (C) 2022-2023 Maximilian Luz <luzmaximilian@gmail.com> > + */ > + > +#include <linux/bitops.h> > +#include <linux/hwmon.h> > +#include <linux/kernel.h> > +#include <linux/module.h> > +#include <linux/types.h> > + > +#include <linux/surface_aggregator/controller.h> > +#include <linux/surface_aggregator/device.h> > + > + > +/* -- SAM interface. -------------------------------------------------------- */ > + > +SSAM_DEFINE_SYNC_REQUEST_CL_R(__ssam_tmp_get_available_sensors, __le16, { > + .target_category = SSAM_SSH_TC_TMP, > + .command_id = 0x04, > +}); > + > +SSAM_DEFINE_SYNC_REQUEST_MD_R(__ssam_tmp_get_temperature, __le16, { > + .target_category = SSAM_SSH_TC_TMP, > + .command_id = 0x01, > +}); > + > +static int ssam_tmp_get_available_sensors(struct ssam_device *sdev, s16 *sensors) > +{ > + __le16 sensors_le; > + int status; > + > + status = __ssam_tmp_get_available_sensors(sdev, &sensors_le); > + if (status) > + return status; > + > + *sensors = le16_to_cpu(sensors_le); > + return 0; > +} > + > +static int ssam_tmp_get_temperature(struct ssam_device *sdev, u8 iid, long *temperature) > +{ > + __le16 temp_le; > + int status; > + > + status = __ssam_tmp_get_temperature(sdev->ctrl, sdev->uid.target, iid, &temp_le); > + if (status) > + return status; > + > + /* Convert 1/10 °K to 1/1000 °C */ > + *temperature = (le16_to_cpu(temp_le) - 2731) * 100L; > + return 0; > +} > + > + > +/* -- Driver.---------------------------------------------------------------- */ > + > +struct ssam_temp { > + struct ssam_device *sdev; > + s16 sensors; > +}; > + > +static umode_t ssam_temp_hwmon_is_visible(const void *data, > + enum hwmon_sensor_types type, > + u32 attr, int channel) > +{ > + const struct ssam_temp *ssam_temp = data; > + > + if (!(ssam_temp->sensors & BIT(channel))) > + return 0; > + > + return 0444; > +} > + > +static int ssam_temp_hwmon_read(struct device *dev, > + enum hwmon_sensor_types type, > + u32 attr, int channel, long *value) > +{ > + const struct ssam_temp *ssam_temp = dev_get_drvdata(dev); > + > + return ssam_tmp_get_temperature(ssam_temp->sdev, channel + 1, value); > +} > + > +static const struct hwmon_channel_info * const ssam_temp_hwmon_info[] = { > + HWMON_CHANNEL_INFO(chip, > + HWMON_C_REGISTER_TZ), > + /* We have at most 16 thermal sensor channels. */ > + HWMON_CHANNEL_INFO(temp, > + HWMON_T_INPUT, > + HWMON_T_INPUT, > + HWMON_T_INPUT, > + HWMON_T_INPUT, > + HWMON_T_INPUT, > + HWMON_T_INPUT, > + HWMON_T_INPUT, > + HWMON_T_INPUT, > + HWMON_T_INPUT, > + HWMON_T_INPUT, > + HWMON_T_INPUT, > + HWMON_T_INPUT, > + HWMON_T_INPUT, > + HWMON_T_INPUT, > + HWMON_T_INPUT, > + HWMON_T_INPUT), > + NULL > +}; > + > +static const struct hwmon_ops ssam_temp_hwmon_ops = { > + .is_visible = ssam_temp_hwmon_is_visible, > + .read = ssam_temp_hwmon_read, > +}; > + > +static const struct hwmon_chip_info ssam_temp_hwmon_chip_info = { > + .ops = &ssam_temp_hwmon_ops, > + .info = ssam_temp_hwmon_info, > +}; > + > +static int ssam_temp_probe(struct ssam_device *sdev) > +{ > + struct ssam_temp *ssam_temp; > + struct device *hwmon_dev; > + s16 sensors; > + int status; > + > + status = ssam_tmp_get_available_sensors(sdev, &sensors); > + if (status) > + return status; > + > + ssam_temp = devm_kzalloc(&sdev->dev, sizeof(*ssam_temp), GFP_KERNEL); > + if (!ssam_temp) > + return -ENOMEM; > + > + ssam_temp->sdev = sdev; > + ssam_temp->sensors = sensors; > + > + hwmon_dev = devm_hwmon_device_register_with_info(&sdev->dev, > + "surface_thermal", ssam_temp, &ssam_temp_hwmon_chip_info, > + NULL); > + if (IS_ERR(hwmon_dev)) > + return PTR_ERR(hwmon_dev); > + > + return 0; > +} > + > +static const struct ssam_device_id ssam_temp_match[] = { > + { SSAM_SDEV(TMP, SAM, 0x00, 0x02) }, > + { }, > +}; > +MODULE_DEVICE_TABLE(ssam, ssam_temp_match); > + > +static struct ssam_device_driver ssam_temp = { > + .probe = ssam_temp_probe, > + .match_table = ssam_temp_match, > + .driver = { > + .name = "surface_temp", > + .probe_type = PROBE_PREFER_ASYNCHRONOUS, > + }, > +}; > +module_ssam_device_driver(ssam_temp); > + > +MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>"); > +MODULE_DESCRIPTION("Thermal sensor subsystem driver for Surface System Aggregator Module"); > +MODULE_LICENSE("GPL");
On Sat, Mar 30, 2024 at 12:24:00PM +0100, Maximilian Luz wrote: > Some of the newer Microsoft Surface devices (such as the Surface Book > 3 and Pro 9) have thermal sensors connected via the Surface Aggregator > Module (the embedded controller on those devices). Add a basic driver > to read out the temperature values of those sensors. > > Link: https://github.com/linux-surface/surface-aggregator-module/issues/59 > Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com> > Reviewed-by: Hans de Goede <hdegoede@redhat.com> CHECK: Please don't use multiple blank lines #189: FILE: drivers/hwmon/surface_temp.c:17: + + CHECK: Please don't use multiple blank lines #229: FILE: drivers/hwmon/surface_temp.c:57: + + CHECK: Alignment should match open parenthesis #311: FILE: drivers/hwmon/surface_temp.c:139: + hwmon_dev = devm_hwmon_device_register_with_info(&sdev->dev, + "surface_thermal", ssam_temp, &ssam_temp_hwmon_chip_info, Please fix. Guenter
On Sat, Mar 30, 2024 at 12:24:00PM +0100, Maximilian Luz wrote: > Some of the newer Microsoft Surface devices (such as the Surface Book > 3 and Pro 9) have thermal sensors connected via the Surface Aggregator > Module (the embedded controller on those devices). Add a basic driver > to read out the temperature values of those sensors. > > Link: https://github.com/linux-surface/surface-aggregator-module/issues/59 > Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com> > Reviewed-by: Hans de Goede <hdegoede@redhat.com> > --- [ ... ] > + hwmon_dev = devm_hwmon_device_register_with_info(&sdev->dev, > + "surface_thermal", ssam_temp, &ssam_temp_hwmon_chip_info, > + NULL); > + if (IS_ERR(hwmon_dev)) > + return PTR_ERR(hwmon_dev); > + > + return 0; return PTR_ERR_OR_ZERO(hwmon_dev);
On 4/16/24 3:27 PM, Guenter Roeck wrote: > On Sat, Mar 30, 2024 at 12:24:00PM +0100, Maximilian Luz wrote: >> Some of the newer Microsoft Surface devices (such as the Surface Book >> 3 and Pro 9) have thermal sensors connected via the Surface Aggregator >> Module (the embedded controller on those devices). Add a basic driver >> to read out the temperature values of those sensors. >> >> Link: https://github.com/linux-surface/surface-aggregator-module/issues/59 >> Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com> >> Reviewed-by: Hans de Goede <hdegoede@redhat.com> >> --- > [ ... ] >> + hwmon_dev = devm_hwmon_device_register_with_info(&sdev->dev, >> + "surface_thermal", ssam_temp, &ssam_temp_hwmon_chip_info, >> + NULL); >> + if (IS_ERR(hwmon_dev)) >> + return PTR_ERR(hwmon_dev); >> + >> + return 0; > > return PTR_ERR_OR_ZERO(hwmon_dev); ACK. Will fix this and the blank lines. Thanks, Max
diff --git a/MAINTAINERS b/MAINTAINERS index d36c19c1bf811..bc5bc418ed479 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14738,6 +14738,12 @@ S: Maintained F: Documentation/hwmon/surface_fan.rst F: drivers/hwmon/surface_fan.c +MICROSOFT SURFACE SENSOR THERMAL DRIVER +M: Maximilian Luz <luzmaximilian@gmail.com> +L: linux-hwmon@vger.kernel.org +S: Maintained +F: drivers/hwmon/surface_temp.c + MICROSOFT SURFACE GPE LID SUPPORT DRIVER M: Maximilian Luz <luzmaximilian@gmail.com> L: platform-driver-x86@vger.kernel.org diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 83945397b6eb1..338ef73c96a3a 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -2070,6 +2070,16 @@ config SENSORS_SURFACE_FAN Select M or Y here, if you want to be able to read the fan's speed. +config SENSORS_SURFACE_TEMP + tristate "Microsoft Surface Thermal Sensor Driver" + depends on SURFACE_AGGREGATOR + help + Driver for monitoring thermal sensors connected via the Surface + Aggregator Module (embedded controller) on Microsoft Surface devices. + + This driver can also be built as a module. If so, the module + will be called surface_temp. + config SENSORS_ADC128D818 tristate "Texas Instruments ADC128D818" depends on I2C diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 5c31808f6378d..de8bc99719e63 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -208,6 +208,7 @@ obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o obj-$(CONFIG_SENSORS_SPARX5) += sparx5-temp.o obj-$(CONFIG_SENSORS_STTS751) += stts751.o obj-$(CONFIG_SENSORS_SURFACE_FAN)+= surface_fan.o +obj-$(CONFIG_SENSORS_SURFACE_TEMP)+= surface_temp.o obj-$(CONFIG_SENSORS_SY7636A) += sy7636a-hwmon.o obj-$(CONFIG_SENSORS_AMC6821) += amc6821.o obj-$(CONFIG_SENSORS_TC74) += tc74.o diff --git a/drivers/hwmon/surface_temp.c b/drivers/hwmon/surface_temp.c new file mode 100644 index 0000000000000..48c3e826713f6 --- /dev/null +++ b/drivers/hwmon/surface_temp.c @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Thermal sensor subsystem driver for Surface System Aggregator Module (SSAM). + * + * Copyright (C) 2022-2023 Maximilian Luz <luzmaximilian@gmail.com> + */ + +#include <linux/bitops.h> +#include <linux/hwmon.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/types.h> + +#include <linux/surface_aggregator/controller.h> +#include <linux/surface_aggregator/device.h> + + +/* -- SAM interface. -------------------------------------------------------- */ + +SSAM_DEFINE_SYNC_REQUEST_CL_R(__ssam_tmp_get_available_sensors, __le16, { + .target_category = SSAM_SSH_TC_TMP, + .command_id = 0x04, +}); + +SSAM_DEFINE_SYNC_REQUEST_MD_R(__ssam_tmp_get_temperature, __le16, { + .target_category = SSAM_SSH_TC_TMP, + .command_id = 0x01, +}); + +static int ssam_tmp_get_available_sensors(struct ssam_device *sdev, s16 *sensors) +{ + __le16 sensors_le; + int status; + + status = __ssam_tmp_get_available_sensors(sdev, &sensors_le); + if (status) + return status; + + *sensors = le16_to_cpu(sensors_le); + return 0; +} + +static int ssam_tmp_get_temperature(struct ssam_device *sdev, u8 iid, long *temperature) +{ + __le16 temp_le; + int status; + + status = __ssam_tmp_get_temperature(sdev->ctrl, sdev->uid.target, iid, &temp_le); + if (status) + return status; + + /* Convert 1/10 °K to 1/1000 °C */ + *temperature = (le16_to_cpu(temp_le) - 2731) * 100L; + return 0; +} + + +/* -- Driver.---------------------------------------------------------------- */ + +struct ssam_temp { + struct ssam_device *sdev; + s16 sensors; +}; + +static umode_t ssam_temp_hwmon_is_visible(const void *data, + enum hwmon_sensor_types type, + u32 attr, int channel) +{ + const struct ssam_temp *ssam_temp = data; + + if (!(ssam_temp->sensors & BIT(channel))) + return 0; + + return 0444; +} + +static int ssam_temp_hwmon_read(struct device *dev, + enum hwmon_sensor_types type, + u32 attr, int channel, long *value) +{ + const struct ssam_temp *ssam_temp = dev_get_drvdata(dev); + + return ssam_tmp_get_temperature(ssam_temp->sdev, channel + 1, value); +} + +static const struct hwmon_channel_info * const ssam_temp_hwmon_info[] = { + HWMON_CHANNEL_INFO(chip, + HWMON_C_REGISTER_TZ), + /* We have at most 16 thermal sensor channels. */ + HWMON_CHANNEL_INFO(temp, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_INPUT), + NULL +}; + +static const struct hwmon_ops ssam_temp_hwmon_ops = { + .is_visible = ssam_temp_hwmon_is_visible, + .read = ssam_temp_hwmon_read, +}; + +static const struct hwmon_chip_info ssam_temp_hwmon_chip_info = { + .ops = &ssam_temp_hwmon_ops, + .info = ssam_temp_hwmon_info, +}; + +static int ssam_temp_probe(struct ssam_device *sdev) +{ + struct ssam_temp *ssam_temp; + struct device *hwmon_dev; + s16 sensors; + int status; + + status = ssam_tmp_get_available_sensors(sdev, &sensors); + if (status) + return status; + + ssam_temp = devm_kzalloc(&sdev->dev, sizeof(*ssam_temp), GFP_KERNEL); + if (!ssam_temp) + return -ENOMEM; + + ssam_temp->sdev = sdev; + ssam_temp->sensors = sensors; + + hwmon_dev = devm_hwmon_device_register_with_info(&sdev->dev, + "surface_thermal", ssam_temp, &ssam_temp_hwmon_chip_info, + NULL); + if (IS_ERR(hwmon_dev)) + return PTR_ERR(hwmon_dev); + + return 0; +} + +static const struct ssam_device_id ssam_temp_match[] = { + { SSAM_SDEV(TMP, SAM, 0x00, 0x02) }, + { }, +}; +MODULE_DEVICE_TABLE(ssam, ssam_temp_match); + +static struct ssam_device_driver ssam_temp = { + .probe = ssam_temp_probe, + .match_table = ssam_temp_match, + .driver = { + .name = "surface_temp", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, +}; +module_ssam_device_driver(ssam_temp); + +MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>"); +MODULE_DESCRIPTION("Thermal sensor subsystem driver for Surface System Aggregator Module"); +MODULE_LICENSE("GPL");
Some of the newer Microsoft Surface devices (such as the Surface Book 3 and Pro 9) have thermal sensors connected via the Surface Aggregator Module (the embedded controller on those devices). Add a basic driver to read out the temperature values of those sensors. Link: https://github.com/linux-surface/surface-aggregator-module/issues/59 Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com> --- MAINTAINERS | 6 ++ drivers/hwmon/Kconfig | 10 +++ drivers/hwmon/Makefile | 1 + drivers/hwmon/surface_temp.c | 165 +++++++++++++++++++++++++++++++++++ 4 files changed, 182 insertions(+) create mode 100644 drivers/hwmon/surface_temp.c