0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/err.h>
0010 #include <linux/hwmon.h>
0011 #include <linux/i2c.h>
0012 #include <linux/init.h>
0013 #include <linux/kernel.h>
0014 #include <linux/module.h>
0015 #include <linux/of.h>
0016 #include <linux/regmap.h>
0017
0018 #include <linux/platform_data/ina2xx.h>
0019
0020
0021 #define INA238_CONFIG 0x0
0022 #define INA238_ADC_CONFIG 0x1
0023 #define INA238_SHUNT_CALIBRATION 0x2
0024 #define INA238_SHUNT_VOLTAGE 0x4
0025 #define INA238_BUS_VOLTAGE 0x5
0026 #define INA238_DIE_TEMP 0x6
0027 #define INA238_CURRENT 0x7
0028 #define INA238_POWER 0x8
0029 #define INA238_DIAG_ALERT 0xb
0030 #define INA238_SHUNT_OVER_VOLTAGE 0xc
0031 #define INA238_SHUNT_UNDER_VOLTAGE 0xd
0032 #define INA238_BUS_OVER_VOLTAGE 0xe
0033 #define INA238_BUS_UNDER_VOLTAGE 0xf
0034 #define INA238_TEMP_LIMIT 0x10
0035 #define INA238_POWER_LIMIT 0x11
0036 #define INA238_DEVICE_ID 0x3f
0037
0038 #define INA238_CONFIG_ADCRANGE BIT(4)
0039
0040 #define INA238_DIAG_ALERT_TMPOL BIT(7)
0041 #define INA238_DIAG_ALERT_SHNTOL BIT(6)
0042 #define INA238_DIAG_ALERT_SHNTUL BIT(5)
0043 #define INA238_DIAG_ALERT_BUSOL BIT(4)
0044 #define INA238_DIAG_ALERT_BUSUL BIT(3)
0045 #define INA238_DIAG_ALERT_POL BIT(2)
0046
0047 #define INA238_REGISTERS 0x11
0048
0049 #define INA238_RSHUNT_DEFAULT 10000
0050
0051
0052 #define INA238_CONFIG_DEFAULT 0
0053
0054 #define INA238_ADC_CONFIG_DEFAULT 0xfb6a
0055
0056 #define INA238_DIAG_ALERT_DEFAULT 0x2000
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092 #define INA238_CALIBRATION_VALUE 16384
0093 #define INA238_FIXED_SHUNT 20000
0094
0095 #define INA238_SHUNT_VOLTAGE_LSB 5
0096 #define INA238_BUS_VOLTAGE_LSB 3125
0097 #define INA238_DIE_TEMP_LSB 125
0098
0099 static struct regmap_config ina238_regmap_config = {
0100 .max_register = INA238_REGISTERS,
0101 .reg_bits = 8,
0102 .val_bits = 16,
0103 };
0104
0105 struct ina238_data {
0106 struct i2c_client *client;
0107 struct mutex config_lock;
0108 struct regmap *regmap;
0109 u32 rshunt;
0110 int gain;
0111 };
0112
0113 static int ina238_read_reg24(const struct i2c_client *client, u8 reg, u32 *val)
0114 {
0115 u8 data[3];
0116 int err;
0117
0118
0119 err = i2c_smbus_read_i2c_block_data(client, reg, 3, data);
0120 if (err < 0)
0121 return err;
0122 if (err != 3)
0123 return -EIO;
0124 *val = (data[0] << 16) | (data[1] << 8) | data[2];
0125
0126 return 0;
0127 }
0128
0129 static int ina238_read_in(struct device *dev, u32 attr, int channel,
0130 long *val)
0131 {
0132 struct ina238_data *data = dev_get_drvdata(dev);
0133 int reg, mask;
0134 int regval;
0135 int err;
0136
0137 switch (channel) {
0138 case 0:
0139 switch (attr) {
0140 case hwmon_in_input:
0141 reg = INA238_SHUNT_VOLTAGE;
0142 break;
0143 case hwmon_in_max:
0144 reg = INA238_SHUNT_OVER_VOLTAGE;
0145 break;
0146 case hwmon_in_min:
0147 reg = INA238_SHUNT_UNDER_VOLTAGE;
0148 break;
0149 case hwmon_in_max_alarm:
0150 reg = INA238_DIAG_ALERT;
0151 mask = INA238_DIAG_ALERT_SHNTOL;
0152 break;
0153 case hwmon_in_min_alarm:
0154 reg = INA238_DIAG_ALERT;
0155 mask = INA238_DIAG_ALERT_SHNTUL;
0156 break;
0157 default:
0158 return -EOPNOTSUPP;
0159 }
0160 break;
0161 case 1:
0162 switch (attr) {
0163 case hwmon_in_input:
0164 reg = INA238_BUS_VOLTAGE;
0165 break;
0166 case hwmon_in_max:
0167 reg = INA238_BUS_OVER_VOLTAGE;
0168 break;
0169 case hwmon_in_min:
0170 reg = INA238_BUS_UNDER_VOLTAGE;
0171 break;
0172 case hwmon_in_max_alarm:
0173 reg = INA238_DIAG_ALERT;
0174 mask = INA238_DIAG_ALERT_BUSOL;
0175 break;
0176 case hwmon_in_min_alarm:
0177 reg = INA238_DIAG_ALERT;
0178 mask = INA238_DIAG_ALERT_BUSUL;
0179 break;
0180 default:
0181 return -EOPNOTSUPP;
0182 }
0183 break;
0184 default:
0185 return -EOPNOTSUPP;
0186 }
0187
0188 err = regmap_read(data->regmap, reg, ®val);
0189 if (err < 0)
0190 return err;
0191
0192 switch (attr) {
0193 case hwmon_in_input:
0194 case hwmon_in_max:
0195 case hwmon_in_min:
0196
0197 regval = (s16)regval;
0198 if (channel == 0)
0199
0200 *val = (regval * INA238_SHUNT_VOLTAGE_LSB) /
0201 (1000 * (4 - data->gain + 1));
0202 else
0203 *val = (regval * INA238_BUS_VOLTAGE_LSB) / 1000;
0204 break;
0205 case hwmon_in_max_alarm:
0206 case hwmon_in_min_alarm:
0207 *val = !!(regval & mask);
0208 break;
0209 }
0210
0211 return 0;
0212 }
0213
0214 static int ina238_write_in(struct device *dev, u32 attr, int channel,
0215 long val)
0216 {
0217 struct ina238_data *data = dev_get_drvdata(dev);
0218 int regval;
0219
0220 if (attr != hwmon_in_max && attr != hwmon_in_min)
0221 return -EOPNOTSUPP;
0222
0223
0224 switch (channel) {
0225 case 0:
0226
0227 regval = clamp_val(val, -163, 163);
0228 regval = (regval * 1000 * (4 - data->gain + 1)) /
0229 INA238_SHUNT_VOLTAGE_LSB;
0230 regval = clamp_val(regval, S16_MIN, S16_MAX);
0231
0232 switch (attr) {
0233 case hwmon_in_max:
0234 return regmap_write(data->regmap,
0235 INA238_SHUNT_OVER_VOLTAGE, regval);
0236 case hwmon_in_min:
0237 return regmap_write(data->regmap,
0238 INA238_SHUNT_UNDER_VOLTAGE, regval);
0239 default:
0240 return -EOPNOTSUPP;
0241 }
0242 case 1:
0243
0244 regval = clamp_val(val, 0, 102396);
0245 regval = (regval * 1000) / INA238_BUS_VOLTAGE_LSB;
0246 regval = clamp_val(regval, 0, S16_MAX);
0247
0248 switch (attr) {
0249 case hwmon_in_max:
0250 return regmap_write(data->regmap,
0251 INA238_BUS_OVER_VOLTAGE, regval);
0252 case hwmon_in_min:
0253 return regmap_write(data->regmap,
0254 INA238_BUS_UNDER_VOLTAGE, regval);
0255 default:
0256 return -EOPNOTSUPP;
0257 }
0258 default:
0259 return -EOPNOTSUPP;
0260 }
0261 }
0262
0263 static int ina238_read_current(struct device *dev, u32 attr, long *val)
0264 {
0265 struct ina238_data *data = dev_get_drvdata(dev);
0266 int regval;
0267 int err;
0268
0269 switch (attr) {
0270 case hwmon_curr_input:
0271 err = regmap_read(data->regmap, INA238_CURRENT, ®val);
0272 if (err < 0)
0273 return err;
0274
0275
0276 *val = div_s64((s16)regval * INA238_FIXED_SHUNT * data->gain,
0277 data->rshunt * 4);
0278 break;
0279 default:
0280 return -EOPNOTSUPP;
0281 }
0282
0283 return 0;
0284 }
0285
0286 static int ina238_read_power(struct device *dev, u32 attr, long *val)
0287 {
0288 struct ina238_data *data = dev_get_drvdata(dev);
0289 long long power;
0290 int regval;
0291 int err;
0292
0293 switch (attr) {
0294 case hwmon_power_input:
0295 err = ina238_read_reg24(data->client, INA238_POWER, ®val);
0296 if (err)
0297 return err;
0298
0299
0300 power = div_u64(regval * 1000ULL * INA238_FIXED_SHUNT *
0301 data->gain, 20 * data->rshunt);
0302
0303 *val = clamp_val(power, 0, LONG_MAX);
0304 break;
0305 case hwmon_power_max:
0306 err = regmap_read(data->regmap, INA238_POWER_LIMIT, ®val);
0307 if (err)
0308 return err;
0309
0310
0311
0312
0313
0314 power = div_u64((regval << 8) * 1000ULL * INA238_FIXED_SHUNT *
0315 data->gain, 20 * data->rshunt);
0316
0317 *val = clamp_val(power, 0, LONG_MAX);
0318 break;
0319 case hwmon_power_max_alarm:
0320 err = regmap_read(data->regmap, INA238_DIAG_ALERT, ®val);
0321 if (err)
0322 return err;
0323
0324 *val = !!(regval & INA238_DIAG_ALERT_POL);
0325 break;
0326 default:
0327 return -EOPNOTSUPP;
0328 }
0329
0330 return 0;
0331 }
0332
0333 static int ina238_write_power(struct device *dev, u32 attr, long val)
0334 {
0335 struct ina238_data *data = dev_get_drvdata(dev);
0336 long regval;
0337
0338 if (attr != hwmon_power_max)
0339 return -EOPNOTSUPP;
0340
0341
0342
0343
0344
0345
0346 regval = clamp_val(val, 0, LONG_MAX);
0347 regval = div_u64(val * 20ULL * data->rshunt,
0348 1000ULL * INA238_FIXED_SHUNT * data->gain);
0349 regval = clamp_val(regval >> 8, 0, U16_MAX);
0350
0351 return regmap_write(data->regmap, INA238_POWER_LIMIT, regval);
0352 }
0353
0354 static int ina238_read_temp(struct device *dev, u32 attr, long *val)
0355 {
0356 struct ina238_data *data = dev_get_drvdata(dev);
0357 int regval;
0358 int err;
0359
0360 switch (attr) {
0361 case hwmon_temp_input:
0362 err = regmap_read(data->regmap, INA238_DIE_TEMP, ®val);
0363 if (err)
0364 return err;
0365
0366
0367 *val = ((s16)regval >> 4) * INA238_DIE_TEMP_LSB;
0368 break;
0369 case hwmon_temp_max:
0370 err = regmap_read(data->regmap, INA238_TEMP_LIMIT, ®val);
0371 if (err)
0372 return err;
0373
0374
0375 *val = ((s16)regval >> 4) * INA238_DIE_TEMP_LSB;
0376 break;
0377 case hwmon_temp_max_alarm:
0378 err = regmap_read(data->regmap, INA238_DIAG_ALERT, ®val);
0379 if (err)
0380 return err;
0381
0382 *val = !!(regval & INA238_DIAG_ALERT_TMPOL);
0383 break;
0384 default:
0385 return -EOPNOTSUPP;
0386 }
0387
0388 return 0;
0389 }
0390
0391 static int ina238_write_temp(struct device *dev, u32 attr, long val)
0392 {
0393 struct ina238_data *data = dev_get_drvdata(dev);
0394 int regval;
0395
0396 if (attr != hwmon_temp_max)
0397 return -EOPNOTSUPP;
0398
0399
0400 regval = (val / INA238_DIE_TEMP_LSB) << 4;
0401 regval = clamp_val(regval, S16_MIN, S16_MAX) & 0xfff0;
0402
0403 return regmap_write(data->regmap, INA238_TEMP_LIMIT, regval);
0404 }
0405
0406 static int ina238_read(struct device *dev, enum hwmon_sensor_types type,
0407 u32 attr, int channel, long *val)
0408 {
0409 switch (type) {
0410 case hwmon_in:
0411 return ina238_read_in(dev, attr, channel, val);
0412 case hwmon_curr:
0413 return ina238_read_current(dev, attr, val);
0414 case hwmon_power:
0415 return ina238_read_power(dev, attr, val);
0416 case hwmon_temp:
0417 return ina238_read_temp(dev, attr, val);
0418 default:
0419 return -EOPNOTSUPP;
0420 }
0421 return 0;
0422 }
0423
0424 static int ina238_write(struct device *dev, enum hwmon_sensor_types type,
0425 u32 attr, int channel, long val)
0426 {
0427 struct ina238_data *data = dev_get_drvdata(dev);
0428 int err;
0429
0430 mutex_lock(&data->config_lock);
0431
0432 switch (type) {
0433 case hwmon_in:
0434 err = ina238_write_in(dev, attr, channel, val);
0435 break;
0436 case hwmon_power:
0437 err = ina238_write_power(dev, attr, val);
0438 break;
0439 case hwmon_temp:
0440 err = ina238_write_temp(dev, attr, val);
0441 break;
0442 default:
0443 err = -EOPNOTSUPP;
0444 break;
0445 }
0446
0447 mutex_unlock(&data->config_lock);
0448 return err;
0449 }
0450
0451 static umode_t ina238_is_visible(const void *drvdata,
0452 enum hwmon_sensor_types type,
0453 u32 attr, int channel)
0454 {
0455 switch (type) {
0456 case hwmon_in:
0457 switch (attr) {
0458 case hwmon_in_input:
0459 case hwmon_in_max_alarm:
0460 case hwmon_in_min_alarm:
0461 return 0444;
0462 case hwmon_in_max:
0463 case hwmon_in_min:
0464 return 0644;
0465 default:
0466 return 0;
0467 }
0468 case hwmon_curr:
0469 switch (attr) {
0470 case hwmon_curr_input:
0471 return 0444;
0472 default:
0473 return 0;
0474 }
0475 case hwmon_power:
0476 switch (attr) {
0477 case hwmon_power_input:
0478 case hwmon_power_max_alarm:
0479 return 0444;
0480 case hwmon_power_max:
0481 return 0644;
0482 default:
0483 return 0;
0484 }
0485 case hwmon_temp:
0486 switch (attr) {
0487 case hwmon_temp_input:
0488 case hwmon_temp_max_alarm:
0489 return 0444;
0490 case hwmon_temp_max:
0491 return 0644;
0492 default:
0493 return 0;
0494 }
0495 default:
0496 return 0;
0497 }
0498 }
0499
0500 #define INA238_HWMON_IN_CONFIG (HWMON_I_INPUT | \
0501 HWMON_I_MAX | HWMON_I_MAX_ALARM | \
0502 HWMON_I_MIN | HWMON_I_MIN_ALARM)
0503
0504 static const struct hwmon_channel_info *ina238_info[] = {
0505 HWMON_CHANNEL_INFO(in,
0506
0507 INA238_HWMON_IN_CONFIG,
0508
0509 INA238_HWMON_IN_CONFIG),
0510 HWMON_CHANNEL_INFO(curr,
0511
0512 HWMON_C_INPUT),
0513 HWMON_CHANNEL_INFO(power,
0514
0515 HWMON_P_INPUT | HWMON_P_MAX | HWMON_P_MAX_ALARM),
0516 HWMON_CHANNEL_INFO(temp,
0517
0518 HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_ALARM),
0519 NULL
0520 };
0521
0522 static const struct hwmon_ops ina238_hwmon_ops = {
0523 .is_visible = ina238_is_visible,
0524 .read = ina238_read,
0525 .write = ina238_write,
0526 };
0527
0528 static const struct hwmon_chip_info ina238_chip_info = {
0529 .ops = &ina238_hwmon_ops,
0530 .info = ina238_info,
0531 };
0532
0533 static int ina238_probe(struct i2c_client *client)
0534 {
0535 struct ina2xx_platform_data *pdata = dev_get_platdata(&client->dev);
0536 struct device *dev = &client->dev;
0537 struct device *hwmon_dev;
0538 struct ina238_data *data;
0539 int config;
0540 int ret;
0541
0542 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
0543 if (!data)
0544 return -ENOMEM;
0545
0546 data->client = client;
0547 mutex_init(&data->config_lock);
0548
0549 data->regmap = devm_regmap_init_i2c(client, &ina238_regmap_config);
0550 if (IS_ERR(data->regmap)) {
0551 dev_err(dev, "failed to allocate register map\n");
0552 return PTR_ERR(data->regmap);
0553 }
0554
0555
0556 data->rshunt = INA238_RSHUNT_DEFAULT;
0557 if (device_property_read_u32(dev, "shunt-resistor", &data->rshunt) < 0 && pdata)
0558 data->rshunt = pdata->shunt_uohms;
0559 if (data->rshunt == 0) {
0560 dev_err(dev, "invalid shunt resister value %u\n", data->rshunt);
0561 return -EINVAL;
0562 }
0563
0564
0565 if (device_property_read_u32(dev, "ti,shunt-gain", &data->gain) < 0)
0566 data->gain = 4;
0567 if (data->gain != 1 && data->gain != 4) {
0568 dev_err(dev, "invalid shunt gain value %u\n", data->gain);
0569 return -EINVAL;
0570 }
0571
0572
0573 config = INA238_CONFIG_DEFAULT;
0574 if (data->gain == 1)
0575 config |= INA238_CONFIG_ADCRANGE;
0576 ret = regmap_write(data->regmap, INA238_CONFIG, config);
0577 if (ret < 0) {
0578 dev_err(dev, "error configuring the device: %d\n", ret);
0579 return -ENODEV;
0580 }
0581
0582
0583 ret = regmap_write(data->regmap, INA238_ADC_CONFIG,
0584 INA238_ADC_CONFIG_DEFAULT);
0585 if (ret < 0) {
0586 dev_err(dev, "error configuring the device: %d\n", ret);
0587 return -ENODEV;
0588 }
0589
0590
0591 ret = regmap_write(data->regmap, INA238_SHUNT_CALIBRATION,
0592 INA238_CALIBRATION_VALUE);
0593 if (ret < 0) {
0594 dev_err(dev, "error configuring the device: %d\n", ret);
0595 return -ENODEV;
0596 }
0597
0598
0599 ret = regmap_write(data->regmap, INA238_DIAG_ALERT,
0600 INA238_DIAG_ALERT_DEFAULT);
0601 if (ret < 0) {
0602 dev_err(dev, "error configuring the device: %d\n", ret);
0603 return -ENODEV;
0604 }
0605
0606 hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, data,
0607 &ina238_chip_info,
0608 NULL);
0609 if (IS_ERR(hwmon_dev))
0610 return PTR_ERR(hwmon_dev);
0611
0612 dev_info(dev, "power monitor %s (Rshunt = %u uOhm, gain = %u)\n",
0613 client->name, data->rshunt, data->gain);
0614
0615 return 0;
0616 }
0617
0618 static const struct i2c_device_id ina238_id[] = {
0619 { "ina238", 0 },
0620 { }
0621 };
0622 MODULE_DEVICE_TABLE(i2c, ina238_id);
0623
0624 static const struct of_device_id __maybe_unused ina238_of_match[] = {
0625 { .compatible = "ti,ina238" },
0626 { },
0627 };
0628 MODULE_DEVICE_TABLE(of, ina238_of_match);
0629
0630 static struct i2c_driver ina238_driver = {
0631 .class = I2C_CLASS_HWMON,
0632 .driver = {
0633 .name = "ina238",
0634 .of_match_table = of_match_ptr(ina238_of_match),
0635 },
0636 .probe_new = ina238_probe,
0637 .id_table = ina238_id,
0638 };
0639
0640 module_i2c_driver(ina238_driver);
0641
0642 MODULE_AUTHOR("Nathan Rossi <nathan.rossi@digi.com>");
0643 MODULE_DESCRIPTION("ina238 driver");
0644 MODULE_LICENSE("GPL");