brintos

brintos / linux-shallow public Read only

0
0
Text · 10.4 KiB · 0be439b Raw
439 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * lm92 - Hardware monitoring driver4 * Copyright (C) 2005-2008  Jean Delvare <jdelvare@suse.de>5 *6 * Based on the lm90 driver, with some ideas taken from the lm_sensors7 * lm92 driver as well.8 *9 * The LM92 is a sensor chip made by National Semiconductor. It reports10 * its own temperature with a 0.0625 deg resolution and a 0.33 deg11 * accuracy. Complete datasheet can be obtained from National's website12 * at:13 *   http://www.national.com/pf/LM/LM92.html14 *15 * This driver also supports the MAX6635 sensor chip made by Maxim.16 * This chip is compatible with the LM92, but has a lesser accuracy17 * (1.0 deg). Complete datasheet can be obtained from Maxim's website18 * at:19 *   http://www.maxim-ic.com/quick_view2.cfm/qv_pk/307420 *21 * Since the LM92 was the first chipset supported by this driver, most22 * comments will refer to this chipset, but are actually general and23 * concern all supported chipsets, unless mentioned otherwise.24 *25 * Support could easily be added for the National Semiconductor LM7626 * and Maxim MAX6633 and MAX6634 chips, which are mostly compatible27 * with the LM92.28 */29 30#include <linux/err.h>31#include <linux/hwmon.h>32#include <linux/i2c.h>33#include <linux/init.h>34#include <linux/module.h>35#include <linux/mutex.h>36#include <linux/regmap.h>37#include <linux/slab.h>38 39/*40 * The LM92 and MAX6635 have 2 two-state pins for address selection,41 * resulting in 4 possible addresses.42 */43static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,44						I2C_CLIENT_END };45/* The LM92 registers */46#define LM92_REG_CONFIG			0x01 /* 8-bit, RW */47#define LM92_REG_TEMP			0x00 /* 16-bit, RO */48#define LM92_REG_TEMP_HYST		0x02 /* 16-bit, RW */49#define LM92_REG_TEMP_CRIT		0x03 /* 16-bit, RW */50#define LM92_REG_TEMP_LOW		0x04 /* 16-bit, RW */51#define LM92_REG_TEMP_HIGH		0x05 /* 16-bit, RW */52#define LM92_REG_MAN_ID			0x07 /* 16-bit, RO, LM92 only */53 54/*55 * The LM92 uses signed 13-bit values with LSB = 0.0625 degree Celsius,56 * left-justified in 16-bit registers. No rounding is done, with such57 * a resolution it's just not worth it. Note that the MAX6635 doesn't58 * make use of the 4 lower bits for limits (i.e. effective resolution59 * for limits is 1 degree Celsius).60 */61static inline int TEMP_FROM_REG(s16 reg)62{63	return reg / 8 * 625 / 10;64}65 66static inline s16 TEMP_TO_REG(long val, int resolution)67{68	val = clamp_val(val, -60000, 160000);69	return DIV_ROUND_CLOSEST(val << (resolution - 9), 1000) << (16 - resolution);70}71 72/* Alarm flags are stored in the 3 LSB of the temperature register */73static inline u8 ALARMS_FROM_REG(s16 reg)74{75	return reg & 0x0007;76}77 78/* Client data (each client gets its own) */79struct lm92_data {80	struct regmap *regmap;81	struct mutex update_lock;82	int resolution;83};84 85static int lm92_temp_read(struct lm92_data *data, u32 attr, int channel, long *val)86{87	int reg = -1, hyst_reg = -1, alarm_bit = 0;88	struct regmap *regmap = data->regmap;89	u32 temp;90	int ret;91 92	switch (attr) {93	case hwmon_temp_input:94		reg = LM92_REG_TEMP;95		break;96	case hwmon_temp_min:97		reg = LM92_REG_TEMP_LOW;98		break;99	case hwmon_temp_max:100		reg = LM92_REG_TEMP_HIGH;101		break;102	case hwmon_temp_crit:103		reg = LM92_REG_TEMP_CRIT;104		break;105	case hwmon_temp_min_hyst:106		hyst_reg = LM92_REG_TEMP_LOW;107		break;108	case hwmon_temp_max_hyst:109		hyst_reg = LM92_REG_TEMP_HIGH;110		break;111	case hwmon_temp_crit_hyst:112		hyst_reg = LM92_REG_TEMP_CRIT;113		break;114	case hwmon_temp_min_alarm:115		alarm_bit = 0;116		break;117	case hwmon_temp_max_alarm:118		alarm_bit = 1;119		break;120	case hwmon_temp_crit_alarm:121		alarm_bit = 2;122		break;123	default:124		return -EOPNOTSUPP;125	}126	if (reg >= 0) {127		ret = regmap_read(regmap, reg, &temp);128		if (ret < 0)129			return ret;130		*val = TEMP_FROM_REG(temp);131	} else if (hyst_reg >= 0) {132		u32 regs[2] = { hyst_reg, LM92_REG_TEMP_HYST };133		u16 regvals[2];134 135		ret = regmap_multi_reg_read(regmap, regs, regvals, 2);136		if (ret)137			return ret;138		if (attr == hwmon_temp_min_hyst)139			*val = TEMP_FROM_REG(regvals[0]) + TEMP_FROM_REG(regvals[1]);140		else141			*val = TEMP_FROM_REG(regvals[0]) - TEMP_FROM_REG(regvals[1]);142	} else {143		ret = regmap_read(regmap, LM92_REG_TEMP, &temp);144		if (ret)145			return ret;146		*val = !!(temp & BIT(alarm_bit));147	}148	return 0;149}150 151static int lm92_chip_read(struct lm92_data *data, u32 attr, long *val)152{153	u32 temp;154	int ret;155 156	switch (attr) {157	case hwmon_chip_alarms:158		ret = regmap_read(data->regmap, LM92_REG_TEMP, &temp);159		if (ret)160			return ret;161		*val = ALARMS_FROM_REG(temp);162		break;163	default:164		return -EOPNOTSUPP;165	}166	return 0;167}168 169static int lm92_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,170		     int channel, long *val)171{172	struct lm92_data *data = dev_get_drvdata(dev);173 174	switch (type) {175	case hwmon_chip:176		return lm92_chip_read(data, attr, val);177	case hwmon_temp:178		return lm92_temp_read(data, attr, channel, val);179	default:180		return -EOPNOTSUPP;181	}182}183 184static int lm92_temp_write(struct lm92_data *data, u32 attr, long val)185{186	struct regmap *regmap = data->regmap;187	int reg, err;188	u32 temp;189 190	switch (attr) {191	case hwmon_temp_min:192		reg = LM92_REG_TEMP_LOW;193		break;194	case hwmon_temp_max:195		reg = LM92_REG_TEMP_HIGH;196		break;197	case hwmon_temp_crit:198		reg = LM92_REG_TEMP_CRIT;199		break;200	case hwmon_temp_crit_hyst:201		val = clamp_val(val, -120000, 220000);202		mutex_lock(&data->update_lock);203		err = regmap_read(regmap, LM92_REG_TEMP_CRIT, &temp);204		if (err)205			goto unlock;206		val = TEMP_TO_REG(TEMP_FROM_REG(temp) - val, data->resolution);207		err = regmap_write(regmap, LM92_REG_TEMP_HYST, val);208unlock:209		mutex_unlock(&data->update_lock);210		return err;211	default:212		return -EOPNOTSUPP;213	}214	return regmap_write(regmap, reg, TEMP_TO_REG(val, data->resolution));215}216 217static int lm92_write(struct device *dev, enum hwmon_sensor_types type,218		      u32 attr, int channel, long val)219{220	struct lm92_data *data = dev_get_drvdata(dev);221 222	switch (type) {223	case hwmon_temp:224		return lm92_temp_write(data, attr, val);225	default:226		return -EOPNOTSUPP;227	}228}229 230static umode_t lm92_is_visible(const void *_data, enum hwmon_sensor_types type,231			       u32 attr, int channel)232{233	switch (type) {234	case hwmon_chip:235		switch (attr) {236		case hwmon_chip_alarms:237			return 0444;238		default:239			break;240		}241		break;242	case hwmon_temp:243		switch (attr) {244		case hwmon_temp_min:245		case hwmon_temp_max:246		case hwmon_temp_crit:247		case hwmon_temp_crit_hyst:248			return 0644;249		case hwmon_temp_input:250		case hwmon_temp_min_hyst:251		case hwmon_temp_max_hyst:252		case hwmon_temp_min_alarm:253		case hwmon_temp_max_alarm:254		case hwmon_temp_crit_alarm:255			return 0444;256		default:257			break;258		}259		break;260	default:261		break;262	}263	return 0;264}265 266static const struct hwmon_channel_info * const lm92_info[] = {267	HWMON_CHANNEL_INFO(chip, HWMON_C_ALARMS),268	HWMON_CHANNEL_INFO(temp,269			   HWMON_T_INPUT |270			   HWMON_T_MIN | HWMON_T_MIN_HYST |271			   HWMON_T_MAX | HWMON_T_MAX_HYST |272			   HWMON_T_CRIT | HWMON_T_CRIT_HYST |273			   HWMON_T_MIN_ALARM | HWMON_T_MAX_ALARM |274			   HWMON_T_CRIT_ALARM),275	NULL276};277 278static const struct hwmon_ops lm92_hwmon_ops = {279	.is_visible = lm92_is_visible,280	.read = lm92_read,281	.write = lm92_write,282};283 284static const struct hwmon_chip_info lm92_chip_info = {285	.ops = &lm92_hwmon_ops,286	.info = lm92_info,287};288 289/*290 * Detection and registration291 */292 293static int lm92_init_client(struct regmap *regmap)294{295	return regmap_clear_bits(regmap, LM92_REG_CONFIG, 0x01);296}297 298/* Return 0 if detection is successful, -ENODEV otherwise */299static int lm92_detect(struct i2c_client *new_client,300		       struct i2c_board_info *info)301{302	struct i2c_adapter *adapter = new_client->adapter;303	u8 config_addr = LM92_REG_CONFIG;304	u8 man_id_addr = LM92_REG_MAN_ID;305	int i, regval;306 307	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA308					    | I2C_FUNC_SMBUS_WORD_DATA))309		return -ENODEV;310 311	/*312	 * Register values repeat with multiples of 8.313	 * Read twice to improve detection accuracy.314	 */315	for (i = 0; i < 2; i++) {316		regval = i2c_smbus_read_word_data(new_client, man_id_addr);317		if (regval != 0x0180)318			return -ENODEV;319		regval = i2c_smbus_read_byte_data(new_client, config_addr);320		if (regval < 0 || (regval & 0xe0))321			return -ENODEV;322		config_addr += 8;323		man_id_addr += 8;324	}325 326	strscpy(info->type, "lm92", I2C_NAME_SIZE);327 328	return 0;329}330 331/* regmap */332 333static int lm92_reg_read(void *context, unsigned int reg, unsigned int *val)334{335	int ret;336 337	if (reg == LM92_REG_CONFIG)338		ret = i2c_smbus_read_byte_data(context, reg);339	else340		ret = i2c_smbus_read_word_swapped(context, reg);341	if (ret < 0)342		return ret;343 344	*val = ret;345	return 0;346}347 348static int lm92_reg_write(void *context, unsigned int reg, unsigned int val)349{350	if (reg == LM92_REG_CONFIG)351		return i2c_smbus_write_byte_data(context, LM92_REG_CONFIG, val);352 353	return i2c_smbus_write_word_swapped(context, reg, val);354}355 356static bool lm92_regmap_is_volatile(struct device *dev, unsigned int reg)357{358	return reg == LM92_REG_TEMP;359}360 361static bool lm92_regmap_is_writeable(struct device *dev, unsigned int reg)362{363	return reg >= LM92_REG_CONFIG;364}365 366static const struct regmap_config lm92_regmap_config = {367	.reg_bits = 8,368	.val_bits = 16,369	.max_register = LM92_REG_TEMP_HIGH,370	.cache_type = REGCACHE_MAPLE,371	.volatile_reg = lm92_regmap_is_volatile,372	.writeable_reg = lm92_regmap_is_writeable,373};374 375static const struct regmap_bus lm92_regmap_bus = {376	.reg_write = lm92_reg_write,377	.reg_read = lm92_reg_read,378};379 380static int lm92_probe(struct i2c_client *client)381{382	struct device *dev = &client->dev;383	struct device *hwmon_dev;384	struct lm92_data *data;385	struct regmap *regmap;386	int err;387 388	regmap = devm_regmap_init(dev, &lm92_regmap_bus, client,389				  &lm92_regmap_config);390	if (IS_ERR(regmap))391		return PTR_ERR(regmap);392 393	data = devm_kzalloc(dev, sizeof(struct lm92_data), GFP_KERNEL);394	if (!data)395		return -ENOMEM;396 397	data->regmap = regmap;398	data->resolution = (unsigned long)i2c_get_match_data(client);399	mutex_init(&data->update_lock);400 401	/* Initialize the chipset */402	err = lm92_init_client(regmap);403	if (err)404		return err;405 406	hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, data,407							 &lm92_chip_info, NULL);408	return PTR_ERR_OR_ZERO(hwmon_dev);409}410 411/*412 * Module and driver stuff413 */414 415/* .driver_data is limit register resolution */ 416static const struct i2c_device_id lm92_id[] = {417	{ "lm92", 13 },418	{ "max6635", 9 },419	{ }420};421MODULE_DEVICE_TABLE(i2c, lm92_id);422 423static struct i2c_driver lm92_driver = {424	.class		= I2C_CLASS_HWMON,425	.driver = {426		.name	= "lm92",427	},428	.probe		= lm92_probe,429	.id_table	= lm92_id,430	.detect		= lm92_detect,431	.address_list	= normal_i2c,432};433 434module_i2c_driver(lm92_driver);435 436MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");437MODULE_DESCRIPTION("LM92/MAX6635 driver");438MODULE_LICENSE("GPL");439