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

sch5636.c (14990B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/***************************************************************************
      3 *   Copyright (C) 2011-2012 Hans de Goede <hdegoede@redhat.com>           *
      4 *                                                                         *
      5 ***************************************************************************/
      6
      7#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
      8
      9#include <linux/module.h>
     10#include <linux/mod_devicetable.h>
     11#include <linux/init.h>
     12#include <linux/slab.h>
     13#include <linux/jiffies.h>
     14#include <linux/platform_device.h>
     15#include <linux/hwmon.h>
     16#include <linux/hwmon-sysfs.h>
     17#include <linux/err.h>
     18#include <linux/mutex.h>
     19#include "sch56xx-common.h"
     20
     21#define DRVNAME "sch5636"
     22#define DEVNAME "theseus" /* We only support one model for now */
     23
     24#define SCH5636_REG_FUJITSU_ID		0x780
     25#define SCH5636_REG_FUJITSU_REV		0x783
     26
     27#define SCH5636_NO_INS			5
     28#define SCH5636_NO_TEMPS		16
     29#define SCH5636_NO_FANS			8
     30
     31static const u16 SCH5636_REG_IN_VAL[SCH5636_NO_INS] = {
     32	0x22, 0x23, 0x24, 0x25, 0x189 };
     33static const u16 SCH5636_REG_IN_FACTORS[SCH5636_NO_INS] = {
     34	4400, 1500, 4000, 4400, 16000 };
     35static const char * const SCH5636_IN_LABELS[SCH5636_NO_INS] = {
     36	"3.3V", "VREF", "VBAT", "3.3AUX", "12V" };
     37
     38static const u16 SCH5636_REG_TEMP_VAL[SCH5636_NO_TEMPS] = {
     39	0x2B, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x180, 0x181,
     40	0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C };
     41#define SCH5636_REG_TEMP_CTRL(i)	(0x790 + (i))
     42#define SCH5636_TEMP_WORKING		0x01
     43#define SCH5636_TEMP_ALARM		0x02
     44#define SCH5636_TEMP_DEACTIVATED	0x80
     45
     46static const u16 SCH5636_REG_FAN_VAL[SCH5636_NO_FANS] = {
     47	0x2C, 0x2E, 0x30, 0x32, 0x62, 0x64, 0x66, 0x68 };
     48#define SCH5636_REG_FAN_CTRL(i)		(0x880 + (i))
     49/* FAULT in datasheet, but acts as an alarm */
     50#define SCH5636_FAN_ALARM		0x04
     51#define SCH5636_FAN_NOT_PRESENT		0x08
     52#define SCH5636_FAN_DEACTIVATED		0x80
     53
     54
     55struct sch5636_data {
     56	unsigned short addr;
     57	struct device *hwmon_dev;
     58
     59	struct mutex update_lock;
     60	bool valid;			/* true if following fields are valid */
     61	unsigned long last_updated;	/* In jiffies */
     62	u8 in[SCH5636_NO_INS];
     63	u8 temp_val[SCH5636_NO_TEMPS];
     64	u8 temp_ctrl[SCH5636_NO_TEMPS];
     65	u16 fan_val[SCH5636_NO_FANS];
     66	u8 fan_ctrl[SCH5636_NO_FANS];
     67};
     68
     69static struct sch5636_data *sch5636_update_device(struct device *dev)
     70{
     71	struct sch5636_data *data = dev_get_drvdata(dev);
     72	struct sch5636_data *ret = data;
     73	int i, val;
     74
     75	mutex_lock(&data->update_lock);
     76
     77	/* Cache the values for 1 second */
     78	if (data->valid && !time_after(jiffies, data->last_updated + HZ))
     79		goto abort;
     80
     81	for (i = 0; i < SCH5636_NO_INS; i++) {
     82		val = sch56xx_read_virtual_reg(data->addr,
     83					       SCH5636_REG_IN_VAL[i]);
     84		if (unlikely(val < 0)) {
     85			ret = ERR_PTR(val);
     86			goto abort;
     87		}
     88		data->in[i] = val;
     89	}
     90
     91	for (i = 0; i < SCH5636_NO_TEMPS; i++) {
     92		if (data->temp_ctrl[i] & SCH5636_TEMP_DEACTIVATED)
     93			continue;
     94
     95		val = sch56xx_read_virtual_reg(data->addr,
     96					       SCH5636_REG_TEMP_VAL[i]);
     97		if (unlikely(val < 0)) {
     98			ret = ERR_PTR(val);
     99			goto abort;
    100		}
    101		data->temp_val[i] = val;
    102
    103		val = sch56xx_read_virtual_reg(data->addr,
    104					       SCH5636_REG_TEMP_CTRL(i));
    105		if (unlikely(val < 0)) {
    106			ret = ERR_PTR(val);
    107			goto abort;
    108		}
    109		data->temp_ctrl[i] = val;
    110		/* Alarms need to be explicitly write-cleared */
    111		if (val & SCH5636_TEMP_ALARM) {
    112			sch56xx_write_virtual_reg(data->addr,
    113						SCH5636_REG_TEMP_CTRL(i), val);
    114		}
    115	}
    116
    117	for (i = 0; i < SCH5636_NO_FANS; i++) {
    118		if (data->fan_ctrl[i] & SCH5636_FAN_DEACTIVATED)
    119			continue;
    120
    121		val = sch56xx_read_virtual_reg16(data->addr,
    122						 SCH5636_REG_FAN_VAL[i]);
    123		if (unlikely(val < 0)) {
    124			ret = ERR_PTR(val);
    125			goto abort;
    126		}
    127		data->fan_val[i] = val;
    128
    129		val = sch56xx_read_virtual_reg(data->addr,
    130					       SCH5636_REG_FAN_CTRL(i));
    131		if (unlikely(val < 0)) {
    132			ret = ERR_PTR(val);
    133			goto abort;
    134		}
    135		data->fan_ctrl[i] = val;
    136		/* Alarms need to be explicitly write-cleared */
    137		if (val & SCH5636_FAN_ALARM) {
    138			sch56xx_write_virtual_reg(data->addr,
    139						SCH5636_REG_FAN_CTRL(i), val);
    140		}
    141	}
    142
    143	data->last_updated = jiffies;
    144	data->valid = true;
    145abort:
    146	mutex_unlock(&data->update_lock);
    147	return ret;
    148}
    149
    150static int reg_to_rpm(u16 reg)
    151{
    152	if (reg == 0)
    153		return -EIO;
    154	if (reg == 0xffff)
    155		return 0;
    156
    157	return 5400540 / reg;
    158}
    159
    160static ssize_t name_show(struct device *dev, struct device_attribute *devattr,
    161			 char *buf)
    162{
    163	return sysfs_emit(buf, "%s\n", DEVNAME);
    164}
    165
    166static ssize_t in_value_show(struct device *dev,
    167			     struct device_attribute *devattr, char *buf)
    168{
    169	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
    170	struct sch5636_data *data = sch5636_update_device(dev);
    171	int val;
    172
    173	if (IS_ERR(data))
    174		return PTR_ERR(data);
    175
    176	val = DIV_ROUND_CLOSEST(
    177		data->in[attr->index] * SCH5636_REG_IN_FACTORS[attr->index],
    178		255);
    179	return sysfs_emit(buf, "%d\n", val);
    180}
    181
    182static ssize_t in_label_show(struct device *dev,
    183			     struct device_attribute *devattr, char *buf)
    184{
    185	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
    186
    187	return sysfs_emit(buf, "%s\n",
    188			  SCH5636_IN_LABELS[attr->index]);
    189}
    190
    191static ssize_t temp_value_show(struct device *dev,
    192			       struct device_attribute *devattr, char *buf)
    193{
    194	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
    195	struct sch5636_data *data = sch5636_update_device(dev);
    196	int val;
    197
    198	if (IS_ERR(data))
    199		return PTR_ERR(data);
    200
    201	val = (data->temp_val[attr->index] - 64) * 1000;
    202	return sysfs_emit(buf, "%d\n", val);
    203}
    204
    205static ssize_t temp_fault_show(struct device *dev,
    206			       struct device_attribute *devattr, char *buf)
    207{
    208	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
    209	struct sch5636_data *data = sch5636_update_device(dev);
    210	int val;
    211
    212	if (IS_ERR(data))
    213		return PTR_ERR(data);
    214
    215	val = (data->temp_ctrl[attr->index] & SCH5636_TEMP_WORKING) ? 0 : 1;
    216	return sysfs_emit(buf, "%d\n", val);
    217}
    218
    219static ssize_t temp_alarm_show(struct device *dev,
    220			       struct device_attribute *devattr, char *buf)
    221{
    222	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
    223	struct sch5636_data *data = sch5636_update_device(dev);
    224	int val;
    225
    226	if (IS_ERR(data))
    227		return PTR_ERR(data);
    228
    229	val = (data->temp_ctrl[attr->index] & SCH5636_TEMP_ALARM) ? 1 : 0;
    230	return sysfs_emit(buf, "%d\n", val);
    231}
    232
    233static ssize_t fan_value_show(struct device *dev,
    234			      struct device_attribute *devattr, char *buf)
    235{
    236	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
    237	struct sch5636_data *data = sch5636_update_device(dev);
    238	int val;
    239
    240	if (IS_ERR(data))
    241		return PTR_ERR(data);
    242
    243	val = reg_to_rpm(data->fan_val[attr->index]);
    244	if (val < 0)
    245		return val;
    246
    247	return sysfs_emit(buf, "%d\n", val);
    248}
    249
    250static ssize_t fan_fault_show(struct device *dev,
    251			      struct device_attribute *devattr, char *buf)
    252{
    253	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
    254	struct sch5636_data *data = sch5636_update_device(dev);
    255	int val;
    256
    257	if (IS_ERR(data))
    258		return PTR_ERR(data);
    259
    260	val = (data->fan_ctrl[attr->index] & SCH5636_FAN_NOT_PRESENT) ? 1 : 0;
    261	return sysfs_emit(buf, "%d\n", val);
    262}
    263
    264static ssize_t fan_alarm_show(struct device *dev,
    265			      struct device_attribute *devattr, char *buf)
    266{
    267	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
    268	struct sch5636_data *data = sch5636_update_device(dev);
    269	int val;
    270
    271	if (IS_ERR(data))
    272		return PTR_ERR(data);
    273
    274	val = (data->fan_ctrl[attr->index] & SCH5636_FAN_ALARM) ? 1 : 0;
    275	return sysfs_emit(buf, "%d\n", val);
    276}
    277
    278static struct sensor_device_attribute sch5636_attr[] = {
    279	SENSOR_ATTR_RO(name, name, 0),
    280	SENSOR_ATTR_RO(in0_input, in_value, 0),
    281	SENSOR_ATTR_RO(in0_label, in_label, 0),
    282	SENSOR_ATTR_RO(in1_input, in_value, 1),
    283	SENSOR_ATTR_RO(in1_label, in_label, 1),
    284	SENSOR_ATTR_RO(in2_input, in_value, 2),
    285	SENSOR_ATTR_RO(in2_label, in_label, 2),
    286	SENSOR_ATTR_RO(in3_input, in_value, 3),
    287	SENSOR_ATTR_RO(in3_label, in_label, 3),
    288	SENSOR_ATTR_RO(in4_input, in_value, 4),
    289	SENSOR_ATTR_RO(in4_label, in_label, 4),
    290};
    291
    292static struct sensor_device_attribute sch5636_temp_attr[] = {
    293	SENSOR_ATTR_RO(temp1_input, temp_value, 0),
    294	SENSOR_ATTR_RO(temp1_fault, temp_fault, 0),
    295	SENSOR_ATTR_RO(temp1_alarm, temp_alarm, 0),
    296	SENSOR_ATTR_RO(temp2_input, temp_value, 1),
    297	SENSOR_ATTR_RO(temp2_fault, temp_fault, 1),
    298	SENSOR_ATTR_RO(temp2_alarm, temp_alarm, 1),
    299	SENSOR_ATTR_RO(temp3_input, temp_value, 2),
    300	SENSOR_ATTR_RO(temp3_fault, temp_fault, 2),
    301	SENSOR_ATTR_RO(temp3_alarm, temp_alarm, 2),
    302	SENSOR_ATTR_RO(temp4_input, temp_value, 3),
    303	SENSOR_ATTR_RO(temp4_fault, temp_fault, 3),
    304	SENSOR_ATTR_RO(temp4_alarm, temp_alarm, 3),
    305	SENSOR_ATTR_RO(temp5_input, temp_value, 4),
    306	SENSOR_ATTR_RO(temp5_fault, temp_fault, 4),
    307	SENSOR_ATTR_RO(temp5_alarm, temp_alarm, 4),
    308	SENSOR_ATTR_RO(temp6_input, temp_value, 5),
    309	SENSOR_ATTR_RO(temp6_fault, temp_fault, 5),
    310	SENSOR_ATTR_RO(temp6_alarm, temp_alarm, 5),
    311	SENSOR_ATTR_RO(temp7_input, temp_value, 6),
    312	SENSOR_ATTR_RO(temp7_fault, temp_fault, 6),
    313	SENSOR_ATTR_RO(temp7_alarm, temp_alarm, 6),
    314	SENSOR_ATTR_RO(temp8_input, temp_value, 7),
    315	SENSOR_ATTR_RO(temp8_fault, temp_fault, 7),
    316	SENSOR_ATTR_RO(temp8_alarm, temp_alarm, 7),
    317	SENSOR_ATTR_RO(temp9_input, temp_value, 8),
    318	SENSOR_ATTR_RO(temp9_fault, temp_fault, 8),
    319	SENSOR_ATTR_RO(temp9_alarm, temp_alarm, 8),
    320	SENSOR_ATTR_RO(temp10_input, temp_value, 9),
    321	SENSOR_ATTR_RO(temp10_fault, temp_fault, 9),
    322	SENSOR_ATTR_RO(temp10_alarm, temp_alarm, 9),
    323	SENSOR_ATTR_RO(temp11_input, temp_value, 10),
    324	SENSOR_ATTR_RO(temp11_fault, temp_fault, 10),
    325	SENSOR_ATTR_RO(temp11_alarm, temp_alarm, 10),
    326	SENSOR_ATTR_RO(temp12_input, temp_value, 11),
    327	SENSOR_ATTR_RO(temp12_fault, temp_fault, 11),
    328	SENSOR_ATTR_RO(temp12_alarm, temp_alarm, 11),
    329	SENSOR_ATTR_RO(temp13_input, temp_value, 12),
    330	SENSOR_ATTR_RO(temp13_fault, temp_fault, 12),
    331	SENSOR_ATTR_RO(temp13_alarm, temp_alarm, 12),
    332	SENSOR_ATTR_RO(temp14_input, temp_value, 13),
    333	SENSOR_ATTR_RO(temp14_fault, temp_fault, 13),
    334	SENSOR_ATTR_RO(temp14_alarm, temp_alarm, 13),
    335	SENSOR_ATTR_RO(temp15_input, temp_value, 14),
    336	SENSOR_ATTR_RO(temp15_fault, temp_fault, 14),
    337	SENSOR_ATTR_RO(temp15_alarm, temp_alarm, 14),
    338	SENSOR_ATTR_RO(temp16_input, temp_value, 15),
    339	SENSOR_ATTR_RO(temp16_fault, temp_fault, 15),
    340	SENSOR_ATTR_RO(temp16_alarm, temp_alarm, 15),
    341};
    342
    343static struct sensor_device_attribute sch5636_fan_attr[] = {
    344	SENSOR_ATTR_RO(fan1_input, fan_value, 0),
    345	SENSOR_ATTR_RO(fan1_fault, fan_fault, 0),
    346	SENSOR_ATTR_RO(fan1_alarm, fan_alarm, 0),
    347	SENSOR_ATTR_RO(fan2_input, fan_value, 1),
    348	SENSOR_ATTR_RO(fan2_fault, fan_fault, 1),
    349	SENSOR_ATTR_RO(fan2_alarm, fan_alarm, 1),
    350	SENSOR_ATTR_RO(fan3_input, fan_value, 2),
    351	SENSOR_ATTR_RO(fan3_fault, fan_fault, 2),
    352	SENSOR_ATTR_RO(fan3_alarm, fan_alarm, 2),
    353	SENSOR_ATTR_RO(fan4_input, fan_value, 3),
    354	SENSOR_ATTR_RO(fan4_fault, fan_fault, 3),
    355	SENSOR_ATTR_RO(fan4_alarm, fan_alarm, 3),
    356	SENSOR_ATTR_RO(fan5_input, fan_value, 4),
    357	SENSOR_ATTR_RO(fan5_fault, fan_fault, 4),
    358	SENSOR_ATTR_RO(fan5_alarm, fan_alarm, 4),
    359	SENSOR_ATTR_RO(fan6_input, fan_value, 5),
    360	SENSOR_ATTR_RO(fan6_fault, fan_fault, 5),
    361	SENSOR_ATTR_RO(fan6_alarm, fan_alarm, 5),
    362	SENSOR_ATTR_RO(fan7_input, fan_value, 6),
    363	SENSOR_ATTR_RO(fan7_fault, fan_fault, 6),
    364	SENSOR_ATTR_RO(fan7_alarm, fan_alarm, 6),
    365	SENSOR_ATTR_RO(fan8_input, fan_value, 7),
    366	SENSOR_ATTR_RO(fan8_fault, fan_fault, 7),
    367	SENSOR_ATTR_RO(fan8_alarm, fan_alarm, 7),
    368};
    369
    370static int sch5636_remove(struct platform_device *pdev)
    371{
    372	struct sch5636_data *data = platform_get_drvdata(pdev);
    373	int i;
    374
    375	if (data->hwmon_dev)
    376		hwmon_device_unregister(data->hwmon_dev);
    377
    378	for (i = 0; i < ARRAY_SIZE(sch5636_attr); i++)
    379		device_remove_file(&pdev->dev, &sch5636_attr[i].dev_attr);
    380
    381	for (i = 0; i < SCH5636_NO_TEMPS * 3; i++)
    382		device_remove_file(&pdev->dev,
    383				   &sch5636_temp_attr[i].dev_attr);
    384
    385	for (i = 0; i < SCH5636_NO_FANS * 3; i++)
    386		device_remove_file(&pdev->dev,
    387				   &sch5636_fan_attr[i].dev_attr);
    388
    389	return 0;
    390}
    391
    392static int sch5636_probe(struct platform_device *pdev)
    393{
    394	struct sch5636_data *data;
    395	int i, err, val, revision[2];
    396	char id[4];
    397
    398	data = devm_kzalloc(&pdev->dev, sizeof(struct sch5636_data),
    399			    GFP_KERNEL);
    400	if (!data)
    401		return -ENOMEM;
    402
    403	data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
    404	mutex_init(&data->update_lock);
    405	platform_set_drvdata(pdev, data);
    406
    407	for (i = 0; i < 3; i++) {
    408		val = sch56xx_read_virtual_reg(data->addr,
    409					       SCH5636_REG_FUJITSU_ID + i);
    410		if (val < 0) {
    411			pr_err("Could not read Fujitsu id byte at %#x\n",
    412				SCH5636_REG_FUJITSU_ID + i);
    413			err = val;
    414			goto error;
    415		}
    416		id[i] = val;
    417	}
    418	id[i] = '\0';
    419
    420	if (strcmp(id, "THS")) {
    421		pr_err("Unknown Fujitsu id: %02x%02x%02x\n",
    422		       id[0], id[1], id[2]);
    423		err = -ENODEV;
    424		goto error;
    425	}
    426
    427	for (i = 0; i < 2; i++) {
    428		val = sch56xx_read_virtual_reg(data->addr,
    429					       SCH5636_REG_FUJITSU_REV + i);
    430		if (val < 0) {
    431			err = val;
    432			goto error;
    433		}
    434		revision[i] = val;
    435	}
    436	pr_info("Found %s chip at %#hx, revision: %d.%02d\n", DEVNAME,
    437		data->addr, revision[0], revision[1]);
    438
    439	/* Read all temp + fan ctrl registers to determine which are active */
    440	for (i = 0; i < SCH5636_NO_TEMPS; i++) {
    441		val = sch56xx_read_virtual_reg(data->addr,
    442					       SCH5636_REG_TEMP_CTRL(i));
    443		if (unlikely(val < 0)) {
    444			err = val;
    445			goto error;
    446		}
    447		data->temp_ctrl[i] = val;
    448	}
    449
    450	for (i = 0; i < SCH5636_NO_FANS; i++) {
    451		val = sch56xx_read_virtual_reg(data->addr,
    452					       SCH5636_REG_FAN_CTRL(i));
    453		if (unlikely(val < 0)) {
    454			err = val;
    455			goto error;
    456		}
    457		data->fan_ctrl[i] = val;
    458	}
    459
    460	for (i = 0; i < ARRAY_SIZE(sch5636_attr); i++) {
    461		err = device_create_file(&pdev->dev,
    462					 &sch5636_attr[i].dev_attr);
    463		if (err)
    464			goto error;
    465	}
    466
    467	for (i = 0; i < (SCH5636_NO_TEMPS * 3); i++) {
    468		if (data->temp_ctrl[i/3] & SCH5636_TEMP_DEACTIVATED)
    469			continue;
    470
    471		err = device_create_file(&pdev->dev,
    472					&sch5636_temp_attr[i].dev_attr);
    473		if (err)
    474			goto error;
    475	}
    476
    477	for (i = 0; i < (SCH5636_NO_FANS * 3); i++) {
    478		if (data->fan_ctrl[i/3] & SCH5636_FAN_DEACTIVATED)
    479			continue;
    480
    481		err = device_create_file(&pdev->dev,
    482					&sch5636_fan_attr[i].dev_attr);
    483		if (err)
    484			goto error;
    485	}
    486
    487	data->hwmon_dev = hwmon_device_register(&pdev->dev);
    488	if (IS_ERR(data->hwmon_dev)) {
    489		err = PTR_ERR(data->hwmon_dev);
    490		data->hwmon_dev = NULL;
    491		goto error;
    492	}
    493
    494	/* Note failing to register the watchdog is not a fatal error */
    495	sch56xx_watchdog_register(&pdev->dev, data->addr, (revision[0] << 8) | revision[1],
    496				  &data->update_lock, 0);
    497
    498	return 0;
    499
    500error:
    501	sch5636_remove(pdev);
    502	return err;
    503}
    504
    505static const struct platform_device_id sch5636_device_id[] = {
    506	{
    507		.name = "sch5636",
    508	},
    509	{ }
    510};
    511MODULE_DEVICE_TABLE(platform, sch5636_device_id);
    512
    513static struct platform_driver sch5636_driver = {
    514	.driver = {
    515		.name	= DRVNAME,
    516	},
    517	.probe		= sch5636_probe,
    518	.remove		= sch5636_remove,
    519	.id_table	= sch5636_device_id,
    520};
    521
    522module_platform_driver(sch5636_driver);
    523
    524MODULE_DESCRIPTION("SMSC SCH5636 Hardware Monitoring Driver");
    525MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
    526MODULE_LICENSE("GPL");