Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0+ 2 : : /* 3 : : * Raspberry Pi voltage sensor driver 4 : : * 5 : : * Based on firmware/raspberrypi.c by Noralf Trønnes 6 : : * 7 : : * Copyright (C) 2018 Stefan Wahren <stefan.wahren@i2se.com> 8 : : */ 9 : : #include <linux/device.h> 10 : : #include <linux/err.h> 11 : : #include <linux/hwmon.h> 12 : : #include <linux/module.h> 13 : : #include <linux/platform_device.h> 14 : : #include <linux/slab.h> 15 : : #include <linux/workqueue.h> 16 : : #include <soc/bcm2835/raspberrypi-firmware.h> 17 : : 18 : : /* 19 : : * This section defines some rate limited logging that prevent 20 : : * repeated messages at much lower Hz than the default kernel settings. 21 : : * It's usually 5s, this is 5 minutes. 22 : : * Burst 3 means you may get three messages 'quickly', before 23 : : * the ratelimiting kicks in. 24 : : */ 25 : : #define LOCAL_RATELIMIT_INTERVAL (5 * 60 * HZ) 26 : : #define LOCAL_RATELIMIT_BURST 3 27 : : 28 : : #ifdef CONFIG_PRINTK 29 : : #define printk_ratelimited_local(fmt, ...) \ 30 : : ({ \ 31 : : static DEFINE_RATELIMIT_STATE(_rs, \ 32 : : LOCAL_RATELIMIT_INTERVAL, \ 33 : : LOCAL_RATELIMIT_BURST); \ 34 : : \ 35 : : if (__ratelimit(&_rs)) \ 36 : : printk(fmt, ##__VA_ARGS__); \ 37 : : }) 38 : : #else 39 : : #define printk_ratelimited_local(fmt, ...) \ 40 : : no_printk(fmt, ##__VA_ARGS__) 41 : : #endif 42 : : 43 : : #define pr_crit_ratelimited_local(fmt, ...) \ 44 : : printk_ratelimited_local(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__) 45 : : #define pr_info_ratelimited_local(fmt, ...) \ 46 : : printk_ratelimited_local(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__) 47 : : 48 : : #define UNDERVOLTAGE_STICKY_BIT BIT(16) 49 : : 50 : : struct rpi_hwmon_data { 51 : : struct device *hwmon_dev; 52 : : struct rpi_firmware *fw; 53 : : u32 last_throttled; 54 : : struct delayed_work get_values_poll_work; 55 : : }; 56 : : 57 : 3 : static void rpi_firmware_get_throttled(struct rpi_hwmon_data *data) 58 : : { 59 : : u32 new_uv, old_uv, value; 60 : : int ret; 61 : : 62 : : /* Request firmware to clear sticky bits */ 63 : 3 : value = 0xffff; 64 : : 65 : 3 : ret = rpi_firmware_property(data->fw, RPI_FIRMWARE_GET_THROTTLED, 66 : : &value, sizeof(value)); 67 : 3 : if (ret) { 68 : 0 : dev_err_once(data->hwmon_dev, "Failed to get throttled (%d)\n", 69 : : ret); 70 : 3 : return; 71 : : } 72 : : 73 : 3 : new_uv = value & UNDERVOLTAGE_STICKY_BIT; 74 : 3 : old_uv = data->last_throttled & UNDERVOLTAGE_STICKY_BIT; 75 : 3 : data->last_throttled = value; 76 : : 77 : 3 : if (new_uv == old_uv) 78 : : return; 79 : : 80 : 0 : if (new_uv) { 81 : 0 : pr_crit_ratelimited_local("Under-voltage detected! (0x%08x)\n", 82 : : value); 83 : : } else { 84 : 0 : pr_info_ratelimited_local("Voltage normalised (0x%08x)\n", 85 : : value); 86 : : } 87 : : 88 : 0 : sysfs_notify(&data->hwmon_dev->kobj, NULL, "in0_lcrit_alarm"); 89 : : } 90 : : 91 : 3 : static void get_values_poll(struct work_struct *work) 92 : : { 93 : : struct rpi_hwmon_data *data; 94 : : 95 : 3 : data = container_of(work, struct rpi_hwmon_data, 96 : : get_values_poll_work.work); 97 : : 98 : 3 : rpi_firmware_get_throttled(data); 99 : : 100 : : /* 101 : : * We can't run faster than the sticky shift (100ms) since we get 102 : : * flipping in the sticky bits that are cleared. 103 : : */ 104 : 3 : schedule_delayed_work(&data->get_values_poll_work, 2 * HZ); 105 : 3 : } 106 : : 107 : 0 : static int rpi_read(struct device *dev, enum hwmon_sensor_types type, 108 : : u32 attr, int channel, long *val) 109 : : { 110 : : struct rpi_hwmon_data *data = dev_get_drvdata(dev); 111 : : 112 : 0 : *val = !!(data->last_throttled & UNDERVOLTAGE_STICKY_BIT); 113 : 0 : return 0; 114 : : } 115 : : 116 : 3 : static umode_t rpi_is_visible(const void *_data, enum hwmon_sensor_types type, 117 : : u32 attr, int channel) 118 : : { 119 : 3 : return 0444; 120 : : } 121 : : 122 : : static const struct hwmon_channel_info *rpi_info[] = { 123 : : HWMON_CHANNEL_INFO(in, 124 : : HWMON_I_LCRIT_ALARM), 125 : : NULL 126 : : }; 127 : : 128 : : static const struct hwmon_ops rpi_hwmon_ops = { 129 : : .is_visible = rpi_is_visible, 130 : : .read = rpi_read, 131 : : }; 132 : : 133 : : static const struct hwmon_chip_info rpi_chip_info = { 134 : : .ops = &rpi_hwmon_ops, 135 : : .info = rpi_info, 136 : : }; 137 : : 138 : 3 : static int rpi_hwmon_probe(struct platform_device *pdev) 139 : : { 140 : 3 : struct device *dev = &pdev->dev; 141 : : struct rpi_hwmon_data *data; 142 : : 143 : : data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 144 : 3 : if (!data) 145 : : return -ENOMEM; 146 : : 147 : : /* Parent driver assure that firmware is correct */ 148 : 3 : data->fw = dev_get_drvdata(dev->parent); 149 : : 150 : 3 : data->hwmon_dev = devm_hwmon_device_register_with_info(dev, "rpi_volt", 151 : : data, 152 : : &rpi_chip_info, 153 : : NULL); 154 : : 155 : 3 : INIT_DELAYED_WORK(&data->get_values_poll_work, get_values_poll); 156 : : platform_set_drvdata(pdev, data); 157 : : 158 : 3 : if (!PTR_ERR_OR_ZERO(data->hwmon_dev)) 159 : 3 : schedule_delayed_work(&data->get_values_poll_work, 2 * HZ); 160 : : 161 : 3 : return PTR_ERR_OR_ZERO(data->hwmon_dev); 162 : : } 163 : : 164 : 0 : static int rpi_hwmon_remove(struct platform_device *pdev) 165 : : { 166 : : struct rpi_hwmon_data *data = platform_get_drvdata(pdev); 167 : : 168 : 0 : cancel_delayed_work_sync(&data->get_values_poll_work); 169 : : 170 : 0 : return 0; 171 : : } 172 : : 173 : : static struct platform_driver rpi_hwmon_driver = { 174 : : .probe = rpi_hwmon_probe, 175 : : .remove = rpi_hwmon_remove, 176 : : .driver = { 177 : : .name = "raspberrypi-hwmon", 178 : : }, 179 : : }; 180 : 3 : module_platform_driver(rpi_hwmon_driver); 181 : : 182 : : MODULE_AUTHOR("Stefan Wahren <wahrenst@gmx.net>"); 183 : : MODULE_DESCRIPTION("Raspberry Pi voltage sensor driver"); 184 : : MODULE_LICENSE("GPL v2"); 185 : : MODULE_ALIAS("platform:raspberrypi-hwmon");