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

lm92.c (9630B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * lm92 - Hardware monitoring driver
      4 * Copyright (C) 2005-2008  Jean Delvare <jdelvare@suse.de>
      5 *
      6 * Based on the lm90 driver, with some ideas taken from the lm_sensors
      7 * lm92 driver as well.
      8 *
      9 * The LM92 is a sensor chip made by National Semiconductor. It reports
     10 * its own temperature with a 0.0625 deg resolution and a 0.33 deg
     11 * accuracy. Complete datasheet can be obtained from National's website
     12 * at:
     13 *   http://www.national.com/pf/LM/LM92.html
     14 *
     15 * This driver also supports the MAX6635 sensor chip made by Maxim.
     16 * This chip is compatible with the LM92, but has a lesser accuracy
     17 * (1.0 deg). Complete datasheet can be obtained from Maxim's website
     18 * at:
     19 *   http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3074
     20 *
     21 * Since the LM92 was the first chipset supported by this driver, most
     22 * comments will refer to this chipset, but are actually general and
     23 * concern all supported chipsets, unless mentioned otherwise.
     24 *
     25 * Support could easily be added for the National Semiconductor LM76
     26 * and Maxim MAX6633 and MAX6634 chips, which are mostly compatible
     27 * with the LM92.
     28 */
     29
     30#include <linux/module.h>
     31#include <linux/init.h>
     32#include <linux/slab.h>
     33#include <linux/i2c.h>
     34#include <linux/hwmon.h>
     35#include <linux/hwmon-sysfs.h>
     36#include <linux/err.h>
     37#include <linux/mutex.h>
     38#include <linux/jiffies.h>
     39
     40/*
     41 * The LM92 and MAX6635 have 2 two-state pins for address selection,
     42 * resulting in 4 possible addresses.
     43 */
     44static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
     45						I2C_CLIENT_END };
     46enum chips { lm92, max6635 };
     47
     48/* The LM92 registers */
     49#define LM92_REG_CONFIG			0x01 /* 8-bit, RW */
     50#define LM92_REG_TEMP			0x00 /* 16-bit, RO */
     51#define LM92_REG_TEMP_HYST		0x02 /* 16-bit, RW */
     52#define LM92_REG_TEMP_CRIT		0x03 /* 16-bit, RW */
     53#define LM92_REG_TEMP_LOW		0x04 /* 16-bit, RW */
     54#define LM92_REG_TEMP_HIGH		0x05 /* 16-bit, RW */
     55#define LM92_REG_MAN_ID			0x07 /* 16-bit, RO, LM92 only */
     56
     57/*
     58 * The LM92 uses signed 13-bit values with LSB = 0.0625 degree Celsius,
     59 * left-justified in 16-bit registers. No rounding is done, with such
     60 * a resolution it's just not worth it. Note that the MAX6635 doesn't
     61 * make use of the 4 lower bits for limits (i.e. effective resolution
     62 * for limits is 1 degree Celsius).
     63 */
     64static inline int TEMP_FROM_REG(s16 reg)
     65{
     66	return reg / 8 * 625 / 10;
     67}
     68
     69static inline s16 TEMP_TO_REG(long val)
     70{
     71	val = clamp_val(val, -60000, 160000);
     72	return val * 10 / 625 * 8;
     73}
     74
     75/* Alarm flags are stored in the 3 LSB of the temperature register */
     76static inline u8 ALARMS_FROM_REG(s16 reg)
     77{
     78	return reg & 0x0007;
     79}
     80
     81enum temp_index {
     82	t_input,
     83	t_crit,
     84	t_min,
     85	t_max,
     86	t_hyst,
     87	t_num_regs
     88};
     89
     90static const u8 regs[t_num_regs] = {
     91	[t_input] = LM92_REG_TEMP,
     92	[t_crit] = LM92_REG_TEMP_CRIT,
     93	[t_min] = LM92_REG_TEMP_LOW,
     94	[t_max] = LM92_REG_TEMP_HIGH,
     95	[t_hyst] = LM92_REG_TEMP_HYST,
     96};
     97
     98/* Client data (each client gets its own) */
     99struct lm92_data {
    100	struct i2c_client *client;
    101	struct mutex update_lock;
    102	bool valid; /* false until following fields are valid */
    103	unsigned long last_updated; /* in jiffies */
    104
    105	/* registers values */
    106	s16 temp[t_num_regs];	/* index with enum temp_index */
    107};
    108
    109/*
    110 * Sysfs attributes and callback functions
    111 */
    112
    113static struct lm92_data *lm92_update_device(struct device *dev)
    114{
    115	struct lm92_data *data = dev_get_drvdata(dev);
    116	struct i2c_client *client = data->client;
    117	int i;
    118
    119	mutex_lock(&data->update_lock);
    120
    121	if (time_after(jiffies, data->last_updated + HZ) ||
    122	    !data->valid) {
    123		dev_dbg(&client->dev, "Updating lm92 data\n");
    124		for (i = 0; i < t_num_regs; i++) {
    125			data->temp[i] =
    126				i2c_smbus_read_word_swapped(client, regs[i]);
    127		}
    128		data->last_updated = jiffies;
    129		data->valid = true;
    130	}
    131
    132	mutex_unlock(&data->update_lock);
    133
    134	return data;
    135}
    136
    137static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
    138			 char *buf)
    139{
    140	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
    141	struct lm92_data *data = lm92_update_device(dev);
    142
    143	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]));
    144}
    145
    146static ssize_t temp_store(struct device *dev,
    147			  struct device_attribute *devattr, const char *buf,
    148			  size_t count)
    149{
    150	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
    151	struct lm92_data *data = dev_get_drvdata(dev);
    152	struct i2c_client *client = data->client;
    153	int nr = attr->index;
    154	long val;
    155	int err;
    156
    157	err = kstrtol(buf, 10, &val);
    158	if (err)
    159		return err;
    160
    161	mutex_lock(&data->update_lock);
    162	data->temp[nr] = TEMP_TO_REG(val);
    163	i2c_smbus_write_word_swapped(client, regs[nr], data->temp[nr]);
    164	mutex_unlock(&data->update_lock);
    165	return count;
    166}
    167
    168static ssize_t temp_hyst_show(struct device *dev,
    169			      struct device_attribute *devattr, char *buf)
    170{
    171	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
    172	struct lm92_data *data = lm92_update_device(dev);
    173
    174	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index])
    175		       - TEMP_FROM_REG(data->temp[t_hyst]));
    176}
    177
    178static ssize_t temp1_min_hyst_show(struct device *dev,
    179				   struct device_attribute *attr, char *buf)
    180{
    181	struct lm92_data *data = lm92_update_device(dev);
    182
    183	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[t_min])
    184		       + TEMP_FROM_REG(data->temp[t_hyst]));
    185}
    186
    187static ssize_t temp_hyst_store(struct device *dev,
    188			       struct device_attribute *devattr,
    189			       const char *buf, size_t count)
    190{
    191	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
    192	struct lm92_data *data = dev_get_drvdata(dev);
    193	struct i2c_client *client = data->client;
    194	long val;
    195	int err;
    196
    197	err = kstrtol(buf, 10, &val);
    198	if (err)
    199		return err;
    200
    201	val = clamp_val(val, -120000, 220000);
    202	mutex_lock(&data->update_lock);
    203	data->temp[t_hyst] =
    204		TEMP_TO_REG(TEMP_FROM_REG(data->temp[attr->index]) - val);
    205	i2c_smbus_write_word_swapped(client, LM92_REG_TEMP_HYST,
    206				     data->temp[t_hyst]);
    207	mutex_unlock(&data->update_lock);
    208	return count;
    209}
    210
    211static ssize_t alarms_show(struct device *dev, struct device_attribute *attr,
    212			   char *buf)
    213{
    214	struct lm92_data *data = lm92_update_device(dev);
    215
    216	return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->temp[t_input]));
    217}
    218
    219static ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
    220			  char *buf)
    221{
    222	int bitnr = to_sensor_dev_attr(attr)->index;
    223	struct lm92_data *data = lm92_update_device(dev);
    224	return sprintf(buf, "%d\n", (data->temp[t_input] >> bitnr) & 1);
    225}
    226
    227static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, t_input);
    228static SENSOR_DEVICE_ATTR_RW(temp1_crit, temp, t_crit);
    229static SENSOR_DEVICE_ATTR_RW(temp1_crit_hyst, temp_hyst, t_crit);
    230static SENSOR_DEVICE_ATTR_RW(temp1_min, temp, t_min);
    231static DEVICE_ATTR_RO(temp1_min_hyst);
    232static SENSOR_DEVICE_ATTR_RW(temp1_max, temp, t_max);
    233static SENSOR_DEVICE_ATTR_RO(temp1_max_hyst, temp_hyst, t_max);
    234static DEVICE_ATTR_RO(alarms);
    235static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 2);
    236static SENSOR_DEVICE_ATTR_RO(temp1_min_alarm, alarm, 0);
    237static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 1);
    238
    239/*
    240 * Detection and registration
    241 */
    242
    243static void lm92_init_client(struct i2c_client *client)
    244{
    245	u8 config;
    246
    247	/* Start the conversions if needed */
    248	config = i2c_smbus_read_byte_data(client, LM92_REG_CONFIG);
    249	if (config & 0x01)
    250		i2c_smbus_write_byte_data(client, LM92_REG_CONFIG,
    251					  config & 0xFE);
    252}
    253
    254static struct attribute *lm92_attrs[] = {
    255	&sensor_dev_attr_temp1_input.dev_attr.attr,
    256	&sensor_dev_attr_temp1_crit.dev_attr.attr,
    257	&sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
    258	&sensor_dev_attr_temp1_min.dev_attr.attr,
    259	&dev_attr_temp1_min_hyst.attr,
    260	&sensor_dev_attr_temp1_max.dev_attr.attr,
    261	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
    262	&dev_attr_alarms.attr,
    263	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
    264	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
    265	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
    266	NULL
    267};
    268ATTRIBUTE_GROUPS(lm92);
    269
    270/* Return 0 if detection is successful, -ENODEV otherwise */
    271static int lm92_detect(struct i2c_client *new_client,
    272		       struct i2c_board_info *info)
    273{
    274	struct i2c_adapter *adapter = new_client->adapter;
    275	u8 config;
    276	u16 man_id;
    277
    278	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
    279					    | I2C_FUNC_SMBUS_WORD_DATA))
    280		return -ENODEV;
    281
    282	config = i2c_smbus_read_byte_data(new_client, LM92_REG_CONFIG);
    283	man_id = i2c_smbus_read_word_data(new_client, LM92_REG_MAN_ID);
    284
    285	if ((config & 0xe0) == 0x00 && man_id == 0x0180)
    286		pr_info("lm92: Found National Semiconductor LM92 chip\n");
    287	else
    288		return -ENODEV;
    289
    290	strlcpy(info->type, "lm92", I2C_NAME_SIZE);
    291
    292	return 0;
    293}
    294
    295static int lm92_probe(struct i2c_client *new_client)
    296{
    297	struct device *hwmon_dev;
    298	struct lm92_data *data;
    299
    300	data = devm_kzalloc(&new_client->dev, sizeof(struct lm92_data),
    301			    GFP_KERNEL);
    302	if (!data)
    303		return -ENOMEM;
    304
    305	data->client = new_client;
    306	mutex_init(&data->update_lock);
    307
    308	/* Initialize the chipset */
    309	lm92_init_client(new_client);
    310
    311	hwmon_dev = devm_hwmon_device_register_with_groups(&new_client->dev,
    312							   new_client->name,
    313							   data, lm92_groups);
    314	return PTR_ERR_OR_ZERO(hwmon_dev);
    315}
    316
    317/*
    318 * Module and driver stuff
    319 */
    320
    321static const struct i2c_device_id lm92_id[] = {
    322	{ "lm92", lm92 },
    323	{ "max6635", max6635 },
    324	{ }
    325};
    326MODULE_DEVICE_TABLE(i2c, lm92_id);
    327
    328static struct i2c_driver lm92_driver = {
    329	.class		= I2C_CLASS_HWMON,
    330	.driver = {
    331		.name	= "lm92",
    332	},
    333	.probe_new	= lm92_probe,
    334	.id_table	= lm92_id,
    335	.detect		= lm92_detect,
    336	.address_list	= normal_i2c,
    337};
    338
    339module_i2c_driver(lm92_driver);
    340
    341MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");
    342MODULE_DESCRIPTION("LM92/MAX6635 driver");
    343MODULE_LICENSE("GPL");