Blame view

drivers/hwmon/ina2xx.c 13.3 KB
b886d83c5   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
2
3
4
5
6
7
8
  /*
   * 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...
9
10
11
12
   * INA220:
   * Bi-Directional Current/Power Monitor with I2C Interface
   * Datasheet: http://www.ti.com/product/ina220
   *
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
13
14
15
16
   * INA226:
   * Bi-Directional Current/Power Monitor with I2C Interface
   * Datasheet: http://www.ti.com/product/ina226
   *
dc92cd0c1   Guenter Roeck   hwmon: (ina2xx) A...
17
18
19
20
   * INA230:
   * Bi-directional Current/Power Monitor with I2C Interface
   * Datasheet: http://www.ti.com/product/ina230
   *
3ad867001   Lothar Felten   hwmon: (ina2xx) f...
21
   * Copyright (C) 2012 Lothar Felten <lothar.felten@gmail.com>
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
22
   * Thanks to Jan Volkering
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
23
24
25
26
27
28
29
30
31
32
   */
  
  #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...
33
  #include <linux/jiffies.h>
bd0ddd4d0   Javier Martinez Canillas   hwmon: (ina2xx) A...
34
  #include <linux/of_device.h>
31e7ad74f   Tang Yuantian   hwmon: (ina2xx) A...
35
  #include <linux/of.h>
509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
36
  #include <linux/delay.h>
d38df34e3   Bartosz Golaszewski   hwmon: (ina2xx) r...
37
  #include <linux/util_macros.h>
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
38
  #include <linux/regmap.h>
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
  
  #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...
54
55
56
57
58
59
60
61
62
63
64
65
  /* 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...
66
67
68
  #define INA2XX_MAX_DELAY		69 /* worst case delay in ms */
  
  #define INA2XX_RSHUNT_DEFAULT		10000
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
69

72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
70
71
72
73
74
75
76
77
78
79
80
81
82
83
  /* 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...
84
85
86
87
  static struct regmap_config ina2xx_regmap_config = {
  	.reg_bits = 8,
  	.val_bits = 16,
  };
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
88
  enum ina2xx_ids { ina219, ina226 };
6106db25c   Guenter Roeck   hwmon: (ina2xx) U...
89
90
  struct ina2xx_config {
  	u16 config_default;
5d389b125   Maciej Purski   hwmon: (ina2xx) M...
91
  	int calibration_value;
6106db25c   Guenter Roeck   hwmon: (ina2xx) U...
92
93
94
95
  	int registers;
  	int shunt_div;
  	int bus_voltage_shift;
  	int bus_voltage_lsb;	/* uV */
5d389b125   Maciej Purski   hwmon: (ina2xx) M...
96
  	int power_lsb_factor;
6106db25c   Guenter Roeck   hwmon: (ina2xx) U...
97
  };
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
98
  struct ina2xx_data {
6106db25c   Guenter Roeck   hwmon: (ina2xx) U...
99
  	const struct ina2xx_config *config;
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
100

509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
101
  	long rshunt;
5d389b125   Maciej Purski   hwmon: (ina2xx) M...
102
103
  	long current_lsb_uA;
  	long power_lsb_uW;
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
  static const struct ina2xx_config ina2xx_config[] = {
  	[ina219] = {
  		.config_default = INA219_CONFIG_DEFAULT,
5d389b125   Maciej Purski   hwmon: (ina2xx) M...
112
  		.calibration_value = 4096,
6106db25c   Guenter Roeck   hwmon: (ina2xx) U...
113
114
115
116
  		.registers = INA219_REGISTERS,
  		.shunt_div = 100,
  		.bus_voltage_shift = 3,
  		.bus_voltage_lsb = 4000,
5d389b125   Maciej Purski   hwmon: (ina2xx) M...
117
  		.power_lsb_factor = 20,
6106db25c   Guenter Roeck   hwmon: (ina2xx) U...
118
119
120
  	},
  	[ina226] = {
  		.config_default = INA226_CONFIG_DEFAULT,
5d389b125   Maciej Purski   hwmon: (ina2xx) M...
121
  		.calibration_value = 2048,
6106db25c   Guenter Roeck   hwmon: (ina2xx) U...
122
123
124
125
  		.registers = INA226_REGISTERS,
  		.shunt_div = 400,
  		.bus_voltage_shift = 0,
  		.bus_voltage_lsb = 1250,
5d389b125   Maciej Purski   hwmon: (ina2xx) M...
126
  		.power_lsb_factor = 25,
6106db25c   Guenter Roeck   hwmon: (ina2xx) U...
127
128
  	},
  };
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
  }
5d389b125   Maciej Purski   hwmon: (ina2xx) M...
161
162
163
164
165
166
  /*
   * Calibration register is set to the best value, which eliminates
   * truncation errors on calculating current register in hardware.
   * According to datasheet (eq. 3) the best values are 2048 for
   * ina226 and 4096 for ina219. They are hardcoded as calibration_value.
   */
8a5fc7951   Bartosz Golaszewski   hwmon: (ina2xx) m...
167
168
  static int ina2xx_calibrate(struct ina2xx_data *data)
  {
5d389b125   Maciej Purski   hwmon: (ina2xx) M...
169
170
  	return regmap_write(data->regmap, INA2XX_CALIBRATION,
  			    data->config->calibration_value);
8a5fc7951   Bartosz Golaszewski   hwmon: (ina2xx) m...
171
  }
509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
172
173
174
175
  /*
   * Initialize the configuration and calibration registers.
   */
  static int ina2xx_init(struct ina2xx_data *data)
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
176
  {
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
177
178
  	int ret = regmap_write(data->regmap, INA2XX_CONFIG,
  			       data->config->config_default);
509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
179
180
  	if (ret < 0)
  		return ret;
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
181

8a5fc7951   Bartosz Golaszewski   hwmon: (ina2xx) m...
182
  	return ina2xx_calibrate(data);
509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
183
  }
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
184

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

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

509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
193
  	for (retry = 5; retry; retry--) {
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
194
195
196
197
198
199
200
  
  		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...
201
202
203
204
205
206
  
  		/*
  		 * 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...
207
208
  		 * We do that extra read of the calibration register if there
  		 * is some hint of a chip reset.
509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
209
  		 */
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
  		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...
233
  		}
509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
234
  		return 0;
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
235
  	}
509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
236
237
238
239
240
241
242
243
244
245
  
  	/*
  	 * 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...
246
247
  static int ina2xx_get_value(struct ina2xx_data *data, u8 reg,
  			    unsigned int regval)
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
248
  {
6106db25c   Guenter Roeck   hwmon: (ina2xx) U...
249
  	int val;
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
250
251
252
  
  	switch (reg) {
  	case INA2XX_SHUNT_VOLTAGE:
c0214f989   Fabio Baltieri   hwmon: (ina2xx) C...
253
  		/* signed register */
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
254
  		val = DIV_ROUND_CLOSEST((s16)regval, data->config->shunt_div);
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
255
256
  		break;
  	case INA2XX_BUS_VOLTAGE:
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
257
  		val = (regval >> data->config->bus_voltage_shift)
6106db25c   Guenter Roeck   hwmon: (ina2xx) U...
258
259
  		  * data->config->bus_voltage_lsb;
  		val = DIV_ROUND_CLOSEST(val, 1000);
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
260
261
  		break;
  	case INA2XX_POWER:
5d389b125   Maciej Purski   hwmon: (ina2xx) M...
262
  		val = regval * data->power_lsb_uW;
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
263
264
  		break;
  	case INA2XX_CURRENT:
5d389b125   Maciej Purski   hwmon: (ina2xx) M...
265
  		/* signed register, result in mA */
38cd989ee   Nicolin Chen   hwmon: (ina2xx) F...
266
  		val = (s16)regval * data->current_lsb_uA;
5d389b125   Maciej Purski   hwmon: (ina2xx) M...
267
  		val = DIV_ROUND_CLOSEST(val, 1000);
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
268
  		break;
8a5fc7951   Bartosz Golaszewski   hwmon: (ina2xx) m...
269
  	case INA2XX_CALIBRATION:
5d389b125   Maciej Purski   hwmon: (ina2xx) M...
270
  		val = regval;
8a5fc7951   Bartosz Golaszewski   hwmon: (ina2xx) m...
271
  		break;
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
272
273
274
275
276
277
278
279
280
  	default:
  		/* programmer goofed */
  		WARN_ON_ONCE(1);
  		val = 0;
  		break;
  	}
  
  	return val;
  }
6a0f234fb   Guenter Roeck   hwmon: (ina2xx) A...
281
  static ssize_t ina2xx_value_show(struct device *dev,
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
282
283
284
  				 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
  }
5d389b125   Maciej Purski   hwmon: (ina2xx) M...
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
  /*
   * In order to keep calibration register value fixed, the product
   * of current_lsb and shunt_resistor should also be fixed and equal
   * to shunt_voltage_lsb = 1 / shunt_div multiplied by 10^9 in order
   * to keep the scale.
   */
  static int ina2xx_set_shunt(struct ina2xx_data *data, long val)
  {
  	unsigned int dividend = DIV_ROUND_CLOSEST(1000000000,
  						  data->config->shunt_div);
  	if (val <= 0 || val > dividend)
  		return -EINVAL;
  
  	mutex_lock(&data->config_lock);
  	data->rshunt = val;
  	data->current_lsb_uA = DIV_ROUND_CLOSEST(dividend, val);
  	data->power_lsb_uW = data->config->power_lsb_factor *
  			     data->current_lsb_uA;
  	mutex_unlock(&data->config_lock);
  
  	return 0;
  }
6a0f234fb   Guenter Roeck   hwmon: (ina2xx) A...
319
320
  static ssize_t ina2xx_shunt_show(struct device *dev,
  				 struct device_attribute *da, char *buf)
3ad867001   Lothar Felten   hwmon: (ina2xx) f...
321
322
323
324
325
326
  {
  	struct ina2xx_data *data = dev_get_drvdata(dev);
  
  	return snprintf(buf, PAGE_SIZE, "%li
  ", data->rshunt);
  }
6a0f234fb   Guenter Roeck   hwmon: (ina2xx) A...
327
  static ssize_t ina2xx_shunt_store(struct device *dev,
5d389b125   Maciej Purski   hwmon: (ina2xx) M...
328
329
  				  struct device_attribute *da,
  				  const char *buf, size_t count)
8a5fc7951   Bartosz Golaszewski   hwmon: (ina2xx) m...
330
  {
8a5fc7951   Bartosz Golaszewski   hwmon: (ina2xx) m...
331
332
  	unsigned long val;
  	int status;
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
333
  	struct ina2xx_data *data = dev_get_drvdata(dev);
8a5fc7951   Bartosz Golaszewski   hwmon: (ina2xx) m...
334
335
336
337
  
  	status = kstrtoul(buf, 10, &val);
  	if (status < 0)
  		return status;
5d389b125   Maciej Purski   hwmon: (ina2xx) M...
338
  	status = ina2xx_set_shunt(data, val);
8a5fc7951   Bartosz Golaszewski   hwmon: (ina2xx) m...
339
340
  	if (status < 0)
  		return status;
8a5fc7951   Bartosz Golaszewski   hwmon: (ina2xx) m...
341
342
  	return count;
  }
6a0f234fb   Guenter Roeck   hwmon: (ina2xx) A...
343
344
345
  static ssize_t ina226_interval_store(struct device *dev,
  				     struct device_attribute *da,
  				     const char *buf, size_t count)
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
346
347
348
349
  {
  	struct ina2xx_data *data = dev_get_drvdata(dev);
  	unsigned long val;
  	int status;
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
350
351
352
353
354
355
  	status = kstrtoul(buf, 10, &val);
  	if (status < 0)
  		return status;
  
  	if (val > INT_MAX || val == 0)
  		return -EINVAL;
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
356
357
358
  	status = regmap_update_bits(data->regmap, INA2XX_CONFIG,
  				    INA226_AVG_RD_MASK,
  				    ina226_interval_to_reg(val));
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
359
360
361
362
363
  	if (status < 0)
  		return status;
  
  	return count;
  }
6a0f234fb   Guenter Roeck   hwmon: (ina2xx) A...
364
  static ssize_t ina226_interval_show(struct device *dev,
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
365
366
  				    struct device_attribute *da, char *buf)
  {
a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
367
368
369
  	struct ina2xx_data *data = dev_get_drvdata(dev);
  	int status;
  	unsigned int regval;
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
370

a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
371
372
373
  	status = regmap_read(data->regmap, INA2XX_CONFIG, &regval);
  	if (status)
  		return status;
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
374

a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
375
376
  	return snprintf(buf, PAGE_SIZE, "%d
  ", ina226_reg_to_interval(regval));
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
377
  }
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
378
  /* shunt voltage */
6a0f234fb   Guenter Roeck   hwmon: (ina2xx) A...
379
  static SENSOR_DEVICE_ATTR_RO(in0_input, ina2xx_value, INA2XX_SHUNT_VOLTAGE);
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
380
381
  
  /* bus voltage */
6a0f234fb   Guenter Roeck   hwmon: (ina2xx) A...
382
  static SENSOR_DEVICE_ATTR_RO(in1_input, ina2xx_value, INA2XX_BUS_VOLTAGE);
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
383
384
  
  /* calculated current */
6a0f234fb   Guenter Roeck   hwmon: (ina2xx) A...
385
  static SENSOR_DEVICE_ATTR_RO(curr1_input, ina2xx_value, INA2XX_CURRENT);
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
386
387
  
  /* calculated power */
6a0f234fb   Guenter Roeck   hwmon: (ina2xx) A...
388
  static SENSOR_DEVICE_ATTR_RO(power1_input, ina2xx_value, INA2XX_POWER);
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
389

8a5fc7951   Bartosz Golaszewski   hwmon: (ina2xx) m...
390
  /* shunt resistance */
6a0f234fb   Guenter Roeck   hwmon: (ina2xx) A...
391
  static SENSOR_DEVICE_ATTR_RW(shunt_resistor, ina2xx_shunt, INA2XX_CALIBRATION);
8a5fc7951   Bartosz Golaszewski   hwmon: (ina2xx) m...
392

72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
393
  /* update interval (ina226 only) */
6a0f234fb   Guenter Roeck   hwmon: (ina2xx) A...
394
  static SENSOR_DEVICE_ATTR_RW(update_interval, ina226_interval, 0);
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
395

f7c2fe386   Felten, Lothar   hwmon: INA219 and...
396
  /* pointers to created device attributes */
468bf0e39   Guenter Roeck   hwmon: (ina2xx) C...
397
  static struct attribute *ina2xx_attrs[] = {
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
398
399
400
401
  	&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...
402
  	&sensor_dev_attr_shunt_resistor.dev_attr.attr,
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
403
404
  	NULL,
  };
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
405
406
407
408
409
410
411
412
413
414
415
416
417
  
  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...
418
419
420
421
  
  static int ina2xx_probe(struct i2c_client *client,
  			const struct i2c_device_id *id)
  {
468bf0e39   Guenter Roeck   hwmon: (ina2xx) C...
422
423
424
  	struct device *dev = &client->dev;
  	struct ina2xx_data *data;
  	struct device *hwmon_dev;
468bf0e39   Guenter Roeck   hwmon: (ina2xx) C...
425
  	u32 val;
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
426
  	int ret, group = 0;
bd0ddd4d0   Javier Martinez Canillas   hwmon: (ina2xx) A...
427
428
429
430
431
432
  	enum ina2xx_ids chip;
  
  	if (client->dev.of_node)
  		chip = (enum ina2xx_ids)of_device_get_match_data(&client->dev);
  	else
  		chip = id->driver_data;
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
433

468bf0e39   Guenter Roeck   hwmon: (ina2xx) C...
434
  	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
435
436
  	if (!data)
  		return -ENOMEM;
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
437
  	/* set the device type */
bd0ddd4d0   Javier Martinez Canillas   hwmon: (ina2xx) A...
438
  	data->config = &ina2xx_config[chip];
0c4c5860e   Marek Szyprowski   hwmon: (ina2xx) F...
439
  	mutex_init(&data->config_lock);
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
440

001e2e730   Marc Titinger   hwmon: (ina2xx) g...
441
442
443
444
445
446
447
448
  	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;
  	}
5d389b125   Maciej Purski   hwmon: (ina2xx) M...
449
  	ina2xx_set_shunt(data, val);
001e2e730   Marc Titinger   hwmon: (ina2xx) g...
450

a0de56c81   Marc Titinger   hwmon: (ina2xx) c...
451
452
453
454
455
456
457
458
  	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...
459
  	ret = ina2xx_init(data);
f975b3399   Bartosz Golaszewski   hwmon: (ina2xx) b...
460
  	if (ret < 0) {
509416a8e   Bartosz Golaszewski   hwmon: (ina2xx) r...
461
462
  		dev_err(dev, "error configuring the device: %d
  ", ret);
f975b3399   Bartosz Golaszewski   hwmon: (ina2xx) b...
463
464
  		return -ENODEV;
  	}
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
465

72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
466
  	data->groups[group++] = &ina2xx_group;
70df9ebbd   Nicolin Chen   hwmon (ina2xx) Fi...
467
  	if (chip == ina226)
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
468
  		data->groups[group++] = &ina226_group;
468bf0e39   Guenter Roeck   hwmon: (ina2xx) C...
469
  	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
72a87a47a   Bartosz Golaszewski   hwmon: (ina2xx) i...
470
  							   data, data->groups);
468bf0e39   Guenter Roeck   hwmon: (ina2xx) C...
471
472
  	if (IS_ERR(hwmon_dev))
  		return PTR_ERR(hwmon_dev);
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
473

468bf0e39   Guenter Roeck   hwmon: (ina2xx) C...
474
475
  	dev_info(dev, "power monitor %s (Rshunt = %li uOhm)
  ",
70df9ebbd   Nicolin Chen   hwmon (ina2xx) Fi...
476
  		 client->name, data->rshunt);
6106db25c   Guenter Roeck   hwmon: (ina2xx) U...
477

f7c2fe386   Felten, Lothar   hwmon: INA219 and...
478
  	return 0;
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
479
480
481
482
  }
  
  static const struct i2c_device_id ina2xx_id[] = {
  	{ "ina219", ina219 },
dc92cd0c1   Guenter Roeck   hwmon: (ina2xx) A...
483
  	{ "ina220", ina219 },
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
484
  	{ "ina226", ina226 },
dc92cd0c1   Guenter Roeck   hwmon: (ina2xx) A...
485
  	{ "ina230", ina226 },
add513be1   Kevin Hilman   hwmon: (ina2xx) A...
486
  	{ "ina231", ina226 },
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
487
488
489
  	{ }
  };
  MODULE_DEVICE_TABLE(i2c, ina2xx_id);
df6b8c70c   Guenter Roeck   hwmon: (ina2xx) F...
490
  static const struct of_device_id __maybe_unused ina2xx_of_match[] = {
bd0ddd4d0   Javier Martinez Canillas   hwmon: (ina2xx) A...
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
  	{
  		.compatible = "ti,ina219",
  		.data = (void *)ina219
  	},
  	{
  		.compatible = "ti,ina220",
  		.data = (void *)ina219
  	},
  	{
  		.compatible = "ti,ina226",
  		.data = (void *)ina226
  	},
  	{
  		.compatible = "ti,ina230",
  		.data = (void *)ina226
  	},
  	{
  		.compatible = "ti,ina231",
  		.data = (void *)ina226
  	},
  	{ },
  };
  MODULE_DEVICE_TABLE(of, ina2xx_of_match);
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
514
515
516
  static struct i2c_driver ina2xx_driver = {
  	.driver = {
  		.name	= "ina2xx",
bd0ddd4d0   Javier Martinez Canillas   hwmon: (ina2xx) A...
517
  		.of_match_table = of_match_ptr(ina2xx_of_match),
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
518
519
  	},
  	.probe		= ina2xx_probe,
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
520
521
  	.id_table	= ina2xx_id,
  };
d835ca0fd   Wei Yongjun   hwmon: (ina2xx) u...
522
  module_i2c_driver(ina2xx_driver);
f7c2fe386   Felten, Lothar   hwmon: INA219 and...
523
524
525
526
  
  MODULE_AUTHOR("Lothar Felten <l-felten@ti.com>");
  MODULE_DESCRIPTION("ina2xx driver");
  MODULE_LICENSE("GPL");