* [PATCH RFC 1/4] pwm: rp1: Export helper to read fan tachometer RPM
2026-10-23 10:15 [PATCH RFC 0/4] hwmon: Add fan tachometer support for Raspberry Pi RP1 Andrea della Porta
@ 2026-10-23 10:15 ` Andrea della Porta
2026-10-23 10:15 ` [PATCH RFC 2/4] dt-bindings: hwmon: Add Raspberry Pi RP1 fan binding Andrea della Porta
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Andrea della Porta @ 2026-10-23 10:15 UTC (permalink / raw)
To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Florian Fainelli, Broadcom internal kernel review list,
Jonathan Corbet, Shuah Khan, Randy Dunlap, Andrea della Porta,
Uwe Kleine-König, Ray Jui, Scott Branden, Laurent Pinchart,
Gregor Herburger, Stanimir Varbanov, linux-hwmon, devicetree,
linux-rpi-kernel, linux-arm-kernel, linux-kernel, linux-doc,
linux-pwm, Gary Guo, Christophe JAILLET
On the Raspberry Pi RP1 southbridge, the internal PWM controller hardware
block houses a register associated with fan tachometer monitoring. The
tachometer pulses are measured by firmware running on the RP1 Cortex-M
core, which periodically writes the calculated RPM values directly into
dedicated MMIO registers within the PWM block.
Because the Linux PWM framework currently does not provide an abstraction
or API to report hardware-calculated tachometer readings to consumer
drivers, a direct accessor is needed by the companion hwmon fan driver
to read these values.
Add and export rp1_pwm_read_tachometer() to allow consumer drivers to
retrieve the fan speed from the PWM MMIO registers. To prevent polluting
the global kernel symbol namespace and restrict access to intended
consumers, export the function under the 'RP1_PWM' symbol namespace.
Signed-off-by: Andrea della Porta <andrea.porta@suse.com>
---
drivers/pwm/pwm-rp1.c | 27 +++++++++++++++++++++++
include/soc/bcm2835/raspberrypi-pwm-rp1.h | 10 +++++++++
2 files changed, 37 insertions(+)
create mode 100644 include/soc/bcm2835/raspberrypi-pwm-rp1.h
diff --git a/drivers/pwm/pwm-rp1.c b/drivers/pwm/pwm-rp1.c
index d4b13fba8d236..79d65f332dd30 100644
--- a/drivers/pwm/pwm-rp1.c
+++ b/drivers/pwm/pwm-rp1.c
@@ -49,6 +49,7 @@
#include <linux/pwm.h>
#include <linux/units.h>
#include <linux/spinlock.h>
+#include <soc/bcm2835/raspberrypi-pwm-rp1.h>
#define RP1_PWM_GLB_CTRL 0x000
#define RP1_PWM_GLB_CTRL_CHANNEL_ENABLE(chan) BIT(chan)
@@ -286,6 +287,32 @@ static const struct pwm_ops rp1_pwm_ops = {
.write_waveform = rp1_pwm_write_waveform,
};
+int rp1_pwm_read_tachometer(struct device *dev)
+{
+ struct pwm_chip *chip;
+ struct rp1_pwm *rp1;
+
+ if (!dev)
+ return -EINVAL;
+
+ if (!of_device_is_compatible(dev_of_node(dev), "raspberrypi,rp1-pwm"))
+ return -EINVAL;
+
+ chip = dev_get_drvdata(dev);
+ if (!chip)
+ return -ENODEV;
+
+ rp1 = pwmchip_get_drvdata(chip);
+ if (!rp1)
+ return -ENODEV;
+
+ if (!rp1->clk_enabled)
+ return -EBUSY;
+
+ return (int)readl(rp1->base + RP1_PWM_PHASE(2));
+}
+EXPORT_SYMBOL_NS_GPL(rp1_pwm_read_tachometer, "RP1_PWM");
+
static int rp1_pwm_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
diff --git a/include/soc/bcm2835/raspberrypi-pwm-rp1.h b/include/soc/bcm2835/raspberrypi-pwm-rp1.h
new file mode 100644
index 0000000000000..3be0892da667e
--- /dev/null
+++ b/include/soc/bcm2835/raspberrypi-pwm-rp1.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __SOC_RASPBERRY_PWM_RP1_H__
+#define __SOC_RASPBERRY_PWM_RP1_H__
+
+#include <linux/device.h>
+
+int rp1_pwm_read_tachometer(struct device *dev);
+
+#endif /* __SOC_RASPBERRY_PWM_RP1_H__ */
--
2.35.3
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH RFC 2/4] dt-bindings: hwmon: Add Raspberry Pi RP1 fan binding
2026-10-23 10:15 [PATCH RFC 0/4] hwmon: Add fan tachometer support for Raspberry Pi RP1 Andrea della Porta
2026-10-23 10:15 ` [PATCH RFC 1/4] pwm: rp1: Export helper to read fan tachometer RPM Andrea della Porta
@ 2026-10-23 10:15 ` Andrea della Porta
2026-10-23 10:15 ` [PATCH RFC 3/4] hwmon: Add driver for Raspberry Pi RP1 fan tachometer Andrea della Porta
2026-10-23 10:15 ` [PATCH RFC 4/4] arm64: dts: broadcom: bcm2712-rpi-5-b: Add RP1 fan tachometer node Andrea della Porta
3 siblings, 0 replies; 5+ messages in thread
From: Andrea della Porta @ 2026-10-23 10:15 UTC (permalink / raw)
To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Florian Fainelli, Broadcom internal kernel review list,
Jonathan Corbet, Shuah Khan, Randy Dunlap, Andrea della Porta,
Uwe Kleine-König, Ray Jui, Scott Branden, Laurent Pinchart,
Gregor Herburger, Stanimir Varbanov, linux-hwmon, devicetree,
linux-rpi-kernel, linux-arm-kernel, linux-kernel, linux-doc,
linux-pwm, Gary Guo, Christophe JAILLET
The Raspberry Pi RP1 is a multi-function southbridge used on the
Raspberry Pi 5. Its internal PWM controller block includes a built-in
hardware tachometer logic, which calculates the fan RPM by measuring the
tachometer pulses. The computed RPM is updated by the internal Cortex-M
firmware into specific MMIO registers within the PWM block.
Currently, the Linux PWM subsystem lacks a standard API to report
hardware-calculated tachometer values back to consumer drivers.
To avoid abusing the standard 'pwms' property, this binding introduces
a custom property, 'raspberrypi,pwm-tachometer', to link the standalone
hwmon fan driver to the RP1 PWM controller node. This enables reading
the tachometer MMIO registers and exposing the RPM via sysfs.
Signed-off-by: Andrea della Porta <andrea.porta@suse.com>
---
For the rationale behind this design, please see the cover letter
.../bindings/hwmon/raspberrypi,rp1-fan.yaml | 39 +++++++++++++++++++
1 file changed, 39 insertions(+)
create mode 100644 Documentation/devicetree/bindings/hwmon/raspberrypi,rp1-fan.yaml
diff --git a/Documentation/devicetree/bindings/hwmon/raspberrypi,rp1-fan.yaml b/Documentation/devicetree/bindings/hwmon/raspberrypi,rp1-fan.yaml
new file mode 100644
index 0000000000000..53e5b67fa856b
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/raspberrypi,rp1-fan.yaml
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/hwmon/raspberrypi,rp1-fan.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Raspberry Pi RP1 fan tachometer
+
+maintainers:
+ - Andrea della Porta <andrea.porta@suse.com>
+
+description: |
+ Hardware monitoring driver for the fan connected to the Raspberry Pi RP1
+ southbridge. The RP1 PWM controller hardware contains a built-in tachometer
+ logic that calculates the fan RPM. This binding links the fan to the PWM
+ controller to read the tachometer values.
+
+properties:
+ compatible:
+ const: raspberrypi,rp1-fan
+
+ raspberrypi,pwm-tachometer:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ Phandle to the RP1 PWM controller node that contains the tachometer
+ registers for this fan.
+
+required:
+ - compatible
+ - raspberrypi,pwm-tachometer
+
+additionalProperties: false
+
+examples:
+ - |
+ fan {
+ compatible = "raspberrypi,rp1-fan";
+ raspberrypi,pwm-tachometer = <&rp1_pwm1>;
+ };
--
2.35.3
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH RFC 3/4] hwmon: Add driver for Raspberry Pi RP1 fan tachometer
2026-10-23 10:15 [PATCH RFC 0/4] hwmon: Add fan tachometer support for Raspberry Pi RP1 Andrea della Porta
2026-10-23 10:15 ` [PATCH RFC 1/4] pwm: rp1: Export helper to read fan tachometer RPM Andrea della Porta
2026-10-23 10:15 ` [PATCH RFC 2/4] dt-bindings: hwmon: Add Raspberry Pi RP1 fan binding Andrea della Porta
@ 2026-10-23 10:15 ` Andrea della Porta
2026-10-23 10:15 ` [PATCH RFC 4/4] arm64: dts: broadcom: bcm2712-rpi-5-b: Add RP1 fan tachometer node Andrea della Porta
3 siblings, 0 replies; 5+ messages in thread
From: Andrea della Porta @ 2026-10-23 10:15 UTC (permalink / raw)
To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Florian Fainelli, Broadcom internal kernel review list,
Jonathan Corbet, Shuah Khan, Randy Dunlap, Andrea della Porta,
Uwe Kleine-König, Ray Jui, Scott Branden, Laurent Pinchart,
Gregor Herburger, Stanimir Varbanov, linux-hwmon, devicetree,
linux-rpi-kernel, linux-arm-kernel, linux-kernel, linux-doc,
linux-pwm, Gary Guo, Christophe JAILLET
Add a hardware monitoring driver to support the fan tachometer on the
Raspberry Pi RP1 southbridge, found on the Raspberry Pi 5.
The RP1 PWM controller block contains specific MMIO registers that hold
the current fan speed in RPM. These registers are periodically updated by
the RP1 internal firmware based on the tachometer pulses.
Since the Linux PWM subsystem does not currently offer a framework for
exposing integrated hardware tachometer readings, this driver is
implemented as a standalone hwmon device. It parses the
'raspberrypi,pwm-tachometer' DT property to find the supplier PWM device,
establishes a device link to ensure proper lifecycle management, and uses
RP1-specific PWM functions to retrieve the RPM values.
Provides the standard hwmon sysfs attribute 'fan1_input'.
Signed-off-by: Andrea della Porta <andrea.porta@suse.com>
---
Documentation/hwmon/index.rst | 1 +
Documentation/hwmon/rp1-fan.rst | 41 ++++++++++
MAINTAINERS | 1 +
drivers/hwmon/Kconfig | 11 +++
drivers/hwmon/Makefile | 1 +
drivers/hwmon/rp1-hwmon.c | 136 ++++++++++++++++++++++++++++++++
6 files changed, 191 insertions(+)
create mode 100644 Documentation/hwmon/rp1-fan.rst
create mode 100644 drivers/hwmon/rp1-hwmon.c
diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
index 9955a525436ae..e078404a0e08d 100644
--- a/Documentation/hwmon/index.rst
+++ b/Documentation/hwmon/index.rst
@@ -235,6 +235,7 @@ Hardware Monitoring Kernel Drivers
q54sj108a2
qnap-mcu-hwmon
raspberrypi-hwmon
+ rp1-fan
sbrmi
sbtsi_temp
sch5627
diff --git a/Documentation/hwmon/rp1-fan.rst b/Documentation/hwmon/rp1-fan.rst
new file mode 100644
index 0000000000000..4497b61c0a394
--- /dev/null
+++ b/Documentation/hwmon/rp1-fan.rst
@@ -0,0 +1,41 @@
+.. SPDX-License-Identifier: GPL-2.0-only
+
+Raspberry Pi RP1 fan tachometer
+=======================================
+
+Supported chips:
+
+ * Raspberry Pi RP1
+
+ Prefix: 'rp1_fan'
+
+ Addresses scanned: -
+
+ Datasheet: not public
+
+Author: Andrea della Porta <andrea.porta@suse.com>
+
+Description
+-----------
+
+The Raspberry Pi RP1 is a multi-function I/O controller (southbridge) used
+on boards such as the Raspberry Pi 5. Among its peripherals, the RP1 includes
+a PWM controller responsible for fan control.
+
+In addition to standard PWM output, the RP1 provides fan speed monitoring
+(tachometer). The tachometer pulse measurement is performed internally by
+firmware running on the RP1 Cortex-M microcontroller core. The computed fan
+speed (RPM) is periodically updated by the firmware directly into dedicated
+MMIO registers located within the RP1 PWM block.
+
+This driver interfaces with the RP1 PWM controller to read these firmware-updated
+registers and exposes the fan speed as standard hwmon sysfs attributes.
+
+Sysfs entries
+-------------
+
+The following attributes are supported.
+
+======================= ========================================================
+fan1_input fan tachometer speed in RPM (RO)
+======================= ========================================================
diff --git a/MAINTAINERS b/MAINTAINERS
index 3a19da74d00c9..f66c52e640342 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22819,6 +22819,7 @@ M: Andrea della Porta <andrea.porta@suse.com>
S: Maintained
F: arch/arm64/boot/dts/broadcom/rp1*.dts*
F: drivers/clk/clk-rp1.c
+F: drivers/hwmon/rp1-hwmon.c
F: drivers/misc/rp1/
F: drivers/pinctrl/pinctrl-rp1.c
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index fecff8610ea8b..c23dfd5f5055a 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1981,6 +1981,17 @@ config SENSORS_RASPBERRYPI_HWMON
This driver can also be built as a module. If so, the module
will be called raspberrypi-hwmon.
+config SENSORS_RP1_FAN
+ tristate "Raspberry Pi RP1 PWM Fan Support"
+ depends on OF
+ depends on PWM_RASPBERRYPI_RP1 || COMPILE_TEST
+ help
+ If you say yes here you get support for reading the fan tachometer
+ from Raspberry Pi RP1.
+
+ This driver can also be built as a module. If so, the module
+ will be called rp1-hwmon.
+
config SENSORS_SL28CPLD
tristate "Kontron sl28cpld hardware monitoring driver"
depends on MFD_SL28CPLD || COMPILE_TEST
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 1229b6b3996d7..54f2bd057a2d8 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -207,6 +207,7 @@ obj-$(CONFIG_SENSORS_PT5161L) += pt5161l.o
obj-$(CONFIG_SENSORS_PWM_FAN) += pwm-fan.o
obj-$(CONFIG_SENSORS_QNAP_MCU_HWMON) += qnap-mcu-hwmon.o
obj-$(CONFIG_SENSORS_RASPBERRYPI_HWMON) += raspberrypi-hwmon.o
+obj-$(CONFIG_SENSORS_RP1_FAN) += rp1-hwmon.o
obj-$(CONFIG_SENSORS_SBTSI) += sbtsi_temp.o
obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o
obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o
diff --git a/drivers/hwmon/rp1-hwmon.c b/drivers/hwmon/rp1-hwmon.c
new file mode 100644
index 0000000000000..7943eda905dbc
--- /dev/null
+++ b/drivers/hwmon/rp1-hwmon.c
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Hardware monitoring fan driver for Raspberry Pi RP1
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <soc/bcm2835/raspberrypi-pwm-rp1.h>
+
+struct rp1_fan_data {
+ struct device *pwm_dev;
+};
+
+static int rp1_fan_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ struct rp1_fan_data *data = dev_get_drvdata(dev);
+ int rpm;
+
+ if (type == hwmon_fan && attr == hwmon_fan_input) {
+ rpm = rp1_pwm_read_tachometer(data->pwm_dev);
+ if (rpm < 0)
+ return rpm;
+
+ *val = rpm;
+ return 0;
+ }
+
+ return -EOPNOTSUPP;
+}
+
+static const struct hwmon_channel_info * const rp1_fan_info[] = {
+ HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT),
+ NULL
+};
+
+static const struct hwmon_ops rp1_fan_hwmon_ops = {
+ .visible = 0444,
+ .read = rp1_fan_read,
+};
+
+static const struct hwmon_chip_info rp1_fan_chip_info = {
+ .ops = &rp1_fan_hwmon_ops,
+ .info = rp1_fan_info,
+};
+
+static void rp1_fan_put_device(void *data)
+{
+ put_device(data);
+}
+
+static int rp1_fan_probe(struct platform_device *pdev)
+{
+ struct platform_device *pwm_pdev;
+ struct device *dev = &pdev->dev;
+ struct device_node *pwm_node;
+ struct rp1_fan_data *data;
+ struct device_link *link;
+ struct device *hwmon_dev;
+ int ret;
+
+ pwm_node = of_parse_phandle(dev->of_node, "raspberrypi,pwm-tachometer", 0);
+ if (!pwm_node)
+ return dev_err_probe(dev, -ENODEV,
+ "RP1 PWM node not specified in Device Tree (requires 'raspberrypi,pwm-tachometer')\n");
+
+ if (!of_device_is_available(pwm_node)) {
+ of_node_put(pwm_node);
+ return dev_err_probe(dev, -ENODEV,
+ "RP1 PWM node is disabled\n");
+ }
+
+ pwm_pdev = of_find_device_by_node(pwm_node);
+ of_node_put(pwm_node);
+ if (!pwm_pdev)
+ return dev_err_probe(dev, -EPROBE_DEFER,
+ "RP1 PWM platform device not populated yet\n");
+
+ scoped_guard(device, &pwm_pdev->dev) {
+ if (!device_is_bound(&pwm_pdev->dev)) {
+ put_device(&pwm_pdev->dev);
+ return dev_err_probe(dev, -EPROBE_DEFER,
+ "RP1 PWM driver is not bound yet\n");
+ }
+ }
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ put_device(&pwm_pdev->dev);
+ return -ENOMEM;
+ }
+
+ ret = devm_add_action_or_reset(dev, rp1_fan_put_device, &pwm_pdev->dev);
+ if (ret)
+ return ret;
+
+ data->pwm_dev = &pwm_pdev->dev;
+
+ link = device_link_add(dev, &pwm_pdev->dev, DL_FLAG_AUTOREMOVE_CONSUMER);
+ if (!link)
+ return dev_err_probe(dev, -EINVAL,
+ "Cannot create the device_link to PWM controller\n");
+
+ hwmon_dev = devm_hwmon_device_register_with_info(dev, "rp1_fan",
+ data,
+ &rp1_fan_chip_info,
+ NULL);
+
+ return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static const struct of_device_id rp1_fan_of_match[] = {
+ { .compatible = "raspberrypi,rp1-fan" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, rp1_fan_of_match);
+
+static struct platform_driver rp1_fan_driver = {
+ .probe = rp1_fan_probe,
+ .driver = {
+ .name = "rp1-fan",
+ .of_match_table = rp1_fan_of_match,
+ },
+};
+module_platform_driver(rp1_fan_driver);
+
+MODULE_AUTHOR("Andrea della Porta <andrea.porta@suse.com>");
+MODULE_DESCRIPTION("Raspberry Pi RP1 HWMon Fan Driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("RP1_PWM");
--
2.35.3
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH RFC 4/4] arm64: dts: broadcom: bcm2712-rpi-5-b: Add RP1 fan tachometer node
2026-10-23 10:15 [PATCH RFC 0/4] hwmon: Add fan tachometer support for Raspberry Pi RP1 Andrea della Porta
` (2 preceding siblings ...)
2026-10-23 10:15 ` [PATCH RFC 3/4] hwmon: Add driver for Raspberry Pi RP1 fan tachometer Andrea della Porta
@ 2026-10-23 10:15 ` Andrea della Porta
3 siblings, 0 replies; 5+ messages in thread
From: Andrea della Porta @ 2026-10-23 10:15 UTC (permalink / raw)
To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Florian Fainelli, Broadcom internal kernel review list,
Jonathan Corbet, Shuah Khan, Randy Dunlap, Andrea della Porta,
Uwe Kleine-König, Ray Jui, Scott Branden, Laurent Pinchart,
Gregor Herburger, Stanimir Varbanov, linux-hwmon, devicetree,
linux-rpi-kernel, linux-arm-kernel, linux-kernel, linux-doc,
linux-pwm, Gary Guo, Christophe JAILLET
Add the hwmon fan node for the Raspberry Pi 5 to expose the cooling fan
speed (RPM) to userspace.
The fan tachometer is managed internally by the RP1 PWM controller.
This node uses the 'raspberrypi,pwm-tachometer' property to link the
rp1-fan hwmon driver to the existing RP1 PWM controller, enabling
RPM reporting via sysfs.
Signed-off-by: Andrea della Porta <andrea.porta@suse.com>
---
arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
index 748be8f1ee9e2..9bc6d0e9da1b5 100644
--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
+++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts
@@ -16,6 +16,11 @@ / {
aliases {
ethernet0 = &rp1_eth;
};
+
+ fan-tach {
+ compatible = "raspberrypi,rp1-fan";
+ raspberrypi,pwm-tachometer = <&rp1_pwm1>;
+ };
};
&pcie2 {
--
2.35.3
^ permalink raw reply [flat|nested] 5+ messages in thread