0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/device.h>
0010 #include <linux/devm-helpers.h>
0011 #include <linux/err.h>
0012 #include <linux/hwmon.h>
0013 #include <linux/module.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/slab.h>
0016 #include <linux/workqueue.h>
0017 #include <soc/bcm2835/raspberrypi-firmware.h>
0018
0019 #define UNDERVOLTAGE_STICKY_BIT BIT(16)
0020
0021 struct rpi_hwmon_data {
0022 struct device *hwmon_dev;
0023 struct rpi_firmware *fw;
0024 u32 last_throttled;
0025 struct delayed_work get_values_poll_work;
0026 };
0027
0028 static void rpi_firmware_get_throttled(struct rpi_hwmon_data *data)
0029 {
0030 u32 new_uv, old_uv, value;
0031 int ret;
0032
0033
0034 value = 0xffff;
0035
0036 ret = rpi_firmware_property(data->fw, RPI_FIRMWARE_GET_THROTTLED,
0037 &value, sizeof(value));
0038 if (ret) {
0039 dev_err_once(data->hwmon_dev, "Failed to get throttled (%d)\n",
0040 ret);
0041 return;
0042 }
0043
0044 new_uv = value & UNDERVOLTAGE_STICKY_BIT;
0045 old_uv = data->last_throttled & UNDERVOLTAGE_STICKY_BIT;
0046 data->last_throttled = value;
0047
0048 if (new_uv == old_uv)
0049 return;
0050
0051 if (new_uv)
0052 dev_crit(data->hwmon_dev, "Undervoltage detected!\n");
0053 else
0054 dev_info(data->hwmon_dev, "Voltage normalised\n");
0055
0056 hwmon_notify_event(data->hwmon_dev, hwmon_in, hwmon_in_lcrit_alarm, 0);
0057 }
0058
0059 static void get_values_poll(struct work_struct *work)
0060 {
0061 struct rpi_hwmon_data *data;
0062
0063 data = container_of(work, struct rpi_hwmon_data,
0064 get_values_poll_work.work);
0065
0066 rpi_firmware_get_throttled(data);
0067
0068
0069
0070
0071
0072 schedule_delayed_work(&data->get_values_poll_work, 2 * HZ);
0073 }
0074
0075 static int rpi_read(struct device *dev, enum hwmon_sensor_types type,
0076 u32 attr, int channel, long *val)
0077 {
0078 struct rpi_hwmon_data *data = dev_get_drvdata(dev);
0079
0080 *val = !!(data->last_throttled & UNDERVOLTAGE_STICKY_BIT);
0081 return 0;
0082 }
0083
0084 static umode_t rpi_is_visible(const void *_data, enum hwmon_sensor_types type,
0085 u32 attr, int channel)
0086 {
0087 return 0444;
0088 }
0089
0090 static const struct hwmon_channel_info *rpi_info[] = {
0091 HWMON_CHANNEL_INFO(in,
0092 HWMON_I_LCRIT_ALARM),
0093 NULL
0094 };
0095
0096 static const struct hwmon_ops rpi_hwmon_ops = {
0097 .is_visible = rpi_is_visible,
0098 .read = rpi_read,
0099 };
0100
0101 static const struct hwmon_chip_info rpi_chip_info = {
0102 .ops = &rpi_hwmon_ops,
0103 .info = rpi_info,
0104 };
0105
0106 static int rpi_hwmon_probe(struct platform_device *pdev)
0107 {
0108 struct device *dev = &pdev->dev;
0109 struct rpi_hwmon_data *data;
0110 int ret;
0111
0112 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
0113 if (!data)
0114 return -ENOMEM;
0115
0116
0117 data->fw = dev_get_drvdata(dev->parent);
0118
0119 data->hwmon_dev = devm_hwmon_device_register_with_info(dev, "rpi_volt",
0120 data,
0121 &rpi_chip_info,
0122 NULL);
0123 if (IS_ERR(data->hwmon_dev))
0124 return PTR_ERR(data->hwmon_dev);
0125
0126 ret = devm_delayed_work_autocancel(dev, &data->get_values_poll_work,
0127 get_values_poll);
0128 if (ret)
0129 return ret;
0130 platform_set_drvdata(pdev, data);
0131
0132 schedule_delayed_work(&data->get_values_poll_work, 2 * HZ);
0133
0134 return 0;
0135 }
0136
0137 static struct platform_driver rpi_hwmon_driver = {
0138 .probe = rpi_hwmon_probe,
0139 .driver = {
0140 .name = "raspberrypi-hwmon",
0141 },
0142 };
0143 module_platform_driver(rpi_hwmon_driver);
0144
0145 MODULE_AUTHOR("Stefan Wahren <wahrenst@gmx.net>");
0146 MODULE_DESCRIPTION("Raspberry Pi voltage sensor driver");
0147 MODULE_LICENSE("GPL v2");
0148 MODULE_ALIAS("platform:raspberrypi-hwmon");