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

vexpress-hwmon.c (6684B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *
      4 * Copyright (C) 2012 ARM Limited
      5 */
      6
      7#define DRVNAME "vexpress-hwmon"
      8#define pr_fmt(fmt) DRVNAME ": " fmt
      9
     10#include <linux/device.h>
     11#include <linux/err.h>
     12#include <linux/hwmon.h>
     13#include <linux/hwmon-sysfs.h>
     14#include <linux/module.h>
     15#include <linux/of.h>
     16#include <linux/of_device.h>
     17#include <linux/platform_device.h>
     18#include <linux/vexpress.h>
     19
     20struct vexpress_hwmon_data {
     21	struct device *hwmon_dev;
     22	struct regmap *reg;
     23};
     24
     25static ssize_t vexpress_hwmon_label_show(struct device *dev,
     26		struct device_attribute *dev_attr, char *buffer)
     27{
     28	const char *label = of_get_property(dev->of_node, "label", NULL);
     29
     30	return sysfs_emit(buffer, "%s\n", label);
     31}
     32
     33static ssize_t vexpress_hwmon_u32_show(struct device *dev,
     34		struct device_attribute *dev_attr, char *buffer)
     35{
     36	struct vexpress_hwmon_data *data = dev_get_drvdata(dev);
     37	int err;
     38	u32 value;
     39
     40	err = regmap_read(data->reg, 0, &value);
     41	if (err)
     42		return err;
     43
     44	return sysfs_emit(buffer, "%u\n", value /
     45			  to_sensor_dev_attr(dev_attr)->index);
     46}
     47
     48static ssize_t vexpress_hwmon_u64_show(struct device *dev,
     49		struct device_attribute *dev_attr, char *buffer)
     50{
     51	struct vexpress_hwmon_data *data = dev_get_drvdata(dev);
     52	int err;
     53	u32 value_hi, value_lo;
     54
     55	err = regmap_read(data->reg, 0, &value_lo);
     56	if (err)
     57		return err;
     58
     59	err = regmap_read(data->reg, 1, &value_hi);
     60	if (err)
     61		return err;
     62
     63	return sysfs_emit(buffer, "%llu\n",
     64			  div_u64(((u64)value_hi << 32) | value_lo,
     65				  to_sensor_dev_attr(dev_attr)->index));
     66}
     67
     68static umode_t vexpress_hwmon_attr_is_visible(struct kobject *kobj,
     69		struct attribute *attr, int index)
     70{
     71	struct device *dev = kobj_to_dev(kobj);
     72	struct device_attribute *dev_attr = container_of(attr,
     73				struct device_attribute, attr);
     74
     75	if (dev_attr->show == vexpress_hwmon_label_show &&
     76			!of_get_property(dev->of_node, "label", NULL))
     77		return 0;
     78
     79	return attr->mode;
     80}
     81
     82struct vexpress_hwmon_type {
     83	const char *name;
     84	const struct attribute_group **attr_groups;
     85};
     86
     87#if !defined(CONFIG_REGULATOR_VEXPRESS)
     88static DEVICE_ATTR(in1_label, 0444, vexpress_hwmon_label_show, NULL);
     89static SENSOR_DEVICE_ATTR_RO(in1_input, vexpress_hwmon_u32, 1000);
     90static struct attribute *vexpress_hwmon_attrs_volt[] = {
     91	&dev_attr_in1_label.attr,
     92	&sensor_dev_attr_in1_input.dev_attr.attr,
     93	NULL
     94};
     95static struct attribute_group vexpress_hwmon_group_volt = {
     96	.is_visible = vexpress_hwmon_attr_is_visible,
     97	.attrs = vexpress_hwmon_attrs_volt,
     98};
     99static struct vexpress_hwmon_type vexpress_hwmon_volt = {
    100	.name = "vexpress_volt",
    101	.attr_groups = (const struct attribute_group *[]) {
    102		&vexpress_hwmon_group_volt,
    103		NULL,
    104	},
    105};
    106#endif
    107
    108static DEVICE_ATTR(curr1_label, 0444, vexpress_hwmon_label_show, NULL);
    109static SENSOR_DEVICE_ATTR_RO(curr1_input, vexpress_hwmon_u32, 1000);
    110static struct attribute *vexpress_hwmon_attrs_amp[] = {
    111	&dev_attr_curr1_label.attr,
    112	&sensor_dev_attr_curr1_input.dev_attr.attr,
    113	NULL
    114};
    115static struct attribute_group vexpress_hwmon_group_amp = {
    116	.is_visible = vexpress_hwmon_attr_is_visible,
    117	.attrs = vexpress_hwmon_attrs_amp,
    118};
    119static struct vexpress_hwmon_type vexpress_hwmon_amp = {
    120	.name = "vexpress_amp",
    121	.attr_groups = (const struct attribute_group *[]) {
    122		&vexpress_hwmon_group_amp,
    123		NULL
    124	},
    125};
    126
    127static DEVICE_ATTR(temp1_label, 0444, vexpress_hwmon_label_show, NULL);
    128static SENSOR_DEVICE_ATTR_RO(temp1_input, vexpress_hwmon_u32, 1000);
    129static struct attribute *vexpress_hwmon_attrs_temp[] = {
    130	&dev_attr_temp1_label.attr,
    131	&sensor_dev_attr_temp1_input.dev_attr.attr,
    132	NULL
    133};
    134static struct attribute_group vexpress_hwmon_group_temp = {
    135	.is_visible = vexpress_hwmon_attr_is_visible,
    136	.attrs = vexpress_hwmon_attrs_temp,
    137};
    138static struct vexpress_hwmon_type vexpress_hwmon_temp = {
    139	.name = "vexpress_temp",
    140	.attr_groups = (const struct attribute_group *[]) {
    141		&vexpress_hwmon_group_temp,
    142		NULL
    143	},
    144};
    145
    146static DEVICE_ATTR(power1_label, 0444, vexpress_hwmon_label_show, NULL);
    147static SENSOR_DEVICE_ATTR_RO(power1_input, vexpress_hwmon_u32, 1);
    148static struct attribute *vexpress_hwmon_attrs_power[] = {
    149	&dev_attr_power1_label.attr,
    150	&sensor_dev_attr_power1_input.dev_attr.attr,
    151	NULL
    152};
    153static struct attribute_group vexpress_hwmon_group_power = {
    154	.is_visible = vexpress_hwmon_attr_is_visible,
    155	.attrs = vexpress_hwmon_attrs_power,
    156};
    157static struct vexpress_hwmon_type vexpress_hwmon_power = {
    158	.name = "vexpress_power",
    159	.attr_groups = (const struct attribute_group *[]) {
    160		&vexpress_hwmon_group_power,
    161		NULL
    162	},
    163};
    164
    165static DEVICE_ATTR(energy1_label, 0444, vexpress_hwmon_label_show, NULL);
    166static SENSOR_DEVICE_ATTR_RO(energy1_input, vexpress_hwmon_u64, 1);
    167static struct attribute *vexpress_hwmon_attrs_energy[] = {
    168	&dev_attr_energy1_label.attr,
    169	&sensor_dev_attr_energy1_input.dev_attr.attr,
    170	NULL
    171};
    172static struct attribute_group vexpress_hwmon_group_energy = {
    173	.is_visible = vexpress_hwmon_attr_is_visible,
    174	.attrs = vexpress_hwmon_attrs_energy,
    175};
    176static struct vexpress_hwmon_type vexpress_hwmon_energy = {
    177	.name = "vexpress_energy",
    178	.attr_groups = (const struct attribute_group *[]) {
    179		&vexpress_hwmon_group_energy,
    180		NULL
    181	},
    182};
    183
    184static const struct of_device_id vexpress_hwmon_of_match[] = {
    185#if !defined(CONFIG_REGULATOR_VEXPRESS)
    186	{
    187		.compatible = "arm,vexpress-volt",
    188		.data = &vexpress_hwmon_volt,
    189	},
    190#endif
    191	{
    192		.compatible = "arm,vexpress-amp",
    193		.data = &vexpress_hwmon_amp,
    194	}, {
    195		.compatible = "arm,vexpress-temp",
    196		.data = &vexpress_hwmon_temp,
    197	}, {
    198		.compatible = "arm,vexpress-power",
    199		.data = &vexpress_hwmon_power,
    200	}, {
    201		.compatible = "arm,vexpress-energy",
    202		.data = &vexpress_hwmon_energy,
    203	},
    204	{}
    205};
    206MODULE_DEVICE_TABLE(of, vexpress_hwmon_of_match);
    207
    208static int vexpress_hwmon_probe(struct platform_device *pdev)
    209{
    210	struct vexpress_hwmon_data *data;
    211	const struct vexpress_hwmon_type *type;
    212
    213	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
    214	if (!data)
    215		return -ENOMEM;
    216	platform_set_drvdata(pdev, data);
    217
    218	type = of_device_get_match_data(&pdev->dev);
    219	if (!type)
    220		return -ENODEV;
    221
    222	data->reg = devm_regmap_init_vexpress_config(&pdev->dev);
    223	if (IS_ERR(data->reg))
    224		return PTR_ERR(data->reg);
    225
    226	data->hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev,
    227			type->name, data, type->attr_groups);
    228
    229	return PTR_ERR_OR_ZERO(data->hwmon_dev);
    230}
    231
    232static struct platform_driver vexpress_hwmon_driver = {
    233	.probe = vexpress_hwmon_probe,
    234	.driver	= {
    235		.name = DRVNAME,
    236		.of_match_table = vexpress_hwmon_of_match,
    237	},
    238};
    239
    240module_platform_driver(vexpress_hwmon_driver);
    241
    242MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
    243MODULE_DESCRIPTION("Versatile Express hwmon sensors driver");
    244MODULE_LICENSE("GPL");
    245MODULE_ALIAS("platform:vexpress-hwmon");