Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Driver for ST Microelectronics TSC1641 I2C power monitor
4 *
5 * 60 V, 16-bit high-precision power monitor with I2C and MIPI I3C interface
6 * Datasheet: https://www.st.com/resource/en/datasheet/tsc1641.pdf
7 *
8 * Copyright (C) 2025 Igor Reznichenko <igor@reznichenko.net>
9 */
10
11#include <linux/bitfield.h>
12#include <linux/bits.h>
13#include <linux/device.h>
14#include <linux/err.h>
15#include <linux/hwmon.h>
16#include <linux/i2c.h>
17#include <linux/module.h>
18#include <linux/regmap.h>
19#include <linux/sysfs.h>
20#include <linux/util_macros.h>
21
22/* I2C registers */
23#define TSC1641_CONFIG 0x00
24#define TSC1641_SHUNT_VOLTAGE 0x01
25#define TSC1641_LOAD_VOLTAGE 0x02
26#define TSC1641_POWER 0x03
27#define TSC1641_CURRENT 0x04
28#define TSC1641_TEMP 0x05
29#define TSC1641_MASK 0x06
30#define TSC1641_FLAG 0x07
31#define TSC1641_RSHUNT 0x08 /* Shunt resistance */
32#define TSC1641_SOL 0x09
33#define TSC1641_SUL 0x0A
34#define TSC1641_LOL 0x0B
35#define TSC1641_LUL 0x0C
36#define TSC1641_POL 0x0D
37#define TSC1641_TOL 0x0E
38#define TSC1641_MANUF_ID 0xFE /* 0x0006 */
39#define TSC1641_DIE_ID 0xFF /* 0x1000 */
40#define TSC1641_MAX_REG 0xFF
41
42#define TSC1641_RSHUNT_DEFAULT 1000 /* 1mOhm */
43#define TSC1641_CONFIG_DEFAULT 0x003F /* Default mode and temperature sensor */
44#define TSC1641_MASK_DEFAULT 0xFC00 /* Unmask all alerts */
45
46/* Bit mask for conversion time in the configuration register */
47#define TSC1641_CONV_TIME_MASK GENMASK(7, 4)
48
49#define TSC1641_CONV_TIME_DEFAULT 1024
50#define TSC1641_MIN_UPDATE_INTERVAL 1024
51
52/* LSB value of different registers */
53#define TSC1641_VLOAD_LSB_MVOLT 2
54#define TSC1641_POWER_LSB_UWATT 25000
55#define TSC1641_VSHUNT_LSB_NVOLT 2500 /* Use nanovolts to make it integer */
56#define TSC1641_RSHUNT_LSB_UOHM 10
57#define TSC1641_TEMP_LSB_MDEGC 500
58
59/* Limits based on datasheet */
60#define TSC1641_RSHUNT_MIN_UOHM 100
61#define TSC1641_RSHUNT_MAX_UOHM 655350
62#define TSC1641_CURR_ABS_MAX_MAMP 819200 /* Max current at 100uOhm*/
63
64#define TSC1641_ALERT_POL_MASK BIT(1)
65#define TSC1641_ALERT_LATCH_EN_MASK BIT(0)
66
67/* Flags indicating alerts in TSC1641_FLAG register*/
68#define TSC1641_SAT_FLAG BIT(13)
69#define TSC1641_SHUNT_OV_FLAG BIT(6)
70#define TSC1641_SHUNT_UV_FLAG BIT(5)
71#define TSC1641_LOAD_OV_FLAG BIT(4)
72#define TSC1641_LOAD_UV_FLAG BIT(3)
73#define TSC1641_POWER_OVER_FLAG BIT(2)
74#define TSC1641_TEMP_OVER_FLAG BIT(1)
75
76static bool tsc1641_writeable_reg(struct device *dev, unsigned int reg)
77{
78 switch (reg) {
79 case TSC1641_CONFIG:
80 case TSC1641_MASK:
81 case TSC1641_RSHUNT:
82 case TSC1641_SOL:
83 case TSC1641_SUL:
84 case TSC1641_LOL:
85 case TSC1641_LUL:
86 case TSC1641_POL:
87 case TSC1641_TOL:
88 return true;
89 default:
90 return false;
91 }
92}
93
94static bool tsc1641_volatile_reg(struct device *dev, unsigned int reg)
95{
96 switch (reg) {
97 case TSC1641_SHUNT_VOLTAGE:
98 case TSC1641_LOAD_VOLTAGE:
99 case TSC1641_POWER:
100 case TSC1641_CURRENT:
101 case TSC1641_TEMP:
102 case TSC1641_FLAG:
103 case TSC1641_MANUF_ID:
104 case TSC1641_DIE_ID:
105 return true;
106 default:
107 return false;
108 }
109}
110
111static const struct regmap_config tsc1641_regmap_config = {
112 .reg_bits = 8,
113 .val_bits = 16,
114 .use_single_write = true,
115 .use_single_read = true,
116 .max_register = TSC1641_MAX_REG,
117 .cache_type = REGCACHE_MAPLE,
118 .volatile_reg = tsc1641_volatile_reg,
119 .writeable_reg = tsc1641_writeable_reg,
120};
121
122struct tsc1641_data {
123 long rshunt_uohm;
124 long current_lsb_ua;
125 struct regmap *regmap;
126};
127
128/*
129 * Upper limit due to chip 16-bit shunt register, lower limit to
130 * prevent current and power registers overflow
131 */
132static inline int tsc1641_validate_shunt(u32 val)
133{
134 if (val < TSC1641_RSHUNT_MIN_UOHM || val > TSC1641_RSHUNT_MAX_UOHM)
135 return -EINVAL;
136 return 0;
137}
138
139static int tsc1641_set_shunt(struct tsc1641_data *data, u32 val)
140{
141 struct regmap *regmap = data->regmap;
142 long rshunt_reg;
143
144 /* RSHUNT register LSB is 10uOhm so need to divide further */
145 rshunt_reg = DIV_ROUND_CLOSEST(val, TSC1641_RSHUNT_LSB_UOHM);
146 /*
147 * Clamp value to the nearest multiple of TSC1641_RSHUNT_LSB_UOHM
148 * in case shunt value provided was not a multiple
149 */
150 data->rshunt_uohm = rshunt_reg * TSC1641_RSHUNT_LSB_UOHM;
151 data->current_lsb_ua = DIV_ROUND_CLOSEST(TSC1641_VSHUNT_LSB_NVOLT * 1000,
152 data->rshunt_uohm);
153
154 return regmap_write(regmap, TSC1641_RSHUNT, rshunt_reg);
155}
156
157/*
158 * Conversion times in uS, value in CONFIG[CT3:CT0] corresponds to index in this array
159 * See "Table 14. CT3 to CT0: conversion time" in:
160 * https://www.st.com/resource/en/datasheet/tsc1641.pdf
161 */
162static const int tsc1641_conv_times[] = { 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768 };
163
164static int tsc1641_reg_to_upd_interval(u16 config)
165{
166 int idx = FIELD_GET(TSC1641_CONV_TIME_MASK, config);
167
168 idx = clamp_val(idx, 0, ARRAY_SIZE(tsc1641_conv_times) - 1);
169 int conv_time = tsc1641_conv_times[idx];
170
171 /* Don't support sub-millisecond update interval as it's not supported in hwmon */
172 conv_time = max(conv_time, TSC1641_MIN_UPDATE_INTERVAL);
173 /* Return nearest value in milliseconds */
174 return DIV_ROUND_CLOSEST(conv_time, 1000);
175}
176
177static u16 tsc1641_upd_interval_to_reg(long interval)
178{
179 /* Supported interval is 1ms - 33ms */
180 interval = clamp_val(interval, 1, 33);
181
182 int conv = interval * 1000;
183 int conv_bits = find_closest(conv, tsc1641_conv_times,
184 ARRAY_SIZE(tsc1641_conv_times));
185
186 return FIELD_PREP(TSC1641_CONV_TIME_MASK, conv_bits);
187}
188
189static int tsc1641_chip_write(struct device *dev, u32 attr, long val)
190{
191 struct tsc1641_data *data = dev_get_drvdata(dev);
192
193 switch (attr) {
194 case hwmon_chip_update_interval:
195 return regmap_update_bits(data->regmap, TSC1641_CONFIG,
196 TSC1641_CONV_TIME_MASK,
197 tsc1641_upd_interval_to_reg(val));
198 default:
199 return -EOPNOTSUPP;
200 }
201}
202
203static int tsc1641_chip_read(struct device *dev, u32 attr, long *val)
204{
205 struct tsc1641_data *data = dev_get_drvdata(dev);
206 u32 regval;
207 int ret;
208
209 switch (attr) {
210 case hwmon_chip_update_interval:
211 ret = regmap_read(data->regmap, TSC1641_CONFIG, ®val);
212 if (ret)
213 return ret;
214
215 *val = tsc1641_reg_to_upd_interval(regval);
216 return 0;
217 default:
218 return -EOPNOTSUPP;
219 }
220}
221
222static int tsc1641_flag_read(struct regmap *regmap, u32 flag, long *val)
223{
224 unsigned int regval;
225 int ret;
226
227 ret = regmap_read_bypassed(regmap, TSC1641_FLAG, ®val);
228 if (ret)
229 return ret;
230
231 *val = !!(regval & flag);
232 return 0;
233}
234
235static int tsc1641_in_read(struct device *dev, u32 attr, long *val)
236{
237 struct tsc1641_data *data = dev_get_drvdata(dev);
238 struct regmap *regmap = data->regmap;
239 unsigned int regval;
240 int ret, reg;
241 long sat_flag;
242
243 switch (attr) {
244 case hwmon_in_input:
245 reg = TSC1641_LOAD_VOLTAGE;
246 break;
247 case hwmon_in_min:
248 reg = TSC1641_LUL;
249 break;
250 case hwmon_in_max:
251 reg = TSC1641_LOL;
252 break;
253 case hwmon_in_min_alarm:
254 return tsc1641_flag_read(regmap, TSC1641_LOAD_UV_FLAG, val);
255 case hwmon_in_max_alarm:
256 return tsc1641_flag_read(regmap, TSC1641_LOAD_OV_FLAG, val);
257 default:
258 return -EOPNOTSUPP;
259 }
260
261 ret = regmap_read(regmap, reg, ®val);
262 if (ret)
263 return ret;
264
265 /* Check if load voltage is out of range */
266 if (reg == TSC1641_LOAD_VOLTAGE) {
267 /* Register is 15-bit max */
268 if (regval & 0x8000)
269 return -ENODATA;
270
271 ret = tsc1641_flag_read(regmap, TSC1641_SAT_FLAG, &sat_flag);
272 if (ret)
273 return ret;
274 /* Out of range conditions per datasheet */
275 if (sat_flag && (regval == 0x7FFF || !regval))
276 return -ENODATA;
277 }
278
279 *val = regval * TSC1641_VLOAD_LSB_MVOLT;
280 return 0;
281}
282
283/* Chip supports bidirectional (positive or negative) current */
284static int tsc1641_curr_read(struct device *dev, u32 attr, long *val)
285{
286 struct tsc1641_data *data = dev_get_drvdata(dev);
287 struct regmap *regmap = data->regmap;
288 int regval;
289 int ret, reg;
290 long sat_flag;
291
292 /* Current limits are the shunt under/over voltage limits */
293 switch (attr) {
294 case hwmon_curr_input:
295 reg = TSC1641_CURRENT;
296 break;
297 case hwmon_curr_min:
298 reg = TSC1641_SUL;
299 break;
300 case hwmon_curr_max:
301 reg = TSC1641_SOL;
302 break;
303 case hwmon_curr_min_alarm:
304 return tsc1641_flag_read(regmap, TSC1641_SHUNT_UV_FLAG, val);
305 case hwmon_curr_max_alarm:
306 return tsc1641_flag_read(regmap, TSC1641_SHUNT_OV_FLAG, val);
307 default:
308 return -EOPNOTSUPP;
309 }
310 /*
311 * Current uses shunt voltage, so check if it's out of range.
312 * We report current register in sysfs to stay consistent with internal
313 * power calculations which use current register values
314 */
315 if (reg == TSC1641_CURRENT) {
316 ret = regmap_read(regmap, TSC1641_SHUNT_VOLTAGE, ®val);
317 if (ret)
318 return ret;
319
320 ret = tsc1641_flag_read(regmap, TSC1641_SAT_FLAG, &sat_flag);
321 if (ret)
322 return ret;
323
324 if (sat_flag && (regval == 0x7FFF || regval == 0x8000))
325 return -ENODATA;
326 }
327
328 ret = regmap_read(regmap, reg, ®val);
329 if (ret)
330 return ret;
331
332 /* Current in milliamps, signed */
333 *val = DIV_ROUND_CLOSEST((s16)regval * data->current_lsb_ua, 1000);
334 return 0;
335}
336
337static int tsc1641_power_read(struct device *dev, u32 attr, long *val)
338{
339 struct tsc1641_data *data = dev_get_drvdata(dev);
340 struct regmap *regmap = data->regmap;
341 unsigned int regval;
342 int ret, reg;
343
344 switch (attr) {
345 case hwmon_power_input:
346 reg = TSC1641_POWER;
347 break;
348 case hwmon_power_max:
349 reg = TSC1641_POL;
350 break;
351 case hwmon_power_max_alarm:
352 return tsc1641_flag_read(regmap, TSC1641_POWER_OVER_FLAG, val);
353 default:
354 return -EOPNOTSUPP;
355 }
356
357 ret = regmap_read(regmap, reg, ®val);
358 if (ret)
359 return ret;
360
361 *val = regval * TSC1641_POWER_LSB_UWATT;
362 return 0;
363}
364
365static int tsc1641_temp_read(struct device *dev, u32 attr, long *val)
366{
367 struct tsc1641_data *data = dev_get_drvdata(dev);
368 struct regmap *regmap = data->regmap;
369 unsigned int regval;
370 int ret, reg;
371
372 switch (attr) {
373 case hwmon_temp_input:
374 reg = TSC1641_TEMP;
375 break;
376 case hwmon_temp_max:
377 reg = TSC1641_TOL;
378 break;
379 case hwmon_temp_max_alarm:
380 return tsc1641_flag_read(regmap, TSC1641_TEMP_OVER_FLAG, val);
381 default:
382 return -EOPNOTSUPP;
383 }
384
385 ret = regmap_read(regmap, reg, ®val);
386 if (ret)
387 return ret;
388
389 /* 0x8000 means that TEMP measurement not enabled */
390 if (reg == TSC1641_TEMP && regval == 0x8000)
391 return -ENODATA;
392
393 /* Both temperature and limit registers are signed */
394 *val = (s16)regval * TSC1641_TEMP_LSB_MDEGC;
395 return 0;
396}
397
398static int tsc1641_in_write(struct device *dev, u32 attr, long val)
399{
400 struct tsc1641_data *data = dev_get_drvdata(dev);
401 struct regmap *regmap = data->regmap;
402 unsigned int regval;
403 int reg;
404
405 switch (attr) {
406 case hwmon_in_min:
407 reg = TSC1641_LUL;
408 break;
409 case hwmon_in_max:
410 reg = TSC1641_LOL;
411 break;
412 default:
413 return -EOPNOTSUPP;
414 }
415 /* Clamp to full register range */
416 val = clamp_val(val, 0, TSC1641_VLOAD_LSB_MVOLT * USHRT_MAX);
417 regval = DIV_ROUND_CLOSEST(val, TSC1641_VLOAD_LSB_MVOLT);
418
419 return regmap_write(regmap, reg, regval);
420}
421
422static int tsc1641_curr_write(struct device *dev, u32 attr, long val)
423{
424 struct tsc1641_data *data = dev_get_drvdata(dev);
425 struct regmap *regmap = data->regmap;
426 int reg, regval;
427
428 switch (attr) {
429 case hwmon_curr_min:
430 reg = TSC1641_SUL;
431 break;
432 case hwmon_curr_max:
433 reg = TSC1641_SOL;
434 break;
435 default:
436 return -EOPNOTSUPP;
437 }
438
439 /* Clamp to prevent over/underflow below */
440 val = clamp_val(val, -TSC1641_CURR_ABS_MAX_MAMP, TSC1641_CURR_ABS_MAX_MAMP);
441 /* Convert val in milliamps to register */
442 regval = DIV_ROUND_CLOSEST(val * 1000, data->current_lsb_ua);
443 /*
444 * Prevent signed 16-bit overflow.
445 * Integer arithmetic and shunt scaling can quantize values near 0x7FFF/0x8000,
446 * so reading and writing back may not preserve the exact original register value.
447 */
448 regval = clamp_val(regval, SHRT_MIN, SHRT_MAX);
449 /* SUL and SOL registers are signed */
450 return regmap_write(regmap, reg, regval & 0xFFFF);
451}
452
453static int tsc1641_power_write(struct device *dev, u32 attr, long val)
454{
455 struct tsc1641_data *data = dev_get_drvdata(dev);
456 struct regmap *regmap = data->regmap;
457 unsigned int regval;
458
459 switch (attr) {
460 case hwmon_power_max:
461 /* Clamp to full register range */
462 val = clamp_val(val, 0, TSC1641_POWER_LSB_UWATT * USHRT_MAX);
463 regval = DIV_ROUND_CLOSEST(val, TSC1641_POWER_LSB_UWATT);
464 return regmap_write(regmap, TSC1641_POL, regval);
465 default:
466 return -EOPNOTSUPP;
467 }
468}
469
470static int tsc1641_temp_write(struct device *dev, u32 attr, long val)
471{
472 struct tsc1641_data *data = dev_get_drvdata(dev);
473 struct regmap *regmap = data->regmap;
474 int regval;
475
476 switch (attr) {
477 case hwmon_temp_max:
478 /* Clamp to full register range */
479 val = clamp_val(val, TSC1641_TEMP_LSB_MDEGC * SHRT_MIN,
480 TSC1641_TEMP_LSB_MDEGC * SHRT_MAX);
481 regval = DIV_ROUND_CLOSEST(val, TSC1641_TEMP_LSB_MDEGC);
482 /* TOL register is signed */
483 return regmap_write(regmap, TSC1641_TOL, regval & 0xFFFF);
484 default:
485 return -EOPNOTSUPP;
486 }
487}
488
489static umode_t tsc1641_is_visible(const void *data, enum hwmon_sensor_types type,
490 u32 attr, int channel)
491{
492 switch (type) {
493 case hwmon_chip:
494 switch (attr) {
495 case hwmon_chip_update_interval:
496 return 0644;
497 default:
498 break;
499 }
500 break;
501 case hwmon_in:
502 switch (attr) {
503 case hwmon_in_input:
504 return 0444;
505 case hwmon_in_min:
506 case hwmon_in_max:
507 return 0644;
508 case hwmon_in_min_alarm:
509 case hwmon_in_max_alarm:
510 return 0444;
511 default:
512 break;
513 }
514 break;
515 case hwmon_curr:
516 switch (attr) {
517 case hwmon_curr_input:
518 return 0444;
519 case hwmon_curr_min:
520 case hwmon_curr_max:
521 return 0644;
522 case hwmon_curr_min_alarm:
523 case hwmon_curr_max_alarm:
524 return 0444;
525 default:
526 break;
527 }
528 break;
529 case hwmon_power:
530 switch (attr) {
531 case hwmon_power_input:
532 return 0444;
533 case hwmon_power_max:
534 return 0644;
535 case hwmon_power_max_alarm:
536 return 0444;
537 default:
538 break;
539 }
540 break;
541 case hwmon_temp:
542 switch (attr) {
543 case hwmon_temp_input:
544 return 0444;
545 case hwmon_temp_max:
546 return 0644;
547 case hwmon_temp_max_alarm:
548 return 0444;
549 default:
550 break;
551 }
552 break;
553 default:
554 break;
555 }
556 return 0;
557}
558
559static int tsc1641_read(struct device *dev, enum hwmon_sensor_types type,
560 u32 attr, int channel, long *val)
561{
562 switch (type) {
563 case hwmon_chip:
564 return tsc1641_chip_read(dev, attr, val);
565 case hwmon_in:
566 return tsc1641_in_read(dev, attr, val);
567 case hwmon_curr:
568 return tsc1641_curr_read(dev, attr, val);
569 case hwmon_power:
570 return tsc1641_power_read(dev, attr, val);
571 case hwmon_temp:
572 return tsc1641_temp_read(dev, attr, val);
573 default:
574 return -EOPNOTSUPP;
575 }
576}
577
578static int tsc1641_write(struct device *dev, enum hwmon_sensor_types type,
579 u32 attr, int channel, long val)
580{
581 switch (type) {
582 case hwmon_chip:
583 return tsc1641_chip_write(dev, attr, val);
584 case hwmon_in:
585 return tsc1641_in_write(dev, attr, val);
586 case hwmon_curr:
587 return tsc1641_curr_write(dev, attr, val);
588 case hwmon_power:
589 return tsc1641_power_write(dev, attr, val);
590 case hwmon_temp:
591 return tsc1641_temp_write(dev, attr, val);
592 default:
593 return -EOPNOTSUPP;
594 }
595}
596
597static const struct hwmon_channel_info * const tsc1641_info[] = {
598 HWMON_CHANNEL_INFO(chip,
599 HWMON_C_UPDATE_INTERVAL),
600 HWMON_CHANNEL_INFO(in,
601 HWMON_I_INPUT | HWMON_I_MAX | HWMON_I_MAX_ALARM |
602 HWMON_I_MIN | HWMON_I_MIN_ALARM),
603 HWMON_CHANNEL_INFO(curr,
604 HWMON_C_INPUT | HWMON_C_MAX | HWMON_C_MAX_ALARM |
605 HWMON_C_MIN | HWMON_C_MIN_ALARM),
606 HWMON_CHANNEL_INFO(power,
607 HWMON_P_INPUT | HWMON_P_MAX | HWMON_P_MAX_ALARM),
608 HWMON_CHANNEL_INFO(temp,
609 HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_ALARM),
610 NULL
611};
612
613static ssize_t shunt_resistor_show(struct device *dev,
614 struct device_attribute *da, char *buf)
615{
616 struct tsc1641_data *data = dev_get_drvdata(dev);
617
618 return sysfs_emit(buf, "%li\n", data->rshunt_uohm);
619}
620
621static ssize_t shunt_resistor_store(struct device *dev,
622 struct device_attribute *da,
623 const char *buf, size_t count)
624{
625 struct tsc1641_data *data = dev_get_drvdata(dev);
626 unsigned int val;
627 int ret;
628
629 ret = kstrtouint(buf, 10, &val);
630 if (ret < 0)
631 return ret;
632
633 ret = tsc1641_validate_shunt(val);
634 if (ret < 0)
635 return ret;
636
637 ret = tsc1641_set_shunt(data, val);
638 if (ret < 0)
639 return ret;
640 return count;
641}
642
643static const struct hwmon_ops tsc1641_hwmon_ops = {
644 .is_visible = tsc1641_is_visible,
645 .read = tsc1641_read,
646 .write = tsc1641_write,
647};
648
649static const struct hwmon_chip_info tsc1641_chip_info = {
650 .ops = &tsc1641_hwmon_ops,
651 .info = tsc1641_info,
652};
653
654static DEVICE_ATTR_RW(shunt_resistor);
655
656/* Shunt resistor value is exposed via sysfs attribute */
657static struct attribute *tsc1641_attrs[] = {
658 &dev_attr_shunt_resistor.attr,
659 NULL,
660};
661ATTRIBUTE_GROUPS(tsc1641);
662
663static int tsc1641_init(struct device *dev, struct tsc1641_data *data)
664{
665 struct regmap *regmap = data->regmap;
666 bool active_high;
667 u32 shunt;
668 int ret;
669
670 if (device_property_read_u32(dev, "shunt-resistor-micro-ohms", &shunt) < 0)
671 shunt = TSC1641_RSHUNT_DEFAULT;
672
673 if (tsc1641_validate_shunt(shunt) < 0) {
674 dev_err(dev, "invalid shunt resistor value %u\n", shunt);
675 return -EINVAL;
676 }
677
678 ret = tsc1641_set_shunt(data, shunt);
679 if (ret < 0)
680 return ret;
681
682 ret = regmap_write(regmap, TSC1641_CONFIG, TSC1641_CONFIG_DEFAULT);
683 if (ret < 0)
684 return ret;
685
686 active_high = device_property_read_bool(dev, "st,alert-polarity-active-high");
687
688 return regmap_write(regmap, TSC1641_MASK, TSC1641_MASK_DEFAULT |
689 FIELD_PREP(TSC1641_ALERT_POL_MASK, active_high));
690}
691
692static int tsc1641_probe(struct i2c_client *client)
693{
694 struct device *dev = &client->dev;
695 struct tsc1641_data *data;
696 struct device *hwmon_dev;
697 int ret;
698
699 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
700 if (!data)
701 return -ENOMEM;
702
703 data->regmap = devm_regmap_init_i2c(client, &tsc1641_regmap_config);
704 if (IS_ERR(data->regmap))
705 return dev_err_probe(dev, PTR_ERR(data->regmap),
706 "failed to allocate register map\n");
707
708 ret = tsc1641_init(dev, data);
709 if (ret < 0)
710 return dev_err_probe(dev, ret, "failed to configure device\n");
711
712 hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
713 data, &tsc1641_chip_info, tsc1641_groups);
714 if (IS_ERR(hwmon_dev))
715 return PTR_ERR(hwmon_dev);
716
717 dev_info(dev, "power monitor %s (Rshunt = %li uOhm)\n",
718 client->name, data->rshunt_uohm);
719
720 return 0;
721}
722
723static const struct i2c_device_id tsc1641_id[] = {
724 { "tsc1641", 0 },
725 { }
726};
727MODULE_DEVICE_TABLE(i2c, tsc1641_id);
728
729static const struct of_device_id __maybe_unused tsc1641_of_match[] = {
730 { .compatible = "st,tsc1641" },
731 { },
732};
733MODULE_DEVICE_TABLE(of, tsc1641_of_match);
734
735static struct i2c_driver tsc1641_driver = {
736 .driver = {
737 .name = "tsc1641",
738 .of_match_table = of_match_ptr(tsc1641_of_match),
739 },
740 .probe = tsc1641_probe,
741 .id_table = tsc1641_id,
742};
743
744module_i2c_driver(tsc1641_driver);
745
746MODULE_AUTHOR("Igor Reznichenko <igor@reznichenko.net>");
747MODULE_DESCRIPTION("tsc1641 driver");
748MODULE_LICENSE("GPL");