Blame view

drivers/hwmon/max1668.c 12.8 KB
74ba9207e   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
731b4cace   David George   hwmon: Driver for...
2
  /*
b6707b78f   Guenter Roeck   hwmon: (max1668) ...
3
4
5
6
   * Copyright (c) 2011 David George <david.george@ska.ac.za>
   *
   * based on adm1021.c
   * some credit to Christoph Scheurer, but largely a rewrite
b6707b78f   Guenter Roeck   hwmon: (max1668) ...
7
   */
731b4cace   David George   hwmon: Driver for...
8
9
10
11
12
13
14
15
16
17
18
19
  
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/slab.h>
  #include <linux/jiffies.h>
  #include <linux/i2c.h>
  #include <linux/hwmon.h>
  #include <linux/hwmon-sysfs.h>
  #include <linux/err.h>
  #include <linux/mutex.h>
  
  /* Addresses to scan */
28681d71e   Axel Lin   hwmon: (max1668) ...
20
  static const unsigned short max1668_addr_list[] = {
731b4cace   David George   hwmon: Driver for...
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
  	0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END };
  
  /* max1668 registers */
  
  #define MAX1668_REG_TEMP(nr)	(nr)
  #define MAX1668_REG_STAT1	0x05
  #define MAX1668_REG_STAT2	0x06
  #define MAX1668_REG_MAN_ID	0xfe
  #define MAX1668_REG_DEV_ID	0xff
  
  /* limits */
  
  /* write high limits */
  #define MAX1668_REG_LIMH_WR(nr)	(0x13 + 2 * (nr))
  /* write low limits */
  #define MAX1668_REG_LIML_WR(nr)	(0x14 + 2 * (nr))
  /* read high limits */
  #define MAX1668_REG_LIMH_RD(nr)	(0x08 + 2 * (nr))
  /* read low limits */
  #define MAX1668_REG_LIML_RD(nr)	(0x09 + 2 * (nr))
  
  /* manufacturer and device ID Constants */
  #define MAN_ID_MAXIM		0x4d
  #define DEV_ID_MAX1668		0x3
  #define DEV_ID_MAX1805		0x5
  #define DEV_ID_MAX1989		0xb
  
  /* read only mode module parameter */
90ab5ee94   Rusty Russell   module_param: mak...
49
  static bool read_only;
731b4cace   David George   hwmon: Driver for...
50
51
52
53
54
55
  module_param(read_only, bool, 0);
  MODULE_PARM_DESC(read_only, "Don't set any values, read only mode");
  
  enum chips { max1668, max1805, max1989 };
  
  struct max1668_data {
5230551a2   Guenter Roeck   hwmon: (max1668) ...
56
57
  	struct i2c_client *client;
  	const struct attribute_group *groups[3];
731b4cace   David George   hwmon: Driver for...
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
  	enum chips type;
  
  	struct mutex update_lock;
  	char valid;		/* !=0 if following fields are valid */
  	unsigned long last_updated;	/* In jiffies */
  
  	/* 1x local and 4x remote */
  	s8 temp_max[5];
  	s8 temp_min[5];
  	s8 temp[5];
  	u16 alarms;
  };
  
  static struct max1668_data *max1668_update_device(struct device *dev)
  {
5230551a2   Guenter Roeck   hwmon: (max1668) ...
73
74
  	struct max1668_data *data = dev_get_drvdata(dev);
  	struct i2c_client *client = data->client;
731b4cace   David George   hwmon: Driver for...
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
  	struct max1668_data *ret = data;
  	s32 val;
  	int i;
  
  	mutex_lock(&data->update_lock);
  
  	if (data->valid && !time_after(jiffies,
  			data->last_updated + HZ + HZ / 2))
  		goto abort;
  
  	for (i = 0; i < 5; i++) {
  		val = i2c_smbus_read_byte_data(client, MAX1668_REG_TEMP(i));
  		if (unlikely(val < 0)) {
  			ret = ERR_PTR(val);
  			goto abort;
  		}
  		data->temp[i] = (s8) val;
  
  		val = i2c_smbus_read_byte_data(client, MAX1668_REG_LIMH_RD(i));
  		if (unlikely(val < 0)) {
  			ret = ERR_PTR(val);
  			goto abort;
  		}
  		data->temp_max[i] = (s8) val;
  
  		val = i2c_smbus_read_byte_data(client, MAX1668_REG_LIML_RD(i));
  		if (unlikely(val < 0)) {
  			ret = ERR_PTR(val);
  			goto abort;
  		}
  		data->temp_min[i] = (s8) val;
  	}
  
  	val = i2c_smbus_read_byte_data(client, MAX1668_REG_STAT1);
  	if (unlikely(val < 0)) {
  		ret = ERR_PTR(val);
  		goto abort;
  	}
dabaa0d2b   Guenter Roeck   hwmon: (max1668) ...
113
  	data->alarms = val << 8;
731b4cace   David George   hwmon: Driver for...
114
115
116
117
118
119
  
  	val = i2c_smbus_read_byte_data(client, MAX1668_REG_STAT2);
  	if (unlikely(val < 0)) {
  		ret = ERR_PTR(val);
  		goto abort;
  	}
dabaa0d2b   Guenter Roeck   hwmon: (max1668) ...
120
  	data->alarms |= val;
731b4cace   David George   hwmon: Driver for...
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
  
  	data->last_updated = jiffies;
  	data->valid = 1;
  abort:
  	mutex_unlock(&data->update_lock);
  
  	return ret;
  }
  
  static ssize_t show_temp(struct device *dev,
  			 struct device_attribute *devattr, char *buf)
  {
  	int index = to_sensor_dev_attr(devattr)->index;
  	struct max1668_data *data = max1668_update_device(dev);
  
  	if (IS_ERR(data))
  		return PTR_ERR(data);
  
  	return sprintf(buf, "%d
  ", data->temp[index] * 1000);
  }
  
  static ssize_t show_temp_max(struct device *dev,
  			     struct device_attribute *devattr, char *buf)
  {
  	int index = to_sensor_dev_attr(devattr)->index;
  	struct max1668_data *data = max1668_update_device(dev);
  
  	if (IS_ERR(data))
  		return PTR_ERR(data);
  
  	return sprintf(buf, "%d
  ", data->temp_max[index] * 1000);
  }
  
  static ssize_t show_temp_min(struct device *dev,
  			     struct device_attribute *devattr, char *buf)
  {
  	int index = to_sensor_dev_attr(devattr)->index;
  	struct max1668_data *data = max1668_update_device(dev);
  
  	if (IS_ERR(data))
  		return PTR_ERR(data);
  
  	return sprintf(buf, "%d
  ", data->temp_min[index] * 1000);
  }
  
  static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
  			  char *buf)
  {
  	int index = to_sensor_dev_attr(attr)->index;
  	struct max1668_data *data = max1668_update_device(dev);
  
  	if (IS_ERR(data))
  		return PTR_ERR(data);
  
  	return sprintf(buf, "%u
  ", (data->alarms >> index) & 0x1);
  }
dabaa0d2b   Guenter Roeck   hwmon: (max1668) ...
181
182
183
184
185
186
187
188
189
190
191
192
193
  static ssize_t show_fault(struct device *dev,
  			  struct device_attribute *devattr, char *buf)
  {
  	int index = to_sensor_dev_attr(devattr)->index;
  	struct max1668_data *data = max1668_update_device(dev);
  
  	if (IS_ERR(data))
  		return PTR_ERR(data);
  
  	return sprintf(buf, "%u
  ",
  		       (data->alarms & (1 << 12)) && data->temp[index] == 127);
  }
731b4cace   David George   hwmon: Driver for...
194
195
196
197
198
  static ssize_t set_temp_max(struct device *dev,
  			    struct device_attribute *devattr,
  			    const char *buf, size_t count)
  {
  	int index = to_sensor_dev_attr(devattr)->index;
5230551a2   Guenter Roeck   hwmon: (max1668) ...
199
200
  	struct max1668_data *data = dev_get_drvdata(dev);
  	struct i2c_client *client = data->client;
731b4cace   David George   hwmon: Driver for...
201
202
203
204
205
206
207
208
  	long temp;
  	int ret;
  
  	ret = kstrtol(buf, 10, &temp);
  	if (ret < 0)
  		return ret;
  
  	mutex_lock(&data->update_lock);
2a844c148   Guenter Roeck   hwmon: Replace SE...
209
  	data->temp_max[index] = clamp_val(temp/1000, -128, 127);
c5a706697   Guenter Roeck   hwmon: (max1668) ...
210
  	ret = i2c_smbus_write_byte_data(client,
731b4cace   David George   hwmon: Driver for...
211
  					MAX1668_REG_LIMH_WR(index),
c5a706697   Guenter Roeck   hwmon: (max1668) ...
212
213
214
  					data->temp_max[index]);
  	if (ret < 0)
  		count = ret;
731b4cace   David George   hwmon: Driver for...
215
216
217
218
219
220
221
222
223
224
  	mutex_unlock(&data->update_lock);
  
  	return count;
  }
  
  static ssize_t set_temp_min(struct device *dev,
  			    struct device_attribute *devattr,
  			    const char *buf, size_t count)
  {
  	int index = to_sensor_dev_attr(devattr)->index;
5230551a2   Guenter Roeck   hwmon: (max1668) ...
225
226
  	struct max1668_data *data = dev_get_drvdata(dev);
  	struct i2c_client *client = data->client;
731b4cace   David George   hwmon: Driver for...
227
228
229
230
231
232
233
234
  	long temp;
  	int ret;
  
  	ret = kstrtol(buf, 10, &temp);
  	if (ret < 0)
  		return ret;
  
  	mutex_lock(&data->update_lock);
2a844c148   Guenter Roeck   hwmon: Replace SE...
235
  	data->temp_min[index] = clamp_val(temp/1000, -128, 127);
c5a706697   Guenter Roeck   hwmon: (max1668) ...
236
  	ret = i2c_smbus_write_byte_data(client,
731b4cace   David George   hwmon: Driver for...
237
  					MAX1668_REG_LIML_WR(index),
c5a706697   Guenter Roeck   hwmon: (max1668) ...
238
239
240
  					data->temp_min[index]);
  	if (ret < 0)
  		count = ret;
731b4cace   David George   hwmon: Driver for...
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
  	mutex_unlock(&data->update_lock);
  
  	return count;
  }
  
  static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
  static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max,
  				set_temp_max, 0);
  static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO, show_temp_min,
  				set_temp_min, 0);
  static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
  static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp_max,
  				set_temp_max, 1);
  static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO, show_temp_min,
  				set_temp_min, 1);
  static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
  static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp_max,
  				set_temp_max, 2);
  static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO, show_temp_min,
  				set_temp_min, 2);
  static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3);
  static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO, show_temp_max,
  				set_temp_max, 3);
  static SENSOR_DEVICE_ATTR(temp4_min, S_IRUGO, show_temp_min,
  				set_temp_min, 3);
  static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp, NULL, 4);
  static SENSOR_DEVICE_ATTR(temp5_max, S_IRUGO, show_temp_max,
  				set_temp_max, 4);
  static SENSOR_DEVICE_ATTR(temp5_min, S_IRUGO, show_temp_min,
  				set_temp_min, 4);
  
  static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 14);
  static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 13);
  static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 7);
  static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 6);
  static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_alarm, NULL, 5);
  static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 4);
  static SENSOR_DEVICE_ATTR(temp4_min_alarm, S_IRUGO, show_alarm, NULL, 3);
  static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_alarm, NULL, 2);
  static SENSOR_DEVICE_ATTR(temp5_min_alarm, S_IRUGO, show_alarm, NULL, 1);
  static SENSOR_DEVICE_ATTR(temp5_max_alarm, S_IRUGO, show_alarm, NULL, 0);
dabaa0d2b   Guenter Roeck   hwmon: (max1668) ...
282
283
284
285
  static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_fault, NULL, 1);
  static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_fault, NULL, 2);
  static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_fault, NULL, 3);
  static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_fault, NULL, 4);
731b4cace   David George   hwmon: Driver for...
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
  /* Attributes common to MAX1668, MAX1989 and MAX1805 */
  static struct attribute *max1668_attribute_common[] = {
  	&sensor_dev_attr_temp1_max.dev_attr.attr,
  	&sensor_dev_attr_temp1_min.dev_attr.attr,
  	&sensor_dev_attr_temp1_input.dev_attr.attr,
  	&sensor_dev_attr_temp2_max.dev_attr.attr,
  	&sensor_dev_attr_temp2_min.dev_attr.attr,
  	&sensor_dev_attr_temp2_input.dev_attr.attr,
  	&sensor_dev_attr_temp3_max.dev_attr.attr,
  	&sensor_dev_attr_temp3_min.dev_attr.attr,
  	&sensor_dev_attr_temp3_input.dev_attr.attr,
  
  	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
  	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
  	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
  	&sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
  	&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
  	&sensor_dev_attr_temp3_min_alarm.dev_attr.attr,
dabaa0d2b   Guenter Roeck   hwmon: (max1668) ...
304
305
306
  
  	&sensor_dev_attr_temp2_fault.dev_attr.attr,
  	&sensor_dev_attr_temp3_fault.dev_attr.attr,
731b4cace   David George   hwmon: Driver for...
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
  	NULL
  };
  
  /* Attributes not present on MAX1805 */
  static struct attribute *max1668_attribute_unique[] = {
  	&sensor_dev_attr_temp4_max.dev_attr.attr,
  	&sensor_dev_attr_temp4_min.dev_attr.attr,
  	&sensor_dev_attr_temp4_input.dev_attr.attr,
  	&sensor_dev_attr_temp5_max.dev_attr.attr,
  	&sensor_dev_attr_temp5_min.dev_attr.attr,
  	&sensor_dev_attr_temp5_input.dev_attr.attr,
  
  	&sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
  	&sensor_dev_attr_temp4_min_alarm.dev_attr.attr,
  	&sensor_dev_attr_temp5_max_alarm.dev_attr.attr,
  	&sensor_dev_attr_temp5_min_alarm.dev_attr.attr,
dabaa0d2b   Guenter Roeck   hwmon: (max1668) ...
323
324
325
  
  	&sensor_dev_attr_temp4_fault.dev_attr.attr,
  	&sensor_dev_attr_temp5_fault.dev_attr.attr,
731b4cace   David George   hwmon: Driver for...
326
327
  	NULL
  };
587a1f165   Al Viro   switch ->is_visib...
328
  static umode_t max1668_attribute_mode(struct kobject *kobj,
731b4cace   David George   hwmon: Driver for...
329
330
  				     struct attribute *attr, int index)
  {
587a1f165   Al Viro   switch ->is_visib...
331
  	umode_t ret = S_IRUGO;
731b4cace   David George   hwmon: Driver for...
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
  	if (read_only)
  		return ret;
  	if (attr == &sensor_dev_attr_temp1_max.dev_attr.attr ||
  	    attr == &sensor_dev_attr_temp2_max.dev_attr.attr ||
  	    attr == &sensor_dev_attr_temp3_max.dev_attr.attr ||
  	    attr == &sensor_dev_attr_temp4_max.dev_attr.attr ||
  	    attr == &sensor_dev_attr_temp5_max.dev_attr.attr ||
  	    attr == &sensor_dev_attr_temp1_min.dev_attr.attr ||
  	    attr == &sensor_dev_attr_temp2_min.dev_attr.attr ||
  	    attr == &sensor_dev_attr_temp3_min.dev_attr.attr ||
  	    attr == &sensor_dev_attr_temp4_min.dev_attr.attr ||
  	    attr == &sensor_dev_attr_temp5_min.dev_attr.attr)
  		ret |= S_IWUSR;
  	return ret;
  }
  
  static const struct attribute_group max1668_group_common = {
  	.attrs = max1668_attribute_common,
  	.is_visible = max1668_attribute_mode
  };
  
  static const struct attribute_group max1668_group_unique = {
  	.attrs = max1668_attribute_unique,
  	.is_visible = max1668_attribute_mode
  };
  
  /* Return 0 if detection is successful, -ENODEV otherwise */
  static int max1668_detect(struct i2c_client *client,
  			  struct i2c_board_info *info)
  {
  	struct i2c_adapter *adapter = client->adapter;
  	const char *type_name;
  	int man_id, dev_id;
  
  	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
  		return -ENODEV;
  
  	/* Check for unsupported part */
  	man_id = i2c_smbus_read_byte_data(client, MAX1668_REG_MAN_ID);
  	if (man_id != MAN_ID_MAXIM)
  		return -ENODEV;
  
  	dev_id = i2c_smbus_read_byte_data(client, MAX1668_REG_DEV_ID);
  	if (dev_id < 0)
  		return -ENODEV;
  
  	type_name = NULL;
  	if (dev_id == DEV_ID_MAX1668)
  		type_name = "max1668";
  	else if (dev_id == DEV_ID_MAX1805)
  		type_name = "max1805";
  	else if (dev_id == DEV_ID_MAX1989)
  		type_name = "max1989";
  
  	if (!type_name)
  		return -ENODEV;
  
  	strlcpy(info->type, type_name, I2C_NAME_SIZE);
  
  	return 0;
  }
674870385   Stephen Kitt   hwmon: use simple...
393
394
395
  static const struct i2c_device_id max1668_id[];
  
  static int max1668_probe(struct i2c_client *client)
731b4cace   David George   hwmon: Driver for...
396
397
  {
  	struct i2c_adapter *adapter = client->adapter;
5230551a2   Guenter Roeck   hwmon: (max1668) ...
398
399
  	struct device *dev = &client->dev;
  	struct device *hwmon_dev;
731b4cace   David George   hwmon: Driver for...
400
  	struct max1668_data *data;
731b4cace   David George   hwmon: Driver for...
401
402
403
  
  	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
  		return -ENODEV;
5230551a2   Guenter Roeck   hwmon: (max1668) ...
404
  	data = devm_kzalloc(dev, sizeof(struct max1668_data), GFP_KERNEL);
731b4cace   David George   hwmon: Driver for...
405
406
  	if (!data)
  		return -ENOMEM;
5230551a2   Guenter Roeck   hwmon: (max1668) ...
407
  	data->client = client;
674870385   Stephen Kitt   hwmon: use simple...
408
  	data->type = i2c_match_id(max1668_id, client)->driver_data;
731b4cace   David George   hwmon: Driver for...
409
  	mutex_init(&data->update_lock);
5230551a2   Guenter Roeck   hwmon: (max1668) ...
410
411
  	/* sysfs hooks */
  	data->groups[0] = &max1668_group_common;
731b4cace   David George   hwmon: Driver for...
412
  	if (data->type == max1668 || data->type == max1989)
5230551a2   Guenter Roeck   hwmon: (max1668) ...
413
  		data->groups[1] = &max1668_group_unique;
731b4cace   David George   hwmon: Driver for...
414

5230551a2   Guenter Roeck   hwmon: (max1668) ...
415
416
417
  	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
  							   data, data->groups);
  	return PTR_ERR_OR_ZERO(hwmon_dev);
731b4cace   David George   hwmon: Driver for...
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
  }
  
  static const struct i2c_device_id max1668_id[] = {
  	{ "max1668", max1668 },
  	{ "max1805", max1805 },
  	{ "max1989", max1989 },
  	{ }
  };
  MODULE_DEVICE_TABLE(i2c, max1668_id);
  
  /* This is the driver that will be inserted */
  static struct i2c_driver max1668_driver = {
  	.class = I2C_CLASS_HWMON,
  	.driver = {
  		  .name	= "max1668",
  		  },
674870385   Stephen Kitt   hwmon: use simple...
434
  	.probe_new = max1668_probe,
731b4cace   David George   hwmon: Driver for...
435
436
437
438
  	.id_table = max1668_id,
  	.detect	= max1668_detect,
  	.address_list = max1668_addr_list,
  };
f0967eea8   Axel Lin   hwmon: convert dr...
439
  module_i2c_driver(max1668_driver);
731b4cace   David George   hwmon: Driver for...
440
441
442
443
  
  MODULE_AUTHOR("David George <david.george@ska.ac.za>");
  MODULE_DESCRIPTION("MAX1668 remote temperature sensor driver");
  MODULE_LICENSE("GPL");