Blame view

drivers/hwmon/ina2xx.c 12.3 KB
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
1
2
3
4
5
6
7
  /*
   * Driver for Texas Instruments INA219, INA226 power monitor chips
   *
   * INA219:
   * Zero Drift Bi-Directional Current/Power Monitor with I2C Interface
   * Datasheet: http://www.ti.com/product/ina219
   *
dc92cd0c1   Guenter Roeck   hwmon: (ina2xx) A...
8
9
10
11
   * INA220:
   * Bi-Directional Current/Power Monitor with I2C Interface
   * Datasheet: http://www.ti.com/product/ina220
   *
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
12
13
14
15
   * INA226:
   * Bi-Directional Current/Power Monitor with I2C Interface
   * Datasheet: http://www.ti.com/product/ina226
   *
dc92cd0c1   Guenter Roeck   hwmon: (ina2xx) A...
16
17
18
19
   * INA230:
   * Bi-directional Current/Power Monitor with I2C Interface
   * Datasheet: http://www.ti.com/product/ina230
   *
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
   * Copyright (C) 2012 Lothar Felten <l-felten@ti.com>
   * Thanks to Jan Volkering
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; version 2 of the License.
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/err.h>
  #include <linux/slab.h>
  #include <linux/i2c.h>
  #include <linux/hwmon.h>
  #include <linux/hwmon-sysfs.h>
dcd8f3923   Jean Delvare   hwmon: Add missin...
36
  #include <linux/jiffies.h>
31e7ad74f   Tang Yuantian   hwmon: (ina2xx) A...
37
  #include <linux/of.h>
509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
38
  #include <linux/delay.h>
d38df34e3   Bartosz Golaszewski   hwmon: (ina2xx) r...
39
  #include <linux/util_macros.h>
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
40
  #include <linux/regmap.h>
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
  
  #include <linux/platform_data/ina2xx.h>
  
  /* common register definitions */
  #define INA2XX_CONFIG			0x00
  #define INA2XX_SHUNT_VOLTAGE		0x01 /* readonly */
  #define INA2XX_BUS_VOLTAGE		0x02 /* readonly */
  #define INA2XX_POWER			0x03 /* readonly */
  #define INA2XX_CURRENT			0x04 /* readonly */
  #define INA2XX_CALIBRATION		0x05
  
  /* INA226 register definitions */
  #define INA226_MASK_ENABLE		0x06
  #define INA226_ALERT_LIMIT		0x07
  #define INA226_DIE_ID			0xFF
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
56
57
58
59
60
61
62
63
64
65
66
67
  /* register count */
  #define INA219_REGISTERS		6
  #define INA226_REGISTERS		8
  
  #define INA2XX_MAX_REGISTERS		8
  
  /* settings - depend on use case */
  #define INA219_CONFIG_DEFAULT		0x399F	/* PGA=8 */
  #define INA226_CONFIG_DEFAULT		0x4527	/* averages=16 */
  
  /* worst case is 68.10 ms (~14.6Hz, ina219) */
  #define INA2XX_CONVERSION_RATE		15
509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
68
69
70
  #define INA2XX_MAX_DELAY		69 /* worst case delay in ms */
  
  #define INA2XX_RSHUNT_DEFAULT		10000
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
71

72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
72
73
74
75
76
77
78
79
80
81
82
83
84
85
  /* bit mask for reading the averaging setting in the configuration register */
  #define INA226_AVG_RD_MASK		0x0E00
  
  #define INA226_READ_AVG(reg)		(((reg) & INA226_AVG_RD_MASK) >> 9)
  #define INA226_SHIFT_AVG(val)		((val) << 9)
  
  /* common attrs, ina226 attrs and NULL */
  #define INA2XX_MAX_ATTRIBUTE_GROUPS	3
  
  /*
   * Both bus voltage and shunt voltage conversion times for ina226 are set
   * to 0b0100 on POR, which translates to 2200 microseconds in total.
   */
  #define INA226_TOTAL_CONV_TIME_DEFAULT	2200
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
86
87
88
89
  static struct regmap_config ina2xx_regmap_config = {
  	.reg_bits = 8,
  	.val_bits = 16,
  };
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
90
  enum ina2xx_ids { ina219, ina226 };
6106db25c   Guenter Roeck   hwmon: (ina2xx) U...
91
92
93
94
95
96
97
98
99
  struct ina2xx_config {
  	u16 config_default;
  	int calibration_factor;
  	int registers;
  	int shunt_div;
  	int bus_voltage_shift;
  	int bus_voltage_lsb;	/* uV */
  	int power_lsb;		/* uW */
  };
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
100
  struct ina2xx_data {
6106db25c   Guenter Roeck   hwmon: (ina2xx) U...
101
  	const struct ina2xx_config *config;
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
102

509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
103
  	long rshunt;
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
104
105
  	struct mutex config_lock;
  	struct regmap *regmap;
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
106

72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
107
  	const struct attribute_group *groups[INA2XX_MAX_ATTRIBUTE_GROUPS];
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
108
  };
6106db25c   Guenter Roeck   hwmon: (ina2xx) U...
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
  static const struct ina2xx_config ina2xx_config[] = {
  	[ina219] = {
  		.config_default = INA219_CONFIG_DEFAULT,
  		.calibration_factor = 40960000,
  		.registers = INA219_REGISTERS,
  		.shunt_div = 100,
  		.bus_voltage_shift = 3,
  		.bus_voltage_lsb = 4000,
  		.power_lsb = 20000,
  	},
  	[ina226] = {
  		.config_default = INA226_CONFIG_DEFAULT,
  		.calibration_factor = 5120000,
  		.registers = INA226_REGISTERS,
  		.shunt_div = 400,
  		.bus_voltage_shift = 0,
  		.bus_voltage_lsb = 1250,
  		.power_lsb = 25000,
  	},
  };
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
129
130
131
132
133
134
135
  /*
   * Available averaging rates for ina226. The indices correspond with
   * the bit values expected by the chip (according to the ina226 datasheet,
   * table 3 AVG bit settings, found at
   * http://www.ti.com/lit/ds/symlink/ina226.pdf.
   */
  static const int ina226_avg_tab[] = { 1, 4, 16, 64, 128, 256, 512, 1024 };
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
136
137
138
139
140
141
142
143
144
145
  static int ina226_reg_to_interval(u16 config)
  {
  	int avg = ina226_avg_tab[INA226_READ_AVG(config)];
  
  	/*
  	 * Multiply the total conversion time by the number of averages.
  	 * Return the result in milliseconds.
  	 */
  	return DIV_ROUND_CLOSEST(avg * INA226_TOTAL_CONV_TIME_DEFAULT, 1000);
  }
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
146
147
148
149
150
  /*
   * Return the new, shifted AVG field value of CONFIG register,
   * to use with regmap_update_bits
   */
  static u16 ina226_interval_to_reg(int interval)
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
151
152
153
154
155
  {
  	int avg, avg_bits;
  
  	avg = DIV_ROUND_CLOSEST(interval * 1000,
  				INA226_TOTAL_CONV_TIME_DEFAULT);
d38df34e3   Bartosz Golaszewski   hwmon: (ina2xx) r...
156
157
  	avg_bits = find_closest(avg, ina226_avg_tab,
  				ARRAY_SIZE(ina226_avg_tab));
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
158

a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
159
  	return INA226_SHIFT_AVG(avg_bits);
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
160
  }
8a5fc7951   Bartosz Golaszewski   hwmon: (ina2xx) m...
161
162
  static int ina2xx_calibrate(struct ina2xx_data *data)
  {
b721fe2a3   Bartosz Golaszewski   hwmon: (ina2xx) u...
163
164
  	u16 val = DIV_ROUND_CLOSEST(data->config->calibration_factor,
  				    data->rshunt);
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
165
  	return regmap_write(data->regmap, INA2XX_CALIBRATION, val);
8a5fc7951   Bartosz Golaszewski   hwmon: (ina2xx) m...
166
  }
509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
167
168
169
170
  /*
   * Initialize the configuration and calibration registers.
   */
  static int ina2xx_init(struct ina2xx_data *data)
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
171
  {
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
172
173
  	int ret = regmap_write(data->regmap, INA2XX_CONFIG,
  			       data->config->config_default);
509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
174
175
  	if (ret < 0)
  		return ret;
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
176

509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
177
178
179
180
  	/*
  	 * Set current LSB to 1mA, shunt is in uOhms
  	 * (equation 13 in datasheet).
  	 */
8a5fc7951   Bartosz Golaszewski   hwmon: (ina2xx) m...
181
  	return ina2xx_calibrate(data);
509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
182
  }
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
183

a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
184
  static int ina2xx_read_reg(struct device *dev, int reg, unsigned int *regval)
509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
185
186
  {
  	struct ina2xx_data *data = dev_get_drvdata(dev);
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
187
  	int ret, retry;
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
188

a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
189
190
  	dev_dbg(dev, "Starting register %d read
  ", reg);
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
191

509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
192
  	for (retry = 5; retry; retry--) {
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
193
194
195
196
197
198
199
  
  		ret = regmap_read(data->regmap, reg, regval);
  		if (ret < 0)
  			return ret;
  
  		dev_dbg(dev, "read %d, val = 0x%04x
  ", reg, *regval);
509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
200
201
202
203
204
205
  
  		/*
  		 * If the current value in the calibration register is 0, the
  		 * power and current registers will also remain at 0. In case
  		 * the chip has been reset let's check the calibration
  		 * register and reinitialize if needed.
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
206
207
  		 * We do that extra read of the calibration register if there
  		 * is some hint of a chip reset.
509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
208
  		 */
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
  		if (*regval == 0) {
  			unsigned int cal;
  
  			ret = regmap_read(data->regmap, INA2XX_CALIBRATION,
  					  &cal);
  			if (ret < 0)
  				return ret;
  
  			if (cal == 0) {
  				dev_warn(dev, "chip not calibrated, reinitializing
  ");
  
  				ret = ina2xx_init(data);
  				if (ret < 0)
  					return ret;
  				/*
  				 * Let's make sure the power and current
  				 * registers have been updated before trying
  				 * again.
  				 */
  				msleep(INA2XX_MAX_DELAY);
  				continue;
  			}
509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
232
  		}
509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
233
  		return 0;
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
234
  	}
509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
235
236
237
238
239
240
241
242
243
244
  
  	/*
  	 * If we're here then although all write operations succeeded, the
  	 * chip still returns 0 in the calibration register. Nothing more we
  	 * can do here.
  	 */
  	dev_err(dev, "unable to reinitialize the chip
  ");
  	return -ENODEV;
  }
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
245
246
  static int ina2xx_get_value(struct ina2xx_data *data, u8 reg,
  			    unsigned int regval)
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
247
  {
6106db25c   Guenter Roeck   hwmon: (ina2xx) U...
248
  	int val;
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
249
250
251
  
  	switch (reg) {
  	case INA2XX_SHUNT_VOLTAGE:
c0214f989   Fabio Baltieri   hwmon: (ina2xx) C...
252
  		/* signed register */
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
253
  		val = DIV_ROUND_CLOSEST((s16)regval, data->config->shunt_div);
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
254
255
  		break;
  	case INA2XX_BUS_VOLTAGE:
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
256
  		val = (regval >> data->config->bus_voltage_shift)
6106db25c   Guenter Roeck   hwmon: (ina2xx) U...
257
258
  		  * data->config->bus_voltage_lsb;
  		val = DIV_ROUND_CLOSEST(val, 1000);
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
259
260
  		break;
  	case INA2XX_POWER:
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
261
  		val = regval * data->config->power_lsb;
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
262
263
  		break;
  	case INA2XX_CURRENT:
c0214f989   Fabio Baltieri   hwmon: (ina2xx) C...
264
  		/* signed register, LSB=1mA (selected), in mA */
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
265
  		val = (s16)regval;
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
266
  		break;
8a5fc7951   Bartosz Golaszewski   hwmon: (ina2xx) m...
267
  	case INA2XX_CALIBRATION:
b721fe2a3   Bartosz Golaszewski   hwmon: (ina2xx) u...
268
  		val = DIV_ROUND_CLOSEST(data->config->calibration_factor,
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
269
  					regval);
8a5fc7951   Bartosz Golaszewski   hwmon: (ina2xx) m...
270
  		break;
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
271
272
273
274
275
276
277
278
279
280
281
282
283
284
  	default:
  		/* programmer goofed */
  		WARN_ON_ONCE(1);
  		val = 0;
  		break;
  	}
  
  	return val;
  }
  
  static ssize_t ina2xx_show_value(struct device *dev,
  				 struct device_attribute *da, char *buf)
  {
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
285
286
  	struct ina2xx_data *data = dev_get_drvdata(dev);
  	unsigned int regval;
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
287

a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
288
289
290
291
  	int err = ina2xx_read_reg(dev, attr->index, &regval);
  
  	if (err < 0)
  		return err;
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
292

6106db25c   Guenter Roeck   hwmon: (ina2xx) U...
293
294
  	return snprintf(buf, PAGE_SIZE, "%d
  ",
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
295
  			ina2xx_get_value(data, attr->index, regval));
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
296
  }
8a5fc7951   Bartosz Golaszewski   hwmon: (ina2xx) m...
297
298
299
300
  static ssize_t ina2xx_set_shunt(struct device *dev,
  				struct device_attribute *da,
  				const char *buf, size_t count)
  {
8a5fc7951   Bartosz Golaszewski   hwmon: (ina2xx) m...
301
302
  	unsigned long val;
  	int status;
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
303
  	struct ina2xx_data *data = dev_get_drvdata(dev);
8a5fc7951   Bartosz Golaszewski   hwmon: (ina2xx) m...
304
305
306
307
308
309
310
311
312
  
  	status = kstrtoul(buf, 10, &val);
  	if (status < 0)
  		return status;
  
  	if (val == 0 ||
  	    /* Values greater than the calibration factor make no sense. */
  	    val > data->config->calibration_factor)
  		return -EINVAL;
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
313
  	mutex_lock(&data->config_lock);
8a5fc7951   Bartosz Golaszewski   hwmon: (ina2xx) m...
314
315
  	data->rshunt = val;
  	status = ina2xx_calibrate(data);
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
316
  	mutex_unlock(&data->config_lock);
8a5fc7951   Bartosz Golaszewski   hwmon: (ina2xx) m...
317
318
319
320
321
  	if (status < 0)
  		return status;
  
  	return count;
  }
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
322
323
324
325
326
327
328
  static ssize_t ina226_set_interval(struct device *dev,
  				   struct device_attribute *da,
  				   const char *buf, size_t count)
  {
  	struct ina2xx_data *data = dev_get_drvdata(dev);
  	unsigned long val;
  	int status;
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
329
330
331
332
333
334
  	status = kstrtoul(buf, 10, &val);
  	if (status < 0)
  		return status;
  
  	if (val > INT_MAX || val == 0)
  		return -EINVAL;
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
335
336
337
  	status = regmap_update_bits(data->regmap, INA2XX_CONFIG,
  				    INA226_AVG_RD_MASK,
  				    ina226_interval_to_reg(val));
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
338
339
340
341
342
343
344
345
346
  	if (status < 0)
  		return status;
  
  	return count;
  }
  
  static ssize_t ina226_show_interval(struct device *dev,
  				    struct device_attribute *da, char *buf)
  {
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
347
348
349
  	struct ina2xx_data *data = dev_get_drvdata(dev);
  	int status;
  	unsigned int regval;
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
350

a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
351
352
353
  	status = regmap_read(data->regmap, INA2XX_CONFIG, &regval);
  	if (status)
  		return status;
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
354

a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
355
356
  	return snprintf(buf, PAGE_SIZE, "%d
  ", ina226_reg_to_interval(regval));
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
357
  }
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
358
  /* shunt voltage */
f0df0fd92   Guenter Roeck   hwmon: (ina2xx) F...
359
360
  static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ina2xx_show_value, NULL,
  			  INA2XX_SHUNT_VOLTAGE);
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
361
362
  
  /* bus voltage */
f0df0fd92   Guenter Roeck   hwmon: (ina2xx) F...
363
364
  static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ina2xx_show_value, NULL,
  			  INA2XX_BUS_VOLTAGE);
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
365
366
  
  /* calculated current */
f0df0fd92   Guenter Roeck   hwmon: (ina2xx) F...
367
368
  static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ina2xx_show_value, NULL,
  			  INA2XX_CURRENT);
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
369
370
  
  /* calculated power */
f0df0fd92   Guenter Roeck   hwmon: (ina2xx) F...
371
372
  static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, ina2xx_show_value, NULL,
  			  INA2XX_POWER);
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
373

8a5fc7951   Bartosz Golaszewski   hwmon: (ina2xx) m...
374
375
376
377
  /* shunt resistance */
  static SENSOR_DEVICE_ATTR(shunt_resistor, S_IRUGO | S_IWUSR,
  			  ina2xx_show_value, ina2xx_set_shunt,
  			  INA2XX_CALIBRATION);
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
378
379
380
  /* update interval (ina226 only) */
  static SENSOR_DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR,
  			  ina226_show_interval, ina226_set_interval, 0);
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
381
  /* pointers to created device attributes */
468bf0e39   Guenter Roeck   hwmon: (ina2xx) C...
382
  static struct attribute *ina2xx_attrs[] = {
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
383
384
385
386
  	&sensor_dev_attr_in0_input.dev_attr.attr,
  	&sensor_dev_attr_in1_input.dev_attr.attr,
  	&sensor_dev_attr_curr1_input.dev_attr.attr,
  	&sensor_dev_attr_power1_input.dev_attr.attr,
8a5fc7951   Bartosz Golaszewski   hwmon: (ina2xx) m...
387
  	&sensor_dev_attr_shunt_resistor.dev_attr.attr,
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
388
389
  	NULL,
  };
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
390
391
392
393
394
395
396
397
398
399
400
401
402
  
  static const struct attribute_group ina2xx_group = {
  	.attrs = ina2xx_attrs,
  };
  
  static struct attribute *ina226_attrs[] = {
  	&sensor_dev_attr_update_interval.dev_attr.attr,
  	NULL,
  };
  
  static const struct attribute_group ina226_group = {
  	.attrs = ina226_attrs,
  };
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
403
404
405
406
  
  static int ina2xx_probe(struct i2c_client *client,
  			const struct i2c_device_id *id)
  {
468bf0e39   Guenter Roeck   hwmon: (ina2xx) C...
407
408
409
  	struct device *dev = &client->dev;
  	struct ina2xx_data *data;
  	struct device *hwmon_dev;
468bf0e39   Guenter Roeck   hwmon: (ina2xx) C...
410
  	u32 val;
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
411
  	int ret, group = 0;
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
412

468bf0e39   Guenter Roeck   hwmon: (ina2xx) C...
413
  	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
414
415
  	if (!data)
  		return -ENOMEM;
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
416
  	/* set the device type */
5aa4e83dd   Marc Titinger   hwmon: (ina2xx) r...
417
  	data->config = &ina2xx_config[id->driver_data];
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
418

001e2e730   Marc Titinger   hwmon: (ina2xx) g...
419
420
421
422
423
424
425
426
427
428
  	if (of_property_read_u32(dev->of_node, "shunt-resistor", &val) < 0) {
  		struct ina2xx_platform_data *pdata = dev_get_platdata(dev);
  
  		if (pdata)
  			val = pdata->shunt_uohms;
  		else
  			val = INA2XX_RSHUNT_DEFAULT;
  	}
  
  	if (val <= 0 || val > data->config->calibration_factor)
f975b3399   Bartosz Golaszewski   hwmon: (ina2xx) b...
429
  		return -ENODEV;
f975b3399   Bartosz Golaszewski   hwmon: (ina2xx) b...
430

001e2e730   Marc Titinger   hwmon: (ina2xx) g...
431
  	data->rshunt = val;
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
432
433
434
435
436
437
438
439
  	ina2xx_regmap_config.max_register = data->config->registers;
  
  	data->regmap = devm_regmap_init_i2c(client, &ina2xx_regmap_config);
  	if (IS_ERR(data->regmap)) {
  		dev_err(dev, "failed to allocate register map
  ");
  		return PTR_ERR(data->regmap);
  	}
509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
440
  	ret = ina2xx_init(data);
f975b3399   Bartosz Golaszewski   hwmon: (ina2xx) b...
441
  	if (ret < 0) {
509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
442
443
  		dev_err(dev, "error configuring the device: %d
  ", ret);
f975b3399   Bartosz Golaszewski   hwmon: (ina2xx) b...
444
445
  		return -ENODEV;
  	}
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
446

a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
447
  	mutex_init(&data->config_lock);
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
448

72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
449
  	data->groups[group++] = &ina2xx_group;
5aa4e83dd   Marc Titinger   hwmon: (ina2xx) r...
450
  	if (id->driver_data == ina226)
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
451
  		data->groups[group++] = &ina226_group;
468bf0e39   Guenter Roeck   hwmon: (ina2xx) C...
452
  	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
453
  							   data, data->groups);
468bf0e39   Guenter Roeck   hwmon: (ina2xx) C...
454
455
  	if (IS_ERR(hwmon_dev))
  		return PTR_ERR(hwmon_dev);
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
456

468bf0e39   Guenter Roeck   hwmon: (ina2xx) C...
457
458
  	dev_info(dev, "power monitor %s (Rshunt = %li uOhm)
  ",
509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
459
  		 id->name, data->rshunt);
6106db25c   Guenter Roeck   hwmon: (ina2xx) U...
460

f7c2fe386   Felten, Lothar   hwmon: INA219 and...
461
  	return 0;
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
462
463
464
465
  }
  
  static const struct i2c_device_id ina2xx_id[] = {
  	{ "ina219", ina219 },
dc92cd0c1   Guenter Roeck   hwmon: (ina2xx) A...
466
  	{ "ina220", ina219 },
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
467
  	{ "ina226", ina226 },
dc92cd0c1   Guenter Roeck   hwmon: (ina2xx) A...
468
  	{ "ina230", ina226 },
add513be1   Kevin Hilman   hwmon: (ina2xx) A...
469
  	{ "ina231", ina226 },
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
470
471
472
473
474
475
476
477
478
  	{ }
  };
  MODULE_DEVICE_TABLE(i2c, ina2xx_id);
  
  static struct i2c_driver ina2xx_driver = {
  	.driver = {
  		.name	= "ina2xx",
  	},
  	.probe		= ina2xx_probe,
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
479
480
  	.id_table	= ina2xx_id,
  };
d835ca0fd   Wei Yongjun   hwmon: (ina2xx) u...
481
  module_i2c_driver(ina2xx_driver);
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
482
483
484
485
  
  MODULE_AUTHOR("Lothar Felten <l-felten@ti.com>");
  MODULE_DESCRIPTION("ina2xx driver");
  MODULE_LICENSE("GPL");