cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

wm831x-hwmon.c (4455B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * drivers/hwmon/wm831x-hwmon.c - Wolfson Microelectronics WM831x PMIC
      4 *                                hardware monitoring features.
      5 *
      6 * Copyright (C) 2009 Wolfson Microelectronics plc
      7 */
      8
      9#include <linux/kernel.h>
     10#include <linux/module.h>
     11#include <linux/platform_device.h>
     12#include <linux/err.h>
     13#include <linux/hwmon.h>
     14#include <linux/hwmon-sysfs.h>
     15#include <linux/slab.h>
     16
     17#include <linux/mfd/wm831x/core.h>
     18#include <linux/mfd/wm831x/auxadc.h>
     19
     20static const char * const input_names[] = {
     21	[WM831X_AUX_SYSVDD]    = "SYSVDD",
     22	[WM831X_AUX_USB]       = "USB",
     23	[WM831X_AUX_BKUP_BATT] = "Backup battery",
     24	[WM831X_AUX_BATT]      = "Battery",
     25	[WM831X_AUX_WALL]      = "WALL",
     26	[WM831X_AUX_CHIP_TEMP] = "PMIC",
     27	[WM831X_AUX_BATT_TEMP] = "Battery",
     28};
     29
     30static ssize_t show_voltage(struct device *dev,
     31			    struct device_attribute *attr, char *buf)
     32{
     33	struct wm831x *wm831x = dev_get_drvdata(dev);
     34	int channel = to_sensor_dev_attr(attr)->index;
     35	int ret;
     36
     37	ret = wm831x_auxadc_read_uv(wm831x, channel);
     38	if (ret < 0)
     39		return ret;
     40
     41	return sprintf(buf, "%d\n", DIV_ROUND_CLOSEST(ret, 1000));
     42}
     43
     44static ssize_t show_chip_temp(struct device *dev,
     45			      struct device_attribute *attr, char *buf)
     46{
     47	struct wm831x *wm831x = dev_get_drvdata(dev);
     48	int channel = to_sensor_dev_attr(attr)->index;
     49	int ret;
     50
     51	ret = wm831x_auxadc_read(wm831x, channel);
     52	if (ret < 0)
     53		return ret;
     54
     55	/* Degrees celsius = (512.18-ret) / 1.0983 */
     56	ret = 512180 - (ret * 1000);
     57	ret = DIV_ROUND_CLOSEST(ret * 10000, 10983);
     58
     59	return sprintf(buf, "%d\n", ret);
     60}
     61
     62static ssize_t show_label(struct device *dev,
     63			  struct device_attribute *attr, char *buf)
     64{
     65	int channel = to_sensor_dev_attr(attr)->index;
     66
     67	return sprintf(buf, "%s\n", input_names[channel]);
     68}
     69
     70#define WM831X_VOLTAGE(id, name) \
     71	static SENSOR_DEVICE_ATTR(in##id##_input, S_IRUGO, show_voltage, \
     72				  NULL, name)
     73
     74#define WM831X_NAMED_VOLTAGE(id, name) \
     75	WM831X_VOLTAGE(id, name); \
     76	static SENSOR_DEVICE_ATTR(in##id##_label, S_IRUGO, show_label,	\
     77				  NULL, name)
     78
     79WM831X_VOLTAGE(0, WM831X_AUX_AUX1);
     80WM831X_VOLTAGE(1, WM831X_AUX_AUX2);
     81WM831X_VOLTAGE(2, WM831X_AUX_AUX3);
     82WM831X_VOLTAGE(3, WM831X_AUX_AUX4);
     83
     84WM831X_NAMED_VOLTAGE(4, WM831X_AUX_SYSVDD);
     85WM831X_NAMED_VOLTAGE(5, WM831X_AUX_USB);
     86WM831X_NAMED_VOLTAGE(6, WM831X_AUX_BATT);
     87WM831X_NAMED_VOLTAGE(7, WM831X_AUX_WALL);
     88WM831X_NAMED_VOLTAGE(8, WM831X_AUX_BKUP_BATT);
     89
     90static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_chip_temp, NULL,
     91			  WM831X_AUX_CHIP_TEMP);
     92static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_label, NULL,
     93			  WM831X_AUX_CHIP_TEMP);
     94/*
     95 * Report as a voltage since conversion depends on external components
     96 * and that's what the ABI wants.
     97 */
     98static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_voltage, NULL,
     99			  WM831X_AUX_BATT_TEMP);
    100static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, show_label, NULL,
    101			  WM831X_AUX_BATT_TEMP);
    102
    103static struct attribute *wm831x_attrs[] = {
    104	&sensor_dev_attr_in0_input.dev_attr.attr,
    105	&sensor_dev_attr_in1_input.dev_attr.attr,
    106	&sensor_dev_attr_in2_input.dev_attr.attr,
    107	&sensor_dev_attr_in3_input.dev_attr.attr,
    108
    109	&sensor_dev_attr_in4_input.dev_attr.attr,
    110	&sensor_dev_attr_in4_label.dev_attr.attr,
    111	&sensor_dev_attr_in5_input.dev_attr.attr,
    112	&sensor_dev_attr_in5_label.dev_attr.attr,
    113	&sensor_dev_attr_in6_input.dev_attr.attr,
    114	&sensor_dev_attr_in6_label.dev_attr.attr,
    115	&sensor_dev_attr_in7_input.dev_attr.attr,
    116	&sensor_dev_attr_in7_label.dev_attr.attr,
    117	&sensor_dev_attr_in8_input.dev_attr.attr,
    118	&sensor_dev_attr_in8_label.dev_attr.attr,
    119
    120	&sensor_dev_attr_temp1_input.dev_attr.attr,
    121	&sensor_dev_attr_temp1_label.dev_attr.attr,
    122	&sensor_dev_attr_temp2_input.dev_attr.attr,
    123	&sensor_dev_attr_temp2_label.dev_attr.attr,
    124
    125	NULL
    126};
    127
    128ATTRIBUTE_GROUPS(wm831x);
    129
    130static int wm831x_hwmon_probe(struct platform_device *pdev)
    131{
    132	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
    133	struct device *hwmon_dev;
    134
    135	hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, "wm831x",
    136							   wm831x,
    137							   wm831x_groups);
    138	return PTR_ERR_OR_ZERO(hwmon_dev);
    139}
    140
    141static struct platform_driver wm831x_hwmon_driver = {
    142	.probe = wm831x_hwmon_probe,
    143	.driver = {
    144		.name = "wm831x-hwmon",
    145	},
    146};
    147
    148module_platform_driver(wm831x_hwmon_driver);
    149
    150MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
    151MODULE_DESCRIPTION("WM831x Hardware Monitoring");
    152MODULE_LICENSE("GPL");
    153MODULE_ALIAS("platform:wm831x-hwmon");