File Index
Files and directories
Sign in
FILE

lm92.c

File preview with syntax highlighting.

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