From dbd77fedadc6d130b443676eb4ef0e8321e1b063 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Thu, 26 Jul 2018 14:13:51 +0100 Subject: [PATCH] Add Raspberry Pi voltage sensor driver --- ...n-Add-support-for-RPi-voltage-sensor.patch | 403 ++++++++++++++++++ .../arm/CONFIG_SENSORS_RASPBERRYPI_HWMON | 1 + kernel-aarch64-debug.config | 1 + kernel-aarch64.config | 1 + kernel-armv7hl-debug.config | 1 + kernel-armv7hl-lpae-debug.config | 1 + kernel-armv7hl-lpae.config | 1 + kernel-armv7hl.config | 1 + kernel.spec | 7 +- 9 files changed, 416 insertions(+), 1 deletion(-) create mode 100644 bcm2835-hwmon-Add-support-for-RPi-voltage-sensor.patch create mode 100644 configs/fedora/generic/arm/CONFIG_SENSORS_RASPBERRYPI_HWMON diff --git a/bcm2835-hwmon-Add-support-for-RPi-voltage-sensor.patch b/bcm2835-hwmon-Add-support-for-RPi-voltage-sensor.patch new file mode 100644 index 000000000..3e65ab969 --- /dev/null +++ b/bcm2835-hwmon-Add-support-for-RPi-voltage-sensor.patch @@ -0,0 +1,403 @@ +From be3035e3627d2570de4c2c612ecd095968986437 Mon Sep 17 00:00:00 2001 +From: Stefan Wahren +Date: Fri, 25 May 2018 21:24:34 +0200 +Subject: [PATCH 1/4] ARM: bcm2835: Add GET_THROTTLED firmware property + +Recent Raspberry Pi firmware provides a mailbox property to detect +under-voltage conditions. Here is the current definition. + +The u32 value returned by the firmware is divided into 2 parts: + - lower 16-bits are the live value + - upper 16-bits are the history or sticky value + + Bits: + 0: undervoltage + 1: arm frequency capped + 2: currently throttled + 16: undervoltage has occurred + 17: arm frequency capped has occurred + 18: throttling has occurred + +Signed-off-by: Stefan Wahren +Signed-off-by: Eric Anholt +Reviewed-by: Eric Anholt +--- + include/soc/bcm2835/raspberrypi-firmware.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h +index 8ee8991aa099a..c4a5c9e9fb478 100644 +--- a/include/soc/bcm2835/raspberrypi-firmware.h ++++ b/include/soc/bcm2835/raspberrypi-firmware.h +@@ -75,6 +75,7 @@ enum rpi_firmware_property_tag { + RPI_FIRMWARE_GET_EDID_BLOCK = 0x00030020, + RPI_FIRMWARE_GET_CUSTOMER_OTP = 0x00030021, + RPI_FIRMWARE_GET_DOMAIN_STATE = 0x00030030, ++ RPI_FIRMWARE_GET_THROTTLED = 0x00030046, + RPI_FIRMWARE_SET_CLOCK_STATE = 0x00038001, + RPI_FIRMWARE_SET_CLOCK_RATE = 0x00038002, + RPI_FIRMWARE_SET_VOLTAGE = 0x00038003, +-- +2.17.1 + +From 3c493c885cf8abf0986c9877875161dfd0a29273 Mon Sep 17 00:00:00 2001 +From: Stefan Wahren +Date: Fri, 25 May 2018 21:24:35 +0200 +Subject: [PATCH 2/4] hwmon: Add support for RPi voltage sensor +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Currently there is no easy way to detect undervoltage conditions on a +remote Raspberry Pi. This hwmon driver retrieves the state of the +undervoltage sensor via mailbox interface. The handling based on +Noralf's modifications to the downstream firmware driver. In case of +an undervoltage condition only an entry is written to the kernel log. + +CC: "Noralf Trønnes" +Signed-off-by: Stefan Wahren +Signed-off-by: Eric Anholt +Acked-by: Guenter Roeck +--- + Documentation/hwmon/raspberrypi-hwmon | 22 ++++ + drivers/hwmon/Kconfig | 10 ++ + drivers/hwmon/Makefile | 1 + + drivers/hwmon/raspberrypi-hwmon.c | 166 ++++++++++++++++++++++++++ + 4 files changed, 199 insertions(+) + create mode 100644 Documentation/hwmon/raspberrypi-hwmon + create mode 100644 drivers/hwmon/raspberrypi-hwmon.c + +diff --git a/Documentation/hwmon/raspberrypi-hwmon b/Documentation/hwmon/raspberrypi-hwmon +new file mode 100644 +index 0000000000000..3c92e2cb52d60 +--- /dev/null ++++ b/Documentation/hwmon/raspberrypi-hwmon +@@ -0,0 +1,22 @@ ++Kernel driver raspberrypi-hwmon ++=============================== ++ ++Supported boards: ++ * Raspberry Pi A+ (via GPIO on SoC) ++ * Raspberry Pi B+ (via GPIO on SoC) ++ * Raspberry Pi 2 B (via GPIO on SoC) ++ * Raspberry Pi 3 B (via GPIO on port expander) ++ * Raspberry Pi 3 B+ (via PMIC) ++ ++Author: Stefan Wahren ++ ++Description ++----------- ++ ++This driver periodically polls a mailbox property of the VC4 firmware to detect ++undervoltage conditions. ++ ++Sysfs entries ++------------- ++ ++in0_lcrit_alarm Undervoltage alarm +diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig +index f10840ad465c2..fdaab8229686f 100644 +--- a/drivers/hwmon/Kconfig ++++ b/drivers/hwmon/Kconfig +@@ -1298,6 +1298,16 @@ config SENSORS_PWM_FAN + This driver can also be built as a module. If so, the module + will be called pwm-fan. + ++config SENSORS_RASPBERRYPI_HWMON ++ tristate "Raspberry Pi voltage monitor" ++ depends on RASPBERRYPI_FIRMWARE || COMPILE_TEST ++ help ++ If you say yes here you get support for voltage sensor on the ++ Raspberry Pi. ++ ++ This driver can also be built as a module. If so, the module ++ will be called raspberrypi-hwmon. ++ + config SENSORS_SHT15 + tristate "Sensiron humidity and temperature sensors. SHT15 and compat." + depends on GPIOLIB || COMPILE_TEST +diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile +index e7d52a36e6c4f..a9297703fd6e4 100644 +--- a/drivers/hwmon/Makefile ++++ b/drivers/hwmon/Makefile +@@ -141,6 +141,7 @@ obj-$(CONFIG_SENSORS_PC87427) += pc87427.o + obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o + obj-$(CONFIG_SENSORS_POWR1220) += powr1220.o + obj-$(CONFIG_SENSORS_PWM_FAN) += pwm-fan.o ++obj-$(CONFIG_SENSORS_RASPBERRYPI_HWMON) += raspberrypi-hwmon.o + obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o + obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o + obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o +diff --git a/drivers/hwmon/raspberrypi-hwmon.c b/drivers/hwmon/raspberrypi-hwmon.c +new file mode 100644 +index 0000000000000..fb4e4a6bb1f63 +--- /dev/null ++++ b/drivers/hwmon/raspberrypi-hwmon.c +@@ -0,0 +1,166 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Raspberry Pi voltage sensor driver ++ * ++ * Based on firmware/raspberrypi.c by Noralf Trønnes ++ * ++ * Copyright (C) 2018 Stefan Wahren ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define UNDERVOLTAGE_STICKY_BIT BIT(16) ++ ++struct rpi_hwmon_data { ++ struct device *hwmon_dev; ++ struct rpi_firmware *fw; ++ u32 last_throttled; ++ struct delayed_work get_values_poll_work; ++}; ++ ++static void rpi_firmware_get_throttled(struct rpi_hwmon_data *data) ++{ ++ u32 new_uv, old_uv, value; ++ int ret; ++ ++ /* Request firmware to clear sticky bits */ ++ value = 0xffff; ++ ++ ret = rpi_firmware_property(data->fw, RPI_FIRMWARE_GET_THROTTLED, ++ &value, sizeof(value)); ++ if (ret) { ++ dev_err_once(data->hwmon_dev, "Failed to get throttled (%d)\n", ++ ret); ++ return; ++ } ++ ++ new_uv = value & UNDERVOLTAGE_STICKY_BIT; ++ old_uv = data->last_throttled & UNDERVOLTAGE_STICKY_BIT; ++ data->last_throttled = value; ++ ++ if (new_uv == old_uv) ++ return; ++ ++ if (new_uv) ++ dev_crit(data->hwmon_dev, "Undervoltage detected!\n"); ++ else ++ dev_info(data->hwmon_dev, "Voltage normalised\n"); ++ ++ sysfs_notify(&data->hwmon_dev->kobj, NULL, "in0_lcrit_alarm"); ++} ++ ++static void get_values_poll(struct work_struct *work) ++{ ++ struct rpi_hwmon_data *data; ++ ++ data = container_of(work, struct rpi_hwmon_data, ++ get_values_poll_work.work); ++ ++ rpi_firmware_get_throttled(data); ++ ++ /* ++ * We can't run faster than the sticky shift (100ms) since we get ++ * flipping in the sticky bits that are cleared. ++ */ ++ schedule_delayed_work(&data->get_values_poll_work, 2 * HZ); ++} ++ ++static int rpi_read(struct device *dev, enum hwmon_sensor_types type, ++ u32 attr, int channel, long *val) ++{ ++ struct rpi_hwmon_data *data = dev_get_drvdata(dev); ++ ++ *val = !!(data->last_throttled & UNDERVOLTAGE_STICKY_BIT); ++ return 0; ++} ++ ++static umode_t rpi_is_visible(const void *_data, enum hwmon_sensor_types type, ++ u32 attr, int channel) ++{ ++ return 0444; ++} ++ ++static const u32 rpi_in_config[] = { ++ HWMON_I_LCRIT_ALARM, ++ 0 ++}; ++ ++static const struct hwmon_channel_info rpi_in = { ++ .type = hwmon_in, ++ .config = rpi_in_config, ++}; ++ ++static const struct hwmon_channel_info *rpi_info[] = { ++ &rpi_in, ++ NULL ++}; ++ ++static const struct hwmon_ops rpi_hwmon_ops = { ++ .is_visible = rpi_is_visible, ++ .read = rpi_read, ++}; ++ ++static const struct hwmon_chip_info rpi_chip_info = { ++ .ops = &rpi_hwmon_ops, ++ .info = rpi_info, ++}; ++ ++static int rpi_hwmon_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct rpi_hwmon_data *data; ++ int ret; ++ ++ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ /* Parent driver assure that firmware is correct */ ++ data->fw = dev_get_drvdata(dev->parent); ++ ++ /* Init throttled */ ++ ret = rpi_firmware_property(data->fw, RPI_FIRMWARE_GET_THROTTLED, ++ &data->last_throttled, ++ sizeof(data->last_throttled)); ++ ++ data->hwmon_dev = devm_hwmon_device_register_with_info(dev, "rpi_volt", ++ data, ++ &rpi_chip_info, ++ NULL); ++ ++ INIT_DELAYED_WORK(&data->get_values_poll_work, get_values_poll); ++ platform_set_drvdata(pdev, data); ++ ++ if (!PTR_ERR_OR_ZERO(data->hwmon_dev)) ++ schedule_delayed_work(&data->get_values_poll_work, 2 * HZ); ++ ++ return PTR_ERR_OR_ZERO(data->hwmon_dev); ++} ++ ++static int rpi_hwmon_remove(struct platform_device *pdev) ++{ ++ struct rpi_hwmon_data *data = platform_get_drvdata(pdev); ++ ++ cancel_delayed_work_sync(&data->get_values_poll_work); ++ ++ return 0; ++} ++ ++static struct platform_driver rpi_hwmon_driver = { ++ .probe = rpi_hwmon_probe, ++ .remove = rpi_hwmon_remove, ++ .driver = { ++ .name = "raspberrypi-hwmon", ++ }, ++}; ++module_platform_driver(rpi_hwmon_driver); ++ ++MODULE_AUTHOR("Stefan Wahren "); ++MODULE_DESCRIPTION("Raspberry Pi voltage sensor driver"); ++MODULE_LICENSE("GPL v2"); +-- +2.17.1 + +From 4ebe8673279b7afbbcbcf92094c9012a3c91f240 Mon Sep 17 00:00:00 2001 +From: Stefan Wahren +Date: Fri, 25 May 2018 21:24:36 +0200 +Subject: [PATCH 3/4] firmware: raspberrypi: Register hwmon driver + +Since the raspberrypi-hwmon driver is tied to the VC4 firmware instead of +particular hardware its registration should be in the firmware driver. + +Signed-off-by: Stefan Wahren +Signed-off-by: Eric Anholt +--- + drivers/firmware/raspberrypi.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c +index 6692888f04cfb..0602626bf72d0 100644 +--- a/drivers/firmware/raspberrypi.c ++++ b/drivers/firmware/raspberrypi.c +@@ -21,6 +21,8 @@ + #define MBOX_DATA28(msg) ((msg) & ~0xf) + #define MBOX_CHAN_PROPERTY 8 + ++static struct platform_device *rpi_hwmon; ++ + struct rpi_firmware { + struct mbox_client cl; + struct mbox_chan *chan; /* The property channel. */ +@@ -183,6 +185,20 @@ rpi_firmware_print_firmware_revision(struct rpi_firmware *fw) + } + } + ++static void ++rpi_register_hwmon_driver(struct device *dev, struct rpi_firmware *fw) ++{ ++ u32 packet; ++ int ret = rpi_firmware_property(fw, RPI_FIRMWARE_GET_THROTTLED, ++ &packet, sizeof(packet)); ++ ++ if (ret) ++ return; ++ ++ rpi_hwmon = platform_device_register_data(dev, "raspberrypi-hwmon", ++ -1, NULL, 0); ++} ++ + static int rpi_firmware_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -209,6 +225,7 @@ static int rpi_firmware_probe(struct platform_device *pdev) + platform_set_drvdata(pdev, fw); + + rpi_firmware_print_firmware_revision(fw); ++ rpi_register_hwmon_driver(dev, fw); + + return 0; + } +@@ -217,6 +234,8 @@ static int rpi_firmware_remove(struct platform_device *pdev) + { + struct rpi_firmware *fw = platform_get_drvdata(pdev); + ++ platform_device_unregister(rpi_hwmon); ++ rpi_hwmon = NULL; + mbox_free_channel(fw->chan); + + return 0; +-- +2.17.1 + +From a0cf7704b6bc145a9f198a9b2bcf92ccc5d6b6be Mon Sep 17 00:00:00 2001 +From: Peter Robinson +Date: Fri, 20 Jul 2018 12:58:37 +0100 +Subject: [PATCH] hwmon: rpi: add module alias to raspberrypi-hwmon + +The raspberrypi-hwmon driver doesn't automatically load, although it does work +when loaded, by adding the alias it auto loads as expected when built as a +module. Tested on RPi2/RPi3 on 32 bit kernel and RPi3B+ on aarch64 with +Fedora 28 and a patched 4.18 RC kernel. + +Fixes: q3c493c885cf ("hwmon: Add support for RPi voltage sensor") +Signed-off-by: Peter Robinson +CC: Stefan Wahren +CC: Eric Anholt +--- + drivers/hwmon/raspberrypi-hwmon.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/hwmon/raspberrypi-hwmon.c b/drivers/hwmon/raspberrypi-hwmon.c +index fb4e4a6bb1f63..be5ba46908953 100644 +--- a/drivers/hwmon/raspberrypi-hwmon.c ++++ b/drivers/hwmon/raspberrypi-hwmon.c +@@ -164,3 +164,4 @@ module_platform_driver(rpi_hwmon_driver); + MODULE_AUTHOR("Stefan Wahren "); + MODULE_DESCRIPTION("Raspberry Pi voltage sensor driver"); + MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:raspberrypi-hwmon"); +-- +2.17.1 + diff --git a/configs/fedora/generic/arm/CONFIG_SENSORS_RASPBERRYPI_HWMON b/configs/fedora/generic/arm/CONFIG_SENSORS_RASPBERRYPI_HWMON new file mode 100644 index 000000000..cecf9cbfb --- /dev/null +++ b/configs/fedora/generic/arm/CONFIG_SENSORS_RASPBERRYPI_HWMON @@ -0,0 +1 @@ +CONFIG_SENSORS_RASPBERRYPI_HWMON=m diff --git a/kernel-aarch64-debug.config b/kernel-aarch64-debug.config index e7f0efd19..86cfd1c72 100644 --- a/kernel-aarch64-debug.config +++ b/kernel-aarch64-debug.config @@ -5272,6 +5272,7 @@ CONFIG_SENSORS_PCF8591=m CONFIG_SENSORS_PMBUS=m CONFIG_SENSORS_POWR1220=m CONFIG_SENSORS_PWM_FAN=m +CONFIG_SENSORS_RASPBERRYPI_HWMON=m CONFIG_SENSORS_SCH5627=m CONFIG_SENSORS_SCH5636=m CONFIG_SENSORS_SHT15=m diff --git a/kernel-aarch64.config b/kernel-aarch64.config index 3eab68f2c..4d6003578 100644 --- a/kernel-aarch64.config +++ b/kernel-aarch64.config @@ -5249,6 +5249,7 @@ CONFIG_SENSORS_PCF8591=m CONFIG_SENSORS_PMBUS=m CONFIG_SENSORS_POWR1220=m CONFIG_SENSORS_PWM_FAN=m +CONFIG_SENSORS_RASPBERRYPI_HWMON=m CONFIG_SENSORS_SCH5627=m CONFIG_SENSORS_SCH5636=m CONFIG_SENSORS_SHT15=m diff --git a/kernel-armv7hl-debug.config b/kernel-armv7hl-debug.config index 86110c519..04f93a6be 100644 --- a/kernel-armv7hl-debug.config +++ b/kernel-armv7hl-debug.config @@ -5596,6 +5596,7 @@ CONFIG_SENSORS_PCF8591=m CONFIG_SENSORS_PMBUS=m CONFIG_SENSORS_POWR1220=m CONFIG_SENSORS_PWM_FAN=m +CONFIG_SENSORS_RASPBERRYPI_HWMON=m CONFIG_SENSORS_SCH5627=m CONFIG_SENSORS_SCH5636=m CONFIG_SENSORS_SHT15=m diff --git a/kernel-armv7hl-lpae-debug.config b/kernel-armv7hl-lpae-debug.config index f3118f300..005231928 100644 --- a/kernel-armv7hl-lpae-debug.config +++ b/kernel-armv7hl-lpae-debug.config @@ -5285,6 +5285,7 @@ CONFIG_SENSORS_PCF8591=m CONFIG_SENSORS_PMBUS=m CONFIG_SENSORS_POWR1220=m CONFIG_SENSORS_PWM_FAN=m +CONFIG_SENSORS_RASPBERRYPI_HWMON=m CONFIG_SENSORS_SCH5627=m CONFIG_SENSORS_SCH5636=m CONFIG_SENSORS_SHT15=m diff --git a/kernel-armv7hl-lpae.config b/kernel-armv7hl-lpae.config index b49bd99ea..ca671a56a 100644 --- a/kernel-armv7hl-lpae.config +++ b/kernel-armv7hl-lpae.config @@ -5262,6 +5262,7 @@ CONFIG_SENSORS_PCF8591=m CONFIG_SENSORS_PMBUS=m CONFIG_SENSORS_POWR1220=m CONFIG_SENSORS_PWM_FAN=m +CONFIG_SENSORS_RASPBERRYPI_HWMON=m CONFIG_SENSORS_SCH5627=m CONFIG_SENSORS_SCH5636=m CONFIG_SENSORS_SHT15=m diff --git a/kernel-armv7hl.config b/kernel-armv7hl.config index 169f14913..794edfdfa 100644 --- a/kernel-armv7hl.config +++ b/kernel-armv7hl.config @@ -5573,6 +5573,7 @@ CONFIG_SENSORS_PCF8591=m CONFIG_SENSORS_PMBUS=m CONFIG_SENSORS_POWR1220=m CONFIG_SENSORS_PWM_FAN=m +CONFIG_SENSORS_RASPBERRYPI_HWMON=m CONFIG_SENSORS_SCH5627=m CONFIG_SENSORS_SCH5636=m CONFIG_SENSORS_SHT15=m diff --git a/kernel.spec b/kernel.spec index 801e5f9ff..ef1802205 100644 --- a/kernel.spec +++ b/kernel.spec @@ -587,7 +587,9 @@ Patch307: arm-tegra-fix-nouveau-crash.patch # Enabling Patches for the RPi3+ Patch330: bcm2837-enable-pmu.patch -Patch332: bcm2835-cpufreq-add-CPU-frequency-control-driver.patch +Patch331: bcm2835-cpufreq-add-CPU-frequency-control-driver.patch + +Patch332: bcm2835-hwmon-Add-support-for-RPi-voltage-sensor.patch # Fix for AllWinner A64 Timer Errata, still not final # https://patchwork.kernel.org/patch/10392891/ @@ -1878,6 +1880,9 @@ fi # # %changelog +* Thu Jul 26 2018 Peter Robinson +- Add Raspberry Pi voltage sensor driver + * Wed Jul 25 2018 Laura Abbott - 4.18.0-0.rc6.git1.1 - Linux v4.18-rc6-93-g9981b4fb8684