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

max6642.c (8366B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Driver for +/-1 degree C, SMBus-Compatible Remote/Local Temperature Sensor
      4 * with Overtemperature Alarm
      5 *
      6 * Copyright (C) 2011 AppearTV AS
      7 *
      8 * Derived from:
      9 *
     10 *  Based on the max1619 driver.
     11 *  Copyright (C) 2003-2004 Oleksij Rempel <bug-track@fisher-privat.net>
     12 *                          Jean Delvare <jdelvare@suse.de>
     13 *
     14 * The MAX6642 is a sensor chip made by Maxim.
     15 * It reports up to two temperatures (its own plus up to
     16 * one external one). Complete datasheet can be
     17 * obtained from Maxim's website at:
     18 *   http://datasheets.maxim-ic.com/en/ds/MAX6642.pdf
     19 */
     20
     21
     22#include <linux/module.h>
     23#include <linux/init.h>
     24#include <linux/slab.h>
     25#include <linux/jiffies.h>
     26#include <linux/i2c.h>
     27#include <linux/hwmon.h>
     28#include <linux/hwmon-sysfs.h>
     29#include <linux/err.h>
     30#include <linux/mutex.h>
     31#include <linux/sysfs.h>
     32
     33static const unsigned short normal_i2c[] = {
     34	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
     35
     36/*
     37 * The MAX6642 registers
     38 */
     39
     40#define MAX6642_REG_R_MAN_ID		0xFE
     41#define MAX6642_REG_R_CONFIG		0x03
     42#define MAX6642_REG_W_CONFIG		0x09
     43#define MAX6642_REG_R_STATUS		0x02
     44#define MAX6642_REG_R_LOCAL_TEMP	0x00
     45#define MAX6642_REG_R_LOCAL_TEMPL	0x11
     46#define MAX6642_REG_R_LOCAL_HIGH	0x05
     47#define MAX6642_REG_W_LOCAL_HIGH	0x0B
     48#define MAX6642_REG_R_REMOTE_TEMP	0x01
     49#define MAX6642_REG_R_REMOTE_TEMPL	0x10
     50#define MAX6642_REG_R_REMOTE_HIGH	0x07
     51#define MAX6642_REG_W_REMOTE_HIGH	0x0D
     52
     53/*
     54 * Conversions
     55 */
     56
     57static int temp_from_reg10(int val)
     58{
     59	return val * 250;
     60}
     61
     62static int temp_from_reg(int val)
     63{
     64	return val * 1000;
     65}
     66
     67static int temp_to_reg(int val)
     68{
     69	return val / 1000;
     70}
     71
     72/*
     73 * Client data (each client gets its own)
     74 */
     75
     76struct max6642_data {
     77	struct i2c_client *client;
     78	struct mutex update_lock;
     79	bool valid; /* zero until following fields are valid */
     80	unsigned long last_updated; /* in jiffies */
     81
     82	/* registers values */
     83	u16 temp_input[2]; /* local/remote */
     84	u16 temp_high[2]; /* local/remote */
     85	u8 alarms;
     86};
     87
     88/*
     89 * Real code
     90 */
     91
     92static void max6642_init_client(struct max6642_data *data,
     93				struct i2c_client *client)
     94{
     95	u8 config;
     96
     97	/*
     98	 * Start the conversions.
     99	 */
    100	config = i2c_smbus_read_byte_data(client, MAX6642_REG_R_CONFIG);
    101	if (config & 0x40)
    102		i2c_smbus_write_byte_data(client, MAX6642_REG_W_CONFIG,
    103					  config & 0xBF); /* run */
    104
    105	data->temp_high[0] = i2c_smbus_read_byte_data(client,
    106				MAX6642_REG_R_LOCAL_HIGH);
    107	data->temp_high[1] = i2c_smbus_read_byte_data(client,
    108				MAX6642_REG_R_REMOTE_HIGH);
    109}
    110
    111/* Return 0 if detection is successful, -ENODEV otherwise */
    112static int max6642_detect(struct i2c_client *client,
    113			  struct i2c_board_info *info)
    114{
    115	struct i2c_adapter *adapter = client->adapter;
    116	u8 reg_config, reg_status, man_id;
    117
    118	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
    119		return -ENODEV;
    120
    121	/* identification */
    122	man_id = i2c_smbus_read_byte_data(client, MAX6642_REG_R_MAN_ID);
    123	if (man_id != 0x4D)
    124		return -ENODEV;
    125
    126	/* sanity check */
    127	if (i2c_smbus_read_byte_data(client, 0x04) != 0x4D
    128	    || i2c_smbus_read_byte_data(client, 0x06) != 0x4D
    129	    || i2c_smbus_read_byte_data(client, 0xff) != 0x4D)
    130		return -ENODEV;
    131
    132	/*
    133	 * We read the config and status register, the 4 lower bits in the
    134	 * config register should be zero and bit 5, 3, 1 and 0 should be
    135	 * zero in the status register.
    136	 */
    137	reg_config = i2c_smbus_read_byte_data(client, MAX6642_REG_R_CONFIG);
    138	if ((reg_config & 0x0f) != 0x00)
    139		return -ENODEV;
    140
    141	/* in between, another round of sanity checks */
    142	if (i2c_smbus_read_byte_data(client, 0x04) != reg_config
    143	    || i2c_smbus_read_byte_data(client, 0x06) != reg_config
    144	    || i2c_smbus_read_byte_data(client, 0xff) != reg_config)
    145		return -ENODEV;
    146
    147	reg_status = i2c_smbus_read_byte_data(client, MAX6642_REG_R_STATUS);
    148	if ((reg_status & 0x2b) != 0x00)
    149		return -ENODEV;
    150
    151	strlcpy(info->type, "max6642", I2C_NAME_SIZE);
    152
    153	return 0;
    154}
    155
    156static struct max6642_data *max6642_update_device(struct device *dev)
    157{
    158	struct max6642_data *data = dev_get_drvdata(dev);
    159	struct i2c_client *client = data->client;
    160	u16 val, tmp;
    161
    162	mutex_lock(&data->update_lock);
    163
    164	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
    165		dev_dbg(dev, "Updating max6642 data.\n");
    166		val = i2c_smbus_read_byte_data(client,
    167					MAX6642_REG_R_LOCAL_TEMPL);
    168		tmp = (val >> 6) & 3;
    169		val = i2c_smbus_read_byte_data(client,
    170					MAX6642_REG_R_LOCAL_TEMP);
    171		val = (val << 2) | tmp;
    172		data->temp_input[0] = val;
    173		val = i2c_smbus_read_byte_data(client,
    174					MAX6642_REG_R_REMOTE_TEMPL);
    175		tmp = (val >> 6) & 3;
    176		val = i2c_smbus_read_byte_data(client,
    177					MAX6642_REG_R_REMOTE_TEMP);
    178		val = (val << 2) | tmp;
    179		data->temp_input[1] = val;
    180		data->alarms = i2c_smbus_read_byte_data(client,
    181					MAX6642_REG_R_STATUS);
    182
    183		data->last_updated = jiffies;
    184		data->valid = true;
    185	}
    186
    187	mutex_unlock(&data->update_lock);
    188
    189	return data;
    190}
    191
    192/*
    193 * Sysfs stuff
    194 */
    195
    196static ssize_t temp_max10_show(struct device *dev,
    197			       struct device_attribute *dev_attr, char *buf)
    198{
    199	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
    200	struct max6642_data *data = max6642_update_device(dev);
    201
    202	return sprintf(buf, "%d\n",
    203		       temp_from_reg10(data->temp_input[attr->index]));
    204}
    205
    206static ssize_t temp_max_show(struct device *dev,
    207			     struct device_attribute *attr, char *buf)
    208{
    209	struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr);
    210	struct max6642_data *data = max6642_update_device(dev);
    211
    212	return sprintf(buf, "%d\n", temp_from_reg(data->temp_high[attr2->nr]));
    213}
    214
    215static ssize_t temp_max_store(struct device *dev,
    216			      struct device_attribute *attr, const char *buf,
    217			      size_t count)
    218{
    219	struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr);
    220	struct max6642_data *data = dev_get_drvdata(dev);
    221	unsigned long val;
    222	int err;
    223
    224	err = kstrtoul(buf, 10, &val);
    225	if (err < 0)
    226		return err;
    227
    228	mutex_lock(&data->update_lock);
    229	data->temp_high[attr2->nr] = clamp_val(temp_to_reg(val), 0, 255);
    230	i2c_smbus_write_byte_data(data->client, attr2->index,
    231				  data->temp_high[attr2->nr]);
    232	mutex_unlock(&data->update_lock);
    233	return count;
    234}
    235
    236static ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
    237			  char *buf)
    238{
    239	int bitnr = to_sensor_dev_attr(attr)->index;
    240	struct max6642_data *data = max6642_update_device(dev);
    241	return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1);
    242}
    243
    244static SENSOR_DEVICE_ATTR_RO(temp1_input, temp_max10, 0);
    245static SENSOR_DEVICE_ATTR_RO(temp2_input, temp_max10, 1);
    246static SENSOR_DEVICE_ATTR_2_RW(temp1_max, temp_max, 0,
    247			       MAX6642_REG_W_LOCAL_HIGH);
    248static SENSOR_DEVICE_ATTR_2_RW(temp2_max, temp_max, 1,
    249			       MAX6642_REG_W_REMOTE_HIGH);
    250static SENSOR_DEVICE_ATTR_RO(temp2_fault, alarm, 2);
    251static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 6);
    252static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, alarm, 4);
    253
    254static struct attribute *max6642_attrs[] = {
    255	&sensor_dev_attr_temp1_input.dev_attr.attr,
    256	&sensor_dev_attr_temp2_input.dev_attr.attr,
    257	&sensor_dev_attr_temp1_max.dev_attr.attr,
    258	&sensor_dev_attr_temp2_max.dev_attr.attr,
    259
    260	&sensor_dev_attr_temp2_fault.dev_attr.attr,
    261	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
    262	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
    263	NULL
    264};
    265ATTRIBUTE_GROUPS(max6642);
    266
    267static int max6642_probe(struct i2c_client *client)
    268{
    269	struct device *dev = &client->dev;
    270	struct max6642_data *data;
    271	struct device *hwmon_dev;
    272
    273	data = devm_kzalloc(dev, sizeof(struct max6642_data), GFP_KERNEL);
    274	if (!data)
    275		return -ENOMEM;
    276
    277	data->client = client;
    278	mutex_init(&data->update_lock);
    279
    280	/* Initialize the MAX6642 chip */
    281	max6642_init_client(data, client);
    282
    283	hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
    284							   client->name, data,
    285							   max6642_groups);
    286	return PTR_ERR_OR_ZERO(hwmon_dev);
    287}
    288
    289/*
    290 * Driver data (common to all clients)
    291 */
    292
    293static const struct i2c_device_id max6642_id[] = {
    294	{ "max6642", 0 },
    295	{ }
    296};
    297MODULE_DEVICE_TABLE(i2c, max6642_id);
    298
    299static struct i2c_driver max6642_driver = {
    300	.class		= I2C_CLASS_HWMON,
    301	.driver = {
    302		.name	= "max6642",
    303	},
    304	.probe_new	= max6642_probe,
    305	.id_table	= max6642_id,
    306	.detect		= max6642_detect,
    307	.address_list	= normal_i2c,
    308};
    309
    310module_i2c_driver(max6642_driver);
    311
    312MODULE_AUTHOR("Per Dalen <per.dalen@appeartv.com>");
    313MODULE_DESCRIPTION("MAX6642 sensor driver");
    314MODULE_LICENSE("GPL");