1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * max1619.c - Part of lm_sensors, Linux kernel modules for hardware
5 * Copyright (C) 2003-2004 Oleksij Rempel <bug-track@fisher-privat.net>
6 * Jean Delvare <jdelvare@suse.de>
8 * Based on the lm90 driver. The MAX1619 is a sensor chip made by Maxim.
9 * It reports up to two temperatures (its own plus up to
10 * one external one). Complete datasheet can be
11 * obtained from Maxim's website at:
12 * http://pdfserv.maxim-ic.com/en/ds/MAX1619.pdf
15 #include <linux/err.h>
16 #include <linux/hwmon.h>
17 #include <linux/i2c.h>
18 #include <linux/init.h>
19 #include <linux/module.h>
20 #include <linux/regmap.h>
21 #include <linux/util_macros.h>
23 static const unsigned short normal_i2c
[] = {
24 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END
};
26 #define MAX1619_REG_LOCAL_TEMP 0x00
27 #define MAX1619_REG_REMOTE_TEMP 0x01
28 #define MAX1619_REG_STATUS 0x02
29 #define MAX1619_REG_CONFIG 0x03
30 #define MAX1619_REG_CONVRATE 0x04
31 #define MAX1619_REG_REMOTE_HIGH 0x07
32 #define MAX1619_REG_REMOTE_LOW 0x08
33 #define MAX1619_REG_REMOTE_CRIT 0x10
34 #define MAX1619_REG_REMOTE_CRIT_HYST 0x11
35 #define MAX1619_REG_MAN_ID 0xFE
36 #define MAX1619_REG_CHIP_ID 0xFF
38 static int get_alarms(struct regmap
*regmap
)
40 static u32 regs
[2] = { MAX1619_REG_STATUS
, MAX1619_REG_CONFIG
};
44 ret
= regmap_multi_reg_read(regmap
, regs
, regdata
, 2);
48 /* OVERT status bit may be reversed */
49 if (!(regdata
[1] & 0x20))
52 return regdata
[0] & 0x1e;
55 static int max1619_temp_read(struct regmap
*regmap
, u32 attr
, int channel
, long *val
)
57 int reg
= -1, alarm_bit
= 0;
62 case hwmon_temp_input
:
63 reg
= channel
? MAX1619_REG_REMOTE_TEMP
: MAX1619_REG_LOCAL_TEMP
;
66 reg
= MAX1619_REG_REMOTE_LOW
;
69 reg
= MAX1619_REG_REMOTE_HIGH
;
72 reg
= MAX1619_REG_REMOTE_CRIT
;
74 case hwmon_temp_crit_hyst
:
75 reg
= MAX1619_REG_REMOTE_CRIT_HYST
;
77 case hwmon_temp_min_alarm
:
80 case hwmon_temp_max_alarm
:
83 case hwmon_temp_crit_alarm
:
86 case hwmon_temp_fault
:
93 ret
= regmap_read(regmap
, reg
, &temp
);
96 *val
= sign_extend32(temp
, 7) * 1000;
98 ret
= get_alarms(regmap
);
101 *val
= !!(ret
& BIT(alarm_bit
));
106 static u16 update_intervals
[] = { 16000, 8000, 4000, 2000, 1000, 500, 250, 125 };
108 static int max1619_chip_read(struct regmap
*regmap
, u32 attr
, long *val
)
114 case hwmon_chip_update_interval
:
115 ret
= regmap_read(regmap
, MAX1619_REG_CONVRATE
, ®val
);
118 *val
= update_intervals
[regval
& 7];
120 case hwmon_chip_alarms
:
121 alarms
= get_alarms(regmap
);
132 static int max1619_read(struct device
*dev
, enum hwmon_sensor_types type
,
133 u32 attr
, int channel
, long *val
)
135 struct regmap
*regmap
= dev_get_drvdata(dev
);
139 return max1619_chip_read(regmap
, attr
, val
);
141 return max1619_temp_read(regmap
, attr
, channel
, val
);
147 static int max1619_chip_write(struct regmap
*regmap
, u32 attr
, long val
)
150 case hwmon_chip_update_interval
:
151 val
= find_closest_descending(val
, update_intervals
, ARRAY_SIZE(update_intervals
));
152 return regmap_write(regmap
, MAX1619_REG_CONVRATE
, val
);
158 static int max1619_temp_write(struct regmap
*regmap
,
159 u32 attr
, int channel
, long val
)
165 reg
= MAX1619_REG_REMOTE_LOW
;
168 reg
= MAX1619_REG_REMOTE_HIGH
;
170 case hwmon_temp_crit
:
171 reg
= MAX1619_REG_REMOTE_CRIT
;
173 case hwmon_temp_crit_hyst
:
174 reg
= MAX1619_REG_REMOTE_CRIT_HYST
;
179 val
= DIV_ROUND_CLOSEST(clamp_val(val
, -128000, 127000), 1000);
180 return regmap_write(regmap
, reg
, val
);
183 static int max1619_write(struct device
*dev
, enum hwmon_sensor_types type
,
184 u32 attr
, int channel
, long val
)
186 struct regmap
*regmap
= dev_get_drvdata(dev
);
190 return max1619_chip_write(regmap
, attr
, val
);
192 return max1619_temp_write(regmap
, attr
, channel
, val
);
198 static umode_t
max1619_is_visible(const void *_data
, enum hwmon_sensor_types type
,
199 u32 attr
, int channel
)
204 case hwmon_chip_update_interval
:
206 case hwmon_chip_alarms
:
214 case hwmon_temp_input
:
218 case hwmon_temp_crit
:
219 case hwmon_temp_crit_hyst
:
221 case hwmon_temp_min_alarm
:
222 case hwmon_temp_max_alarm
:
223 case hwmon_temp_crit_alarm
:
224 case hwmon_temp_fault
:
236 static const struct hwmon_channel_info
* const max1619_info
[] = {
237 HWMON_CHANNEL_INFO(chip
, HWMON_C_ALARMS
| HWMON_C_UPDATE_INTERVAL
),
238 HWMON_CHANNEL_INFO(temp
,
240 HWMON_T_INPUT
| HWMON_T_MIN
| HWMON_T_MAX
|
241 HWMON_T_CRIT
| HWMON_T_CRIT_HYST
|
242 HWMON_T_MIN_ALARM
| HWMON_T_MAX_ALARM
|
243 HWMON_T_CRIT_ALARM
| HWMON_T_FAULT
),
247 static const struct hwmon_ops max1619_hwmon_ops
= {
248 .is_visible
= max1619_is_visible
,
249 .read
= max1619_read
,
250 .write
= max1619_write
,
253 static const struct hwmon_chip_info max1619_chip_info
= {
254 .ops
= &max1619_hwmon_ops
,
255 .info
= max1619_info
,
258 /* Return 0 if detection is successful, -ENODEV otherwise */
259 static int max1619_detect(struct i2c_client
*client
,
260 struct i2c_board_info
*info
)
262 struct i2c_adapter
*adapter
= client
->adapter
;
265 if (!i2c_check_functionality(adapter
, I2C_FUNC_SMBUS_BYTE_DATA
))
268 regval
= i2c_smbus_read_byte_data(client
, MAX1619_REG_CONFIG
);
269 if (regval
< 0 || (regval
& 0x03))
271 regval
= i2c_smbus_read_byte_data(client
, MAX1619_REG_CONVRATE
);
272 if (regval
< 0 || regval
> 0x07)
274 regval
= i2c_smbus_read_byte_data(client
, MAX1619_REG_STATUS
);
275 if (regval
< 0 || (regval
& 0x61))
278 regval
= i2c_smbus_read_byte_data(client
, MAX1619_REG_MAN_ID
);
281 regval
= i2c_smbus_read_byte_data(client
, MAX1619_REG_CHIP_ID
);
285 strscpy(info
->type
, "max1619", I2C_NAME_SIZE
);
290 static int max1619_init_chip(struct regmap
*regmap
)
294 ret
= regmap_write(regmap
, MAX1619_REG_CONVRATE
, 5); /* 2 Hz */
298 /* Start conversions */
299 return regmap_clear_bits(regmap
, MAX1619_REG_CONFIG
, 0x40);
304 static int max1619_reg_read(void *context
, unsigned int reg
, unsigned int *val
)
308 ret
= i2c_smbus_read_byte_data(context
, reg
);
316 static int max1619_reg_write(void *context
, unsigned int reg
, unsigned int val
)
318 int offset
= reg
< MAX1619_REG_REMOTE_CRIT
? 6 : 2;
320 return i2c_smbus_write_byte_data(context
, reg
+ offset
, val
);
323 static bool max1619_regmap_is_volatile(struct device
*dev
, unsigned int reg
)
325 return reg
<= MAX1619_REG_STATUS
;
328 static bool max1619_regmap_is_writeable(struct device
*dev
, unsigned int reg
)
330 return reg
> MAX1619_REG_STATUS
&& reg
<= MAX1619_REG_REMOTE_CRIT_HYST
;
333 static const struct regmap_config max1619_regmap_config
= {
336 .max_register
= MAX1619_REG_REMOTE_CRIT_HYST
,
337 .cache_type
= REGCACHE_MAPLE
,
338 .volatile_reg
= max1619_regmap_is_volatile
,
339 .writeable_reg
= max1619_regmap_is_writeable
,
342 static const struct regmap_bus max1619_regmap_bus
= {
343 .reg_write
= max1619_reg_write
,
344 .reg_read
= max1619_reg_read
,
347 static int max1619_probe(struct i2c_client
*client
)
349 struct device
*dev
= &client
->dev
;
350 struct device
*hwmon_dev
;
351 struct regmap
*regmap
;
354 regmap
= devm_regmap_init(dev
, &max1619_regmap_bus
, client
,
355 &max1619_regmap_config
);
357 return PTR_ERR(regmap
);
359 ret
= max1619_init_chip(regmap
);
363 hwmon_dev
= devm_hwmon_device_register_with_info(dev
, client
->name
,
364 regmap
, &max1619_chip_info
, NULL
);
365 return PTR_ERR_OR_ZERO(hwmon_dev
);
368 static const struct i2c_device_id max1619_id
[] = {
372 MODULE_DEVICE_TABLE(i2c
, max1619_id
);
375 static const struct of_device_id max1619_of_match
[] = {
376 { .compatible
= "maxim,max1619", },
380 MODULE_DEVICE_TABLE(of
, max1619_of_match
);
383 static struct i2c_driver max1619_driver
= {
384 .class = I2C_CLASS_HWMON
,
387 .of_match_table
= of_match_ptr(max1619_of_match
),
389 .probe
= max1619_probe
,
390 .id_table
= max1619_id
,
391 .detect
= max1619_detect
,
392 .address_list
= normal_i2c
,
395 module_i2c_driver(max1619_driver
);
397 MODULE_AUTHOR("Oleksij Rempel <bug-track@fisher-privat.net>, Jean Delvare <jdelvare@suse.de>");
398 MODULE_DESCRIPTION("MAX1619 sensor driver");
399 MODULE_LICENSE("GPL");