Skip to content

Commit

Permalink
hwmon: add fan speed monitoring driver for Surface devices
Browse files Browse the repository at this point in the history
Adds a driver that provides read only access to the fan speed for Microsoft
Surface Pro devices. The fan speed is always regulated by the EC and cannot
be influenced directly.

Signed-off-by: Ivor Wanders <ivor@iwanders.net>
Link: linux-surface/kernel#144
Patchset: surface-sam
  • Loading branch information
iwanders authored and ReillyBrogan committed Apr 27, 2024
1 parent 275e858 commit 77a949c
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 0 deletions.
1 change: 1 addition & 0 deletions Documentation/hwmon/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ Hardware Monitoring Kernel Drivers
smsc47m1
sparx5-temp
stpddc60
surface_fan
sy7636a-hwmon
tc654
tc74
Expand Down
25 changes: 25 additions & 0 deletions Documentation/hwmon/surface_fan.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
Kernel driver surface_fan
=========================

Supported Devices:

* Microsoft Surface Pro 9

Author: Ivor Wanders <ivor@iwanders.net>

Description
-----------

This provides monitoring of the fan found in some Microsoft Surface Pro devices,
like the Surface Pro 9. The fan is always controlled by the onboard controller.

Sysfs interface
---------------

======================= ======= =========================================
Name Perm Description
======================= ======= =========================================
``fan1_input`` RO Current fan speed in RPM.
======================= ======= =========================================
8 changes: 8 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -14576,6 +14576,14 @@ F: Documentation/driver-api/surface_aggregator/clients/dtx.rst
F: drivers/platform/surface/surface_dtx.c
F: include/uapi/linux/surface_aggregator/dtx.h

MICROSOFT SURFACE SENSOR FAN DRIVER
M: Maximilian Luz <luzmaximilian@gmail.com>
M: Ivor Wanders <ivor@iwanders.net>
L: linux-hwmon@vger.kernel.org
S: Maintained
F: Documentation/hwmon/surface_fan.rst
F: drivers/hwmon/surface_fan.c

MICROSOFT SURFACE GPE LID SUPPORT DRIVER
M: Maximilian Luz <luzmaximilian@gmail.com>
L: platform-driver-x86@vger.kernel.org
Expand Down
13 changes: 13 additions & 0 deletions drivers/hwmon/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1994,6 +1994,19 @@ config SENSORS_SFCTEMP
This driver can also be built as a module. If so, the module
will be called sfctemp.

config SENSORS_SURFACE_FAN
tristate "Surface Fan Driver"
depends on SURFACE_AGGREGATOR
help
Driver that provides monitoring of the fan on Surface Pro devices that
have a fan, like the Surface Pro 9.

This makes the fan's current speed accessible through the hwmon
system. It does not provide control over the fan, the firmware is
responsible for that, this driver merely provides monitoring.

Select M or Y here, if you want to be able to read the fan's speed.

config SENSORS_ADC128D818
tristate "Texas Instruments ADC128D818"
depends on I2C
Expand Down
1 change: 1 addition & 0 deletions drivers/hwmon/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
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_SY7636A) += sy7636a-hwmon.o
obj-$(CONFIG_SENSORS_AMC6821) += amc6821.o
obj-$(CONFIG_SENSORS_TC74) += tc74.o
Expand Down
93 changes: 93 additions & 0 deletions drivers/hwmon/surface_fan.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Surface Fan driver for Surface System Aggregator Module. It provides access
* to the fan's rpm through the hwmon system.
*
* Copyright (C) 2023 Ivor Wanders <ivor@iwanders.net>
*/

#include <linux/hwmon.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/surface_aggregator/device.h>
#include <linux/types.h>

// SSAM
SSAM_DEFINE_SYNC_REQUEST_CL_R(__ssam_fan_rpm_get, __le16, {
.target_category = SSAM_SSH_TC_FAN,
.command_id = 0x01,
});

// hwmon
umode_t surface_fan_hwmon_is_visible(const void *drvdata,
enum hwmon_sensor_types type, u32 attr,
int channel)
{
return 0444;
}

static int surface_fan_hwmon_read(struct device *dev,
enum hwmon_sensor_types type, u32 attr,
int channel, long *val)
{
struct ssam_device *sdev = dev_get_drvdata(dev);
int ret;
__le16 value;

ret = __ssam_fan_rpm_get(sdev, &value);
if (ret)
return ret;

*val = le16_to_cpu(value);

return ret;
}

static const struct hwmon_channel_info *const surface_fan_info[] = {
HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT),
NULL
};

static const struct hwmon_ops surface_fan_hwmon_ops = {
.is_visible = surface_fan_hwmon_is_visible,
.read = surface_fan_hwmon_read,
};

static const struct hwmon_chip_info surface_fan_chip_info = {
.ops = &surface_fan_hwmon_ops,
.info = surface_fan_info,
};

static int surface_fan_probe(struct ssam_device *sdev)
{
struct device *hdev;

hdev = devm_hwmon_device_register_with_info(&sdev->dev,
"surface_fan", sdev,
&surface_fan_chip_info,
NULL);
if (IS_ERR(hdev))
return PTR_ERR(hdev);

return 0;
}

static const struct ssam_device_id ssam_fan_match[] = {
{ SSAM_SDEV(FAN, SAM, 0x01, 0x01) },
{},
};
MODULE_DEVICE_TABLE(ssam, ssam_fan_match);

static struct ssam_device_driver surface_fan = {
.probe = surface_fan_probe,
.match_table = ssam_fan_match,
.driver = {
.name = "surface_fan",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
};
module_ssam_device_driver(surface_fan);

MODULE_AUTHOR("Ivor Wanders <ivor@iwanders.net>");
MODULE_DESCRIPTION("Fan Driver for Surface System Aggregator Module");
MODULE_LICENSE("GPL");

0 comments on commit 77a949c

Please sign in to comment.