From: Shubham Chakraborty <chakrabortyshubham66@gmail.com>
To: Guenter Roeck <linux@roeck-us.net>,
Florian Fainelli <florian.fainelli@broadcom.com>,
Broadcom internal kernel review list
<bcm-kernel-feedback-list@broadcom.com>,
linux-hwmon@vger.kernel.org,
linux-rpi-kernel@lists.infradead.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
Subject: [PATCH 2/2] hwmon: raspberrypi: Add voltage input support
Date: Sat, 16 May 2026 22:14:06 +0530 [thread overview]
Message-ID: <20260516164407.25255-2-chakrabortyshubham66@gmail.com> (raw)
In-Reply-To: <20260516164407.25255-1-chakrabortyshubham66@gmail.com>
Extend the raspberrypi-hwmon driver to expose firmware-provided
voltage measurements through the hwmon subsystem.
The driver now exports the following voltage inputs:
- in0_input (core)
- in1_input (sdram_c)
- in2_input (sdram_i)
- in3_input (sdram_p)
Voltage values returned by firmware are converted from microvolts
to millivolts as expected by the hwmon subsystem.
The existing undervoltage sticky alarm handling is preserved and
associated with the first voltage channel.
Tested in -
- Raspberry Pi 3b+ (Linux raspberrypi 6.12.75+rpt-rpi-v8 #1 SMP PREEMPT
Debian 1:6.12.75-1+rpt1 (2026-03-11) aarch64 GNU/Linux)
Signed-off-by: Shubham Chakraborty <chakrabortyshubham66@gmail.com>
---
drivers/hwmon/raspberrypi-hwmon.c | 112 +++++++++++++++++++++++++++++-
1 file changed, 109 insertions(+), 3 deletions(-)
diff --git a/drivers/hwmon/raspberrypi-hwmon.c b/drivers/hwmon/raspberrypi-hwmon.c
index a2938881ccd2..c73a970db025 100644
--- a/drivers/hwmon/raspberrypi-hwmon.c
+++ b/drivers/hwmon/raspberrypi-hwmon.c
@@ -5,6 +5,7 @@
* Based on firmware/raspberrypi.c by Noralf Trønnes
*
* Copyright (C) 2018 Stefan Wahren <stefan.wahren@i2se.com>
+ * Copyright (C) 2026 Shubham Chakraborty <chakrabortyshubham66@gmail.com>
*/
#include <linux/device.h>
#include <linux/devm-helpers.h>
@@ -18,6 +19,11 @@
#define UNDERVOLTAGE_STICKY_BIT BIT(16)
+struct rpi_firmware_get_value {
+ __le32 id;
+ __le32 val;
+} __packed;
+
struct rpi_hwmon_data {
struct device *hwmon_dev;
struct rpi_firmware *fw;
@@ -56,6 +62,23 @@ static void rpi_firmware_get_throttled(struct rpi_hwmon_data *data)
hwmon_notify_event(data->hwmon_dev, hwmon_in, hwmon_in_lcrit_alarm, 0);
}
+static int rpi_firmware_get_voltage(struct rpi_hwmon_data *data, u32 id,
+ long *val)
+{
+ struct rpi_firmware_get_value packet;
+ int ret;
+
+ packet.id = cpu_to_le32(id);
+ packet.val = 0;
+ ret = rpi_firmware_property(data->fw, RPI_FIRMWARE_GET_VOLTAGE,
+ &packet, sizeof(packet));
+ if (ret)
+ return ret;
+
+ *val = le32_to_cpu(packet.val) / 1000;
+ return 0;
+}
+
static void get_values_poll(struct work_struct *work)
{
struct rpi_hwmon_data *data;
@@ -77,19 +100,101 @@ static int rpi_read(struct device *dev, enum hwmon_sensor_types type,
{
struct rpi_hwmon_data *data = dev_get_drvdata(dev);
- *val = !!(data->last_throttled & UNDERVOLTAGE_STICKY_BIT);
+ if (type == hwmon_in) {
+ switch (attr) {
+ case hwmon_in_input:
+ switch (channel) {
+ case 0:
+ return rpi_firmware_get_voltage(data,
+ RPI_FIRMWARE_VOLT_ID_CORE,
+ val);
+ case 1:
+ return rpi_firmware_get_voltage(data,
+ RPI_FIRMWARE_VOLT_ID_SDRAM_C,
+ val);
+ case 2:
+ return rpi_firmware_get_voltage(data,
+ RPI_FIRMWARE_VOLT_ID_SDRAM_I,
+ val);
+ case 3:
+ return rpi_firmware_get_voltage(data,
+ RPI_FIRMWARE_VOLT_ID_SDRAM_P,
+ val);
+ default:
+ return -EOPNOTSUPP;
+ }
+ case hwmon_in_lcrit_alarm:
+ if (channel == 0) {
+ *val = !!(data->last_throttled & UNDERVOLTAGE_STICKY_BIT);
+ return 0;
+ }
+ return -EOPNOTSUPP;
+ default:
+ return -EOPNOTSUPP;
+ }
+ }
+
+ return -EOPNOTSUPP;
+}
+
+static int rpi_read_string(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, const char **str)
+{
+ if (type == hwmon_in && attr == hwmon_in_label) {
+ switch (channel) {
+ case 0:
+ *str = "core";
+ return 0;
+ case 1:
+ *str = "sdram_c";
+ return 0;
+ case 2:
+ *str = "sdram_i";
+ return 0;
+ case 3:
+ *str = "sdram_p";
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+ }
+
+ return -EOPNOTSUPP;
+}
+
+static umode_t rpi_is_visible(const void *_data, enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ if (type == hwmon_in) {
+ switch (attr) {
+ case hwmon_in_input:
+ case hwmon_in_label:
+ return 0444;
+ case hwmon_in_lcrit_alarm:
+ if (channel == 0)
+ return 0444;
+ return 0;
+ default:
+ return 0;
+ }
+ }
+
return 0;
}
static const struct hwmon_channel_info * const rpi_info[] = {
HWMON_CHANNEL_INFO(in,
- HWMON_I_LCRIT_ALARM),
+ HWMON_I_INPUT | HWMON_I_LABEL | HWMON_I_LCRIT_ALARM,
+ HWMON_I_INPUT | HWMON_I_LABEL,
+ HWMON_I_INPUT | HWMON_I_LABEL,
+ HWMON_I_INPUT | HWMON_I_LABEL),
NULL
};
static const struct hwmon_ops rpi_hwmon_ops = {
- .visible = 0444,
+ .is_visible = rpi_is_visible,
.read = rpi_read,
+ .read_string = rpi_read_string,
};
static const struct hwmon_chip_info rpi_chip_info = {
@@ -159,6 +264,7 @@ static struct platform_driver rpi_hwmon_driver = {
module_platform_driver(rpi_hwmon_driver);
MODULE_AUTHOR("Stefan Wahren <wahrenst@gmx.net>");
+MODULE_AUTHOR("Shubham Chakraborty <chakrabortyshubham66@gmail.com>");
MODULE_DESCRIPTION("Raspberry Pi voltage sensor driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:raspberrypi-hwmon");
--
2.54.0
next prev parent reply other threads:[~2026-05-16 16:44 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-16 16:44 [PATCH 1/2] soc: bcm2835: raspberrypi-firmware: Add voltage domain IDs Shubham Chakraborty
2026-05-16 16:44 ` Shubham Chakraborty [this message]
2026-05-16 17:13 ` [PATCH 2/2] hwmon: raspberrypi: Add voltage input support Guenter Roeck
2026-05-16 18:24 ` Guenter Roeck
2026-05-16 19:15 ` [PATCH v2 0/2] raspberrypi: firmware and hwmon voltage support Shubham Chakraborty
2026-05-16 19:15 ` [PATCH v2 1/2] soc: bcm2835: raspberrypi-firmware: Add voltage domain IDs Shubham Chakraborty
2026-05-16 23:09 ` Guenter Roeck
2026-05-16 19:15 ` [PATCH v2 2/2] hwmon: raspberrypi: Add voltage input support Shubham Chakraborty
2026-05-16 23:20 ` Guenter Roeck
2026-05-17 8:04 ` [PATCH v3 0/3] raspberrypi-hwmon voltage support and teardown fix Shubham Chakraborty
2026-05-17 8:04 ` [PATCH v3 1/3] soc: bcm2835: raspberrypi-firmware: Add voltage domain IDs Shubham Chakraborty
2026-05-18 22:17 ` Guenter Roeck
2026-05-19 15:29 ` Florian Fainelli
2026-05-20 13:35 ` Guenter Roeck
2026-05-17 8:04 ` [PATCH v3 2/3] hwmon: raspberrypi: Add voltage input support Shubham Chakraborty
2026-05-19 15:28 ` Florian Fainelli
2026-05-20 13:37 ` Guenter Roeck
2026-05-17 8:04 ` [PATCH v3 3/3] hwmon: raspberrypi: Fix delayed-work teardown race Shubham Chakraborty
2026-05-20 13:39 ` Guenter Roeck
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260516164407.25255-2-chakrabortyshubham66@gmail.com \
--to=chakrabortyshubham66@gmail.com \
--cc=bcm-kernel-feedback-list@broadcom.com \
--cc=florian.fainelli@broadcom.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-hwmon@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rpi-kernel@lists.infradead.org \
--cc=linux@roeck-us.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox