| 1 | |
| 2 | |
| 3 | * Driver for Texas Instruments TMP512, TMP513 power monitor chips
|
| 4 | *
|
| 5 | * TMP513:
|
| 6 | * Thermal/Power Management with Triple Remote and
|
| 7 | * Local Temperature Sensor and Current Shunt Monitor
|
| 8 | * Datasheet: https://www.ti.com/lit/gpn/tmp513
|
| 9 | *
|
| 10 | * TMP512:
|
| 11 | * Thermal/Power Management with Dual Remote
|
| 12 | * and Local Temperature Sensor and Current Shunt Monitor
|
| 13 | * Datasheet: https://www.ti.com/lit/gpn/tmp512
|
| 14 | *
|
| 15 | * Copyright (C) 2019 Eric Tremblay <[email protected]>
|
| 16 | *
|
| 17 | * This program is free software; you can redistribute it and/or modify
|
| 18 | * it under the terms of the GNU General Public License as published by
|
| 19 | * the Free Software Foundation; version 2 of the License.
|
| 20 |
|
| 21 |
|
| 22 | #include <linux/bitops.h>
|
| 23 | #include <linux/bug.h>
|
| 24 | #include <linux/device.h>
|
| 25 | #include <linux/err.h>
|
| 26 | #include <linux/hwmon.h>
|
| 27 | #include <linux/i2c.h>
|
| 28 | #include <linux/init.h>
|
| 29 | #include <linux/math.h>
|
| 30 | #include <linux/module.h>
|
| 31 | #include <linux/property.h>
|
| 32 | #include <linux/regmap.h>
|
| 33 | #include <linux/slab.h>
|
| 34 | #include <linux/types.h>
|
| 35 | #include <linux/units.h>
|
| 36 |
|
| 37 | |
| 38 | #define TMP51X_SHUNT_CONFIG 0x00
|
| 39 | #define TMP51X_TEMP_CONFIG 0x01
|
| 40 | #define TMP51X_STATUS 0x02
|
| 41 | #define TMP51X_SMBUS_ALERT 0x03
|
| 42 | #define TMP51X_SHUNT_CURRENT_RESULT 0x04
|
| 43 | #define TMP51X_BUS_VOLTAGE_RESULT 0x05
|
| 44 | #define TMP51X_POWER_RESULT 0x06
|
| 45 | #define TMP51X_BUS_CURRENT_RESULT 0x07
|
| 46 | #define TMP51X_LOCAL_TEMP_RESULT 0x08
|
| 47 | #define TMP51X_REMOTE_TEMP_RESULT_1 0x09
|
| 48 | #define TMP51X_REMOTE_TEMP_RESULT_2 0x0A
|
| 49 | #define TMP51X_SHUNT_CURRENT_H_LIMIT 0x0C
|
| 50 | #define TMP51X_SHUNT_CURRENT_L_LIMIT 0x0D
|
| 51 | #define TMP51X_BUS_VOLTAGE_H_LIMIT 0x0E
|
| 52 | #define TMP51X_BUS_VOLTAGE_L_LIMIT 0x0F
|
| 53 | #define TMP51X_POWER_LIMIT 0x10
|
| 54 | #define TMP51X_LOCAL_TEMP_LIMIT 0x11
|
| 55 | #define TMP51X_REMOTE_TEMP_LIMIT_1 0x12
|
| 56 | #define TMP51X_REMOTE_TEMP_LIMIT_2 0x13
|
| 57 | #define TMP51X_SHUNT_CALIBRATION 0x15
|
| 58 | #define TMP51X_N_FACTOR_AND_HYST_1 0x16
|
| 59 | #define TMP51X_N_FACTOR_2 0x17
|
| 60 | #define TMP51X_MAN_ID_REG 0xFE
|
| 61 | #define TMP51X_DEVICE_ID_REG 0xFF
|
| 62 |
|
| 63 | |
| 64 | #define TMP513_REMOTE_TEMP_RESULT_3 0x0B
|
| 65 | #define TMP513_REMOTE_TEMP_LIMIT_3 0x14
|
| 66 | #define TMP513_N_FACTOR_3 0x18
|
| 67 |
|
| 68 | |
| 69 | #define TMP51X_MANUFACTURER_ID 0x55FF
|
| 70 |
|
| 71 | #define TMP512_DEVICE_ID 0x22FF
|
| 72 | #define TMP513_DEVICE_ID 0x23FF
|
| 73 |
|
| 74 | |
| 75 | #define TMP51X_SHUNT_CONFIG_DEFAULT 0x399F
|
| 76 | #define TMP51X_SHUNT_VALUE_DEFAULT 1000
|
| 77 | #define TMP51X_VBUS_RANGE_DEFAULT TMP51X_VBUS_RANGE_32V
|
| 78 | #define TMP51X_PGA_DEFAULT 8
|
| 79 | #define TMP51X_MAX_REGISTER_ADDR 0xFF
|
| 80 |
|
| 81 | |
| 82 | #define CURRENT_SENSE_VOLTAGE_320_MASK 0x1800
|
| 83 | #define CURRENT_SENSE_VOLTAGE_160_MASK 0x1000
|
| 84 | #define CURRENT_SENSE_VOLTAGE_80_MASK 0x0800
|
| 85 | #define CURRENT_SENSE_VOLTAGE_40_MASK 0
|
| 86 |
|
| 87 | #define TMP51X_BUS_VOLTAGE_MASK 0x2000
|
| 88 | #define TMP51X_NFACTOR_MASK 0xFF00
|
| 89 | #define TMP51X_HYST_MASK 0x00FF
|
| 90 |
|
| 91 | #define TMP51X_BUS_VOLTAGE_SHIFT 3
|
| 92 | #define TMP51X_TEMP_SHIFT 3
|
| 93 |
|
| 94 | |
| 95 | #define TMP51X_SHUNT_CURRENT_H_LIMIT_POS 15
|
| 96 | #define TMP51X_SHUNT_CURRENT_L_LIMIT_POS 14
|
| 97 | #define TMP51X_BUS_VOLTAGE_H_LIMIT_POS 13
|
| 98 | #define TMP51X_BUS_VOLTAGE_L_LIMIT_POS 12
|
| 99 | #define TMP51X_POWER_LIMIT_POS 11
|
| 100 | #define TMP51X_LOCAL_TEMP_LIMIT_POS 10
|
| 101 | #define TMP51X_REMOTE_TEMP_LIMIT_1_POS 9
|
| 102 | #define TMP51X_REMOTE_TEMP_LIMIT_2_POS 8
|
| 103 | #define TMP513_REMOTE_TEMP_LIMIT_3_POS 7
|
| 104 |
|
| 105 | #define TMP51X_VBUS_RANGE_32V (32 * MICRO)
|
| 106 | #define TMP51X_VBUS_RANGE_16V (16 * MICRO)
|
| 107 |
|
| 108 | |
| 109 | #define MAX_BUS_VOLTAGE_32_LIMIT 32764
|
| 110 | #define MAX_BUS_VOLTAGE_16_LIMIT 16382
|
| 111 |
|
| 112 | |
| 113 | #define MAX_TEMP_LIMIT 125000
|
| 114 | #define MIN_TEMP_LIMIT -40000
|
| 115 |
|
| 116 | #define MAX_TEMP_HYST 127500
|
| 117 |
|
| 118 | #define TMP512_MAX_CHANNELS 3
|
| 119 | #define TMP513_MAX_CHANNELS 4
|
| 120 |
|
| 121 | #define TMP51X_TEMP_CONFIG_CONV_RATE GENMASK(9, 7)
|
| 122 | #define TMP51X_TEMP_CONFIG_RC BIT(10)
|
| 123 | #define TMP51X_TEMP_CHANNEL_MASK(n) (GENMASK((n) - 1, 0) << 11)
|
| 124 | #define TMP51X_TEMP_CONFIG_CONT BIT(15)
|
| 125 | #define TMP51X_TEMP_CONFIG_DEFAULT(n) \
|
| 126 | (TMP51X_TEMP_CHANNEL_MASK(n) | TMP51X_TEMP_CONFIG_CONT | \
|
| 127 | TMP51X_TEMP_CONFIG_CONV_RATE | TMP51X_TEMP_CONFIG_RC)
|
| 128 |
|
| 129 | static const u8 TMP51X_TEMP_INPUT[4] = {
|
| 130 | TMP51X_LOCAL_TEMP_RESULT,
|
| 131 | TMP51X_REMOTE_TEMP_RESULT_1,
|
| 132 | TMP51X_REMOTE_TEMP_RESULT_2,
|
| 133 | TMP513_REMOTE_TEMP_RESULT_3
|
| 134 | };
|
| 135 |
|
| 136 | static const u8 TMP51X_TEMP_CRIT[4] = {
|
| 137 | TMP51X_LOCAL_TEMP_LIMIT,
|
| 138 | TMP51X_REMOTE_TEMP_LIMIT_1,
|
| 139 | TMP51X_REMOTE_TEMP_LIMIT_2,
|
| 140 | TMP513_REMOTE_TEMP_LIMIT_3
|
| 141 | };
|
| 142 |
|
| 143 | static const u8 TMP51X_TEMP_CRIT_ALARM[4] = {
|
| 144 | TMP51X_LOCAL_TEMP_LIMIT_POS,
|
| 145 | TMP51X_REMOTE_TEMP_LIMIT_1_POS,
|
| 146 | TMP51X_REMOTE_TEMP_LIMIT_2_POS,
|
| 147 | TMP513_REMOTE_TEMP_LIMIT_3_POS
|
| 148 | };
|
| 149 |
|
| 150 | static const u8 TMP51X_TEMP_CRIT_HYST[4] = {
|
| 151 | TMP51X_N_FACTOR_AND_HYST_1,
|
| 152 | TMP51X_N_FACTOR_AND_HYST_1,
|
| 153 | TMP51X_N_FACTOR_AND_HYST_1,
|
| 154 | TMP51X_N_FACTOR_AND_HYST_1
|
| 155 | };
|
| 156 |
|
| 157 | static const u8 TMP51X_CURR_INPUT[2] = {
|
| 158 | TMP51X_SHUNT_CURRENT_RESULT,
|
| 159 | TMP51X_BUS_CURRENT_RESULT
|
| 160 | };
|
| 161 |
|
| 162 | static const struct regmap_config tmp51x_regmap_config = {
|
| 163 | .reg_bits = 8,
|
| 164 | .val_bits = 16,
|
| 165 | .max_register = TMP51X_MAX_REGISTER_ADDR,
|
| 166 | };
|
| 167 |
|
| 168 | struct tmp51x_data {
|
| 169 | u16 shunt_config;
|
| 170 | u16 pga_gain;
|
| 171 | u32 vbus_range_uvolt;
|
| 172 |
|
| 173 | u16 temp_config;
|
| 174 | u32 nfactor[3];
|
| 175 |
|
| 176 | u32 shunt_uohms;
|
| 177 |
|
| 178 | u32 curr_lsb_ua;
|
| 179 | u32 pwr_lsb_uw;
|
| 180 |
|
| 181 | u8 max_channels;
|
| 182 | struct regmap *regmap;
|
| 183 | };
|
| 184 |
|
| 185 | |
| 186 | static inline u8 tmp51x_get_pga_shift(struct tmp51x_data *data)
|
| 187 | {
|
| 188 | return 5 - ffs(data->pga_gain);
|
| 189 | }
|
| 190 |
|
| 191 | static int tmp51x_get_value(struct tmp51x_data *data, u8 reg, u8 pos,
|
| 192 | unsigned int regval, long *val)
|
| 193 | {
|
| 194 | switch (reg) {
|
| 195 | case TMP51X_STATUS:
|
| 196 | *val = (regval >> pos) & 1;
|
| 197 | break;
|
| 198 | case TMP51X_SHUNT_CURRENT_RESULT:
|
| 199 | case TMP51X_SHUNT_CURRENT_H_LIMIT:
|
| 200 | case TMP51X_SHUNT_CURRENT_L_LIMIT:
|
| 201 | |
| 202 | * The valus is read in voltage in the chip but reported as
|
| 203 | * current to the user.
|
| 204 | * 2's complement number shifted by one to four depending
|
| 205 | * on the pga gain setting. 1lsb = 10uV
|
| 206 |
|
| 207 | *val = sign_extend32(regval,
|
| 208 | reg == TMP51X_SHUNT_CURRENT_RESULT ?
|
| 209 | 16 - tmp51x_get_pga_shift(data) : 15);
|
| 210 | *val = DIV_ROUND_CLOSEST(*val * 10 * (long)MILLI, (long)data->shunt_uohms);
|
| 211 |
|
| 212 | break;
|
| 213 | case TMP51X_BUS_VOLTAGE_RESULT:
|
| 214 | case TMP51X_BUS_VOLTAGE_H_LIMIT:
|
| 215 | case TMP51X_BUS_VOLTAGE_L_LIMIT:
|
| 216 | |
| 217 | *val = (regval >> TMP51X_BUS_VOLTAGE_SHIFT) * 4;
|
| 218 | break;
|
| 219 | case TMP51X_POWER_RESULT:
|
| 220 | case TMP51X_POWER_LIMIT:
|
| 221 | |
| 222 | *val = regval * data->pwr_lsb_uw;
|
| 223 | break;
|
| 224 | case TMP51X_BUS_CURRENT_RESULT:
|
| 225 | |
| 226 | *val = sign_extend32(regval, 15) * (long)data->curr_lsb_ua;
|
| 227 | *val = DIV_ROUND_CLOSEST(*val, (long)MILLI);
|
| 228 | break;
|
| 229 | case TMP51X_LOCAL_TEMP_RESULT:
|
| 230 | case TMP51X_REMOTE_TEMP_RESULT_1:
|
| 231 | case TMP51X_REMOTE_TEMP_RESULT_2:
|
| 232 | case TMP513_REMOTE_TEMP_RESULT_3:
|
| 233 | case TMP51X_LOCAL_TEMP_LIMIT:
|
| 234 | case TMP51X_REMOTE_TEMP_LIMIT_1:
|
| 235 | case TMP51X_REMOTE_TEMP_LIMIT_2:
|
| 236 | case TMP513_REMOTE_TEMP_LIMIT_3:
|
| 237 | |
| 238 | *val = sign_extend32(regval, 15) >> TMP51X_TEMP_SHIFT;
|
| 239 | *val = DIV_ROUND_CLOSEST(*val * 625, 10);
|
| 240 | break;
|
| 241 | case TMP51X_N_FACTOR_AND_HYST_1:
|
| 242 | |
| 243 | *val = (regval & TMP51X_HYST_MASK) * 500;
|
| 244 | break;
|
| 245 | default:
|
| 246 | |
| 247 | WARN_ON_ONCE(1);
|
| 248 | *val = 0;
|
| 249 | return -EOPNOTSUPP;
|
| 250 | }
|
| 251 |
|
| 252 | return 0;
|
| 253 | }
|
| 254 |
|
| 255 | static int tmp51x_set_value(struct tmp51x_data *data, u8 reg, long val)
|
| 256 | {
|
| 257 | int regval, max_val;
|
| 258 | u32 mask = 0;
|
| 259 |
|
| 260 | switch (reg) {
|
| 261 | case TMP51X_SHUNT_CURRENT_H_LIMIT:
|
| 262 | case TMP51X_SHUNT_CURRENT_L_LIMIT:
|
| 263 | |
| 264 | * The user enter current value and we convert it to
|
| 265 | * voltage. 1lsb = 10uV
|
| 266 |
|
| 267 | val = DIV_ROUND_CLOSEST(val * (long)data->shunt_uohms, 10 * (long)MILLI);
|
| 268 | max_val = U16_MAX >> tmp51x_get_pga_shift(data);
|
| 269 | regval = clamp_val(val, -max_val, max_val);
|
| 270 | break;
|
| 271 | case TMP51X_BUS_VOLTAGE_H_LIMIT:
|
| 272 | case TMP51X_BUS_VOLTAGE_L_LIMIT:
|
| 273 | |
| 274 | max_val = (data->vbus_range_uvolt == TMP51X_VBUS_RANGE_32V) ?
|
| 275 | MAX_BUS_VOLTAGE_32_LIMIT : MAX_BUS_VOLTAGE_16_LIMIT;
|
| 276 |
|
| 277 | val = clamp_val(DIV_ROUND_CLOSEST(val, 4), 0, max_val);
|
| 278 | regval = val << TMP51X_BUS_VOLTAGE_SHIFT;
|
| 279 | break;
|
| 280 | case TMP51X_POWER_LIMIT:
|
| 281 | regval = clamp_val(DIV_ROUND_CLOSEST(val, data->pwr_lsb_uw), 0,
|
| 282 | U16_MAX);
|
| 283 | break;
|
| 284 | case TMP51X_LOCAL_TEMP_LIMIT:
|
| 285 | case TMP51X_REMOTE_TEMP_LIMIT_1:
|
| 286 | case TMP51X_REMOTE_TEMP_LIMIT_2:
|
| 287 | case TMP513_REMOTE_TEMP_LIMIT_3:
|
| 288 | |
| 289 | val = clamp_val(val, MIN_TEMP_LIMIT, MAX_TEMP_LIMIT);
|
| 290 | regval = DIV_ROUND_CLOSEST(val * 10, 625) << TMP51X_TEMP_SHIFT;
|
| 291 | break;
|
| 292 | case TMP51X_N_FACTOR_AND_HYST_1:
|
| 293 | |
| 294 | val = clamp_val(val, 0, MAX_TEMP_HYST);
|
| 295 | regval = DIV_ROUND_CLOSEST(val, 500);
|
| 296 | mask = TMP51X_HYST_MASK;
|
| 297 | break;
|
| 298 | default:
|
| 299 | |
| 300 | WARN_ON_ONCE(1);
|
| 301 | return -EOPNOTSUPP;
|
| 302 | }
|
| 303 |
|
| 304 | if (mask == 0)
|
| 305 | return regmap_write(data->regmap, reg, regval);
|
| 306 | else
|
| 307 | return regmap_update_bits(data->regmap, reg, mask, regval);
|
| 308 | }
|
| 309 |
|
| 310 | static u8 tmp51x_get_reg(enum hwmon_sensor_types type, u32 attr, int channel)
|
| 311 | {
|
| 312 | switch (type) {
|
| 313 | case hwmon_temp:
|
| 314 | switch (attr) {
|
| 315 | case hwmon_temp_input:
|
| 316 | return TMP51X_TEMP_INPUT[channel];
|
| 317 | case hwmon_temp_crit_alarm:
|
| 318 | return TMP51X_STATUS;
|
| 319 | case hwmon_temp_crit:
|
| 320 | return TMP51X_TEMP_CRIT[channel];
|
| 321 | case hwmon_temp_crit_hyst:
|
| 322 | return TMP51X_TEMP_CRIT_HYST[channel];
|
| 323 | }
|
| 324 | break;
|
| 325 | case hwmon_in:
|
| 326 | switch (attr) {
|
| 327 | case hwmon_in_input:
|
| 328 | return TMP51X_BUS_VOLTAGE_RESULT;
|
| 329 | case hwmon_in_lcrit_alarm:
|
| 330 | case hwmon_in_crit_alarm:
|
| 331 | return TMP51X_STATUS;
|
| 332 | case hwmon_in_lcrit:
|
| 333 | return TMP51X_BUS_VOLTAGE_L_LIMIT;
|
| 334 | case hwmon_in_crit:
|
| 335 | return TMP51X_BUS_VOLTAGE_H_LIMIT;
|
| 336 | }
|
| 337 | break;
|
| 338 | case hwmon_curr:
|
| 339 | switch (attr) {
|
| 340 | case hwmon_curr_input:
|
| 341 | return TMP51X_CURR_INPUT[channel];
|
| 342 | case hwmon_curr_lcrit_alarm:
|
| 343 | case hwmon_curr_crit_alarm:
|
| 344 | return TMP51X_STATUS;
|
| 345 | case hwmon_curr_lcrit:
|
| 346 | return TMP51X_SHUNT_CURRENT_L_LIMIT;
|
| 347 | case hwmon_curr_crit:
|
| 348 | return TMP51X_SHUNT_CURRENT_H_LIMIT;
|
| 349 | }
|
| 350 | break;
|
| 351 | case hwmon_power:
|
| 352 | switch (attr) {
|
| 353 | case hwmon_power_input:
|
| 354 | return TMP51X_POWER_RESULT;
|
| 355 | case hwmon_power_crit_alarm:
|
| 356 | return TMP51X_STATUS;
|
| 357 | case hwmon_power_crit:
|
| 358 | return TMP51X_POWER_LIMIT;
|
| 359 | }
|
| 360 | break;
|
| 361 | default:
|
| 362 | break;
|
| 363 | }
|
| 364 |
|
| 365 | return 0;
|
| 366 | }
|
| 367 |
|
| 368 | static u8 tmp51x_get_status_pos(enum hwmon_sensor_types type, u32 attr,
|
| 369 | int channel)
|
| 370 | {
|
| 371 | switch (type) {
|
| 372 | case hwmon_temp:
|
| 373 | switch (attr) {
|
| 374 | case hwmon_temp_crit_alarm:
|
| 375 | return TMP51X_TEMP_CRIT_ALARM[channel];
|
| 376 | }
|
| 377 | break;
|
| 378 | case hwmon_in:
|
| 379 | switch (attr) {
|
| 380 | case hwmon_in_lcrit_alarm:
|
| 381 | return TMP51X_BUS_VOLTAGE_L_LIMIT_POS;
|
| 382 | case hwmon_in_crit_alarm:
|
| 383 | return TMP51X_BUS_VOLTAGE_H_LIMIT_POS;
|
| 384 | }
|
| 385 | break;
|
| 386 | case hwmon_curr:
|
| 387 | switch (attr) {
|
| 388 | case hwmon_curr_lcrit_alarm:
|
| 389 | return TMP51X_SHUNT_CURRENT_L_LIMIT_POS;
|
| 390 | case hwmon_curr_crit_alarm:
|
| 391 | return TMP51X_SHUNT_CURRENT_H_LIMIT_POS;
|
| 392 | }
|
| 393 | break;
|
| 394 | case hwmon_power:
|
| 395 | switch (attr) {
|
| 396 | case hwmon_power_crit_alarm:
|
| 397 | return TMP51X_POWER_LIMIT_POS;
|
| 398 | }
|
| 399 | break;
|
| 400 | default:
|
| 401 | break;
|
| 402 | }
|
| 403 |
|
| 404 | return 0;
|
| 405 | }
|
| 406 |
|
| 407 | static int tmp51x_read(struct device *dev, enum hwmon_sensor_types type,
|
| 408 | u32 attr, int channel, long *val)
|
| 409 | {
|
| 410 | struct tmp51x_data *data = dev_get_drvdata(dev);
|
| 411 | int ret;
|
| 412 | u32 regval;
|
| 413 | u8 pos = 0, reg = 0;
|
| 414 |
|
| 415 | reg = tmp51x_get_reg(type, attr, channel);
|
| 416 | if (reg == 0)
|
| 417 | return -EOPNOTSUPP;
|
| 418 |
|
| 419 | if (reg == TMP51X_STATUS)
|
| 420 | pos = tmp51x_get_status_pos(type, attr, channel);
|
| 421 |
|
| 422 | ret = regmap_read(data->regmap, reg, ®val);
|
| 423 | if (ret < 0)
|
| 424 | return ret;
|
| 425 |
|
| 426 | return tmp51x_get_value(data, reg, pos, regval, val);
|
| 427 | }
|
| 428 |
|
| 429 | static int tmp51x_write(struct device *dev, enum hwmon_sensor_types type,
|
| 430 | u32 attr, int channel, long val)
|
| 431 | {
|
| 432 | u8 reg = 0;
|
| 433 |
|
| 434 | reg = tmp51x_get_reg(type, attr, channel);
|
| 435 | if (reg == 0)
|
| 436 | return -EOPNOTSUPP;
|
| 437 |
|
| 438 | return tmp51x_set_value(dev_get_drvdata(dev), reg, val);
|
| 439 | }
|
| 440 |
|
| 441 | static umode_t tmp51x_is_visible(const void *_data,
|
| 442 | enum hwmon_sensor_types type, u32 attr,
|
| 443 | int channel)
|
| 444 | {
|
| 445 | const struct tmp51x_data *data = _data;
|
| 446 |
|
| 447 | switch (type) {
|
| 448 | case hwmon_temp:
|
| 449 | if (channel >= data->max_channels)
|
| 450 | return 0;
|
| 451 | switch (attr) {
|
| 452 | case hwmon_temp_input:
|
| 453 | case hwmon_temp_crit_alarm:
|
| 454 | return 0444;
|
| 455 | case hwmon_temp_crit:
|
| 456 | return 0644;
|
| 457 | case hwmon_temp_crit_hyst:
|
| 458 | if (channel == 0)
|
| 459 | return 0644;
|
| 460 | return 0444;
|
| 461 | }
|
| 462 | break;
|
| 463 | case hwmon_in:
|
| 464 | switch (attr) {
|
| 465 | case hwmon_in_input:
|
| 466 | case hwmon_in_lcrit_alarm:
|
| 467 | case hwmon_in_crit_alarm:
|
| 468 | return 0444;
|
| 469 | case hwmon_in_lcrit:
|
| 470 | case hwmon_in_crit:
|
| 471 | return 0644;
|
| 472 | }
|
| 473 | break;
|
| 474 | case hwmon_curr:
|
| 475 | if (!data->shunt_uohms)
|
| 476 | return 0;
|
| 477 |
|
| 478 | switch (attr) {
|
| 479 | case hwmon_curr_input:
|
| 480 | case hwmon_curr_lcrit_alarm:
|
| 481 | case hwmon_curr_crit_alarm:
|
| 482 | return 0444;
|
| 483 | case hwmon_curr_lcrit:
|
| 484 | case hwmon_curr_crit:
|
| 485 | return 0644;
|
| 486 | }
|
| 487 | break;
|
| 488 | case hwmon_power:
|
| 489 | if (!data->shunt_uohms)
|
| 490 | return 0;
|
| 491 |
|
| 492 | switch (attr) {
|
| 493 | case hwmon_power_input:
|
| 494 | case hwmon_power_crit_alarm:
|
| 495 | return 0444;
|
| 496 | case hwmon_power_crit:
|
| 497 | return 0644;
|
| 498 | }
|
| 499 | break;
|
| 500 | default:
|
| 501 | break;
|
| 502 | }
|
| 503 | return 0;
|
| 504 | }
|
| 505 |
|
| 506 | static const struct hwmon_channel_info * const tmp51x_info[] = {
|
| 507 | HWMON_CHANNEL_INFO(temp,
|
| 508 | HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_CRIT_ALARM |
|
| 509 | HWMON_T_CRIT_HYST,
|
| 510 | HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_CRIT_ALARM |
|
| 511 | HWMON_T_CRIT_HYST,
|
| 512 | HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_CRIT_ALARM |
|
| 513 | HWMON_T_CRIT_HYST,
|
| 514 | HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_CRIT_ALARM |
|
| 515 | HWMON_T_CRIT_HYST),
|
| 516 | HWMON_CHANNEL_INFO(in,
|
| 517 | HWMON_I_INPUT | HWMON_I_LCRIT | HWMON_I_LCRIT_ALARM |
|
| 518 | HWMON_I_CRIT | HWMON_I_CRIT_ALARM),
|
| 519 | HWMON_CHANNEL_INFO(curr,
|
| 520 | HWMON_C_INPUT | HWMON_C_LCRIT | HWMON_C_LCRIT_ALARM |
|
| 521 | HWMON_C_CRIT | HWMON_C_CRIT_ALARM,
|
| 522 | HWMON_C_INPUT),
|
| 523 | HWMON_CHANNEL_INFO(power,
|
| 524 | HWMON_P_INPUT | HWMON_P_CRIT | HWMON_P_CRIT_ALARM),
|
| 525 | NULL
|
| 526 | };
|
| 527 |
|
| 528 | static const struct hwmon_ops tmp51x_hwmon_ops = {
|
| 529 | .is_visible = tmp51x_is_visible,
|
| 530 | .read = tmp51x_read,
|
| 531 | .write = tmp51x_write,
|
| 532 | };
|
| 533 |
|
| 534 | static const struct hwmon_chip_info tmp51x_chip_info = {
|
| 535 | .ops = &tmp51x_hwmon_ops,
|
| 536 | .info = tmp51x_info,
|
| 537 | };
|
| 538 |
|
| 539 | |
| 540 | * Calibrate the tmp51x following the datasheet method
|
| 541 |
|
| 542 | static int tmp51x_calibrate(struct tmp51x_data *data)
|
| 543 | {
|
| 544 | int vshunt_max = data->pga_gain * 40;
|
| 545 | u64 max_curr_ma;
|
| 546 | u32 div;
|
| 547 |
|
| 548 | |
| 549 | * If shunt_uohms is equal to 0, the calibration should be set to 0.
|
| 550 | * The consequence will be that the current and power measurement engine
|
| 551 | * of the sensor will not work. Temperature and voltage sensing will
|
| 552 | * continue to work.
|
| 553 |
|
| 554 | if (data->shunt_uohms == 0)
|
| 555 | return regmap_write(data->regmap, TMP51X_SHUNT_CALIBRATION, 0);
|
| 556 |
|
| 557 | max_curr_ma = DIV_ROUND_CLOSEST_ULL(vshunt_max * MICRO, data->shunt_uohms);
|
| 558 |
|
| 559 | |
| 560 | * Calculate the minimal bit resolution for the current and the power.
|
| 561 | * Those values will be used during register interpretation.
|
| 562 |
|
| 563 | data->curr_lsb_ua = DIV_ROUND_CLOSEST_ULL(max_curr_ma * MILLI, 32767);
|
| 564 | data->pwr_lsb_uw = 20 * data->curr_lsb_ua;
|
| 565 |
|
| 566 | div = DIV_ROUND_CLOSEST_ULL(data->curr_lsb_ua * data->shunt_uohms, MICRO);
|
| 567 |
|
| 568 | return regmap_write(data->regmap, TMP51X_SHUNT_CALIBRATION,
|
| 569 | DIV_ROUND_CLOSEST(40960, div));
|
| 570 | }
|
| 571 |
|
| 572 | |
| 573 | * Initialize the configuration and calibration registers.
|
| 574 |
|
| 575 | static int tmp51x_init(struct tmp51x_data *data)
|
| 576 | {
|
| 577 | unsigned int regval;
|
| 578 | int ret = regmap_write(data->regmap, TMP51X_SHUNT_CONFIG,
|
| 579 | data->shunt_config);
|
| 580 | if (ret < 0)
|
| 581 | return ret;
|
| 582 |
|
| 583 | ret = regmap_write(data->regmap, TMP51X_TEMP_CONFIG, data->temp_config);
|
| 584 | if (ret < 0)
|
| 585 | return ret;
|
| 586 |
|
| 587 | |
| 588 | ret = regmap_update_bits(data->regmap, TMP51X_N_FACTOR_AND_HYST_1,
|
| 589 | TMP51X_NFACTOR_MASK, data->nfactor[0] << 8);
|
| 590 | if (ret < 0)
|
| 591 | return ret;
|
| 592 |
|
| 593 | ret = regmap_write(data->regmap, TMP51X_N_FACTOR_2,
|
| 594 | data->nfactor[1] << 8);
|
| 595 | if (ret < 0)
|
| 596 | return ret;
|
| 597 |
|
| 598 | if (data->max_channels == TMP513_MAX_CHANNELS) {
|
| 599 | ret = regmap_write(data->regmap, TMP513_N_FACTOR_3,
|
| 600 | data->nfactor[2] << 8);
|
| 601 | if (ret < 0)
|
| 602 | return ret;
|
| 603 | }
|
| 604 |
|
| 605 | ret = tmp51x_calibrate(data);
|
| 606 | if (ret < 0)
|
| 607 | return ret;
|
| 608 |
|
| 609 | |
| 610 | return regmap_read(data->regmap, TMP51X_STATUS, ®val);
|
| 611 | }
|
| 612 |
|
| 613 | static const struct i2c_device_id tmp51x_id[] = {
|
| 614 | { .name = "tmp512", .driver_data = TMP512_MAX_CHANNELS },
|
| 615 | { .name = "tmp513", .driver_data = TMP513_MAX_CHANNELS },
|
| 616 | { }
|
| 617 | };
|
| 618 | MODULE_DEVICE_TABLE(i2c, tmp51x_id);
|
| 619 |
|
| 620 | static const struct of_device_id tmp51x_of_match[] = {
|
| 621 | { .compatible = "ti,tmp512", .data = (void *)TMP512_MAX_CHANNELS },
|
| 622 | { .compatible = "ti,tmp513", .data = (void *)TMP513_MAX_CHANNELS },
|
| 623 | { }
|
| 624 | };
|
| 625 | MODULE_DEVICE_TABLE(of, tmp51x_of_match);
|
| 626 |
|
| 627 | static int tmp51x_vbus_range_to_reg(struct device *dev,
|
| 628 | struct tmp51x_data *data)
|
| 629 | {
|
| 630 | if (data->vbus_range_uvolt == TMP51X_VBUS_RANGE_32V) {
|
| 631 | data->shunt_config |= TMP51X_BUS_VOLTAGE_MASK;
|
| 632 | } else if (data->vbus_range_uvolt == TMP51X_VBUS_RANGE_16V) {
|
| 633 | data->shunt_config &= ~TMP51X_BUS_VOLTAGE_MASK;
|
| 634 | } else {
|
| 635 | return dev_err_probe(dev, -EINVAL,
|
| 636 | "ti,bus-range-microvolt is invalid: %u\n",
|
| 637 | data->vbus_range_uvolt);
|
| 638 | }
|
| 639 | return 0;
|
| 640 | }
|
| 641 |
|
| 642 | static int tmp51x_pga_gain_to_reg(struct device *dev, struct tmp51x_data *data)
|
| 643 | {
|
| 644 | if (data->pga_gain == 8) {
|
| 645 | data->shunt_config |= CURRENT_SENSE_VOLTAGE_320_MASK;
|
| 646 | } else if (data->pga_gain == 4) {
|
| 647 | data->shunt_config |= CURRENT_SENSE_VOLTAGE_160_MASK;
|
| 648 | } else if (data->pga_gain == 2) {
|
| 649 | data->shunt_config |= CURRENT_SENSE_VOLTAGE_80_MASK;
|
| 650 | } else if (data->pga_gain == 1) {
|
| 651 | data->shunt_config |= CURRENT_SENSE_VOLTAGE_40_MASK;
|
| 652 | } else {
|
| 653 | return dev_err_probe(dev, -EINVAL,
|
| 654 | "ti,pga-gain is invalid: %u\n", data->pga_gain);
|
| 655 | }
|
| 656 | return 0;
|
| 657 | }
|
| 658 |
|
| 659 | static int tmp51x_read_properties(struct device *dev, struct tmp51x_data *data)
|
| 660 | {
|
| 661 | int ret;
|
| 662 | u32 val;
|
| 663 |
|
| 664 | ret = device_property_read_u32(dev, "shunt-resistor-micro-ohms", &val);
|
| 665 | data->shunt_uohms = (ret >= 0) ? val : TMP51X_SHUNT_VALUE_DEFAULT;
|
| 666 |
|
| 667 | ret = device_property_read_u32(dev, "ti,bus-range-microvolt", &val);
|
| 668 | data->vbus_range_uvolt = (ret >= 0) ? val : TMP51X_VBUS_RANGE_DEFAULT;
|
| 669 | ret = tmp51x_vbus_range_to_reg(dev, data);
|
| 670 | if (ret < 0)
|
| 671 | return ret;
|
| 672 |
|
| 673 | ret = device_property_read_u32(dev, "ti,pga-gain", &val);
|
| 674 | data->pga_gain = (ret >= 0) ? val : TMP51X_PGA_DEFAULT;
|
| 675 | ret = tmp51x_pga_gain_to_reg(dev, data);
|
| 676 | if (ret < 0)
|
| 677 | return ret;
|
| 678 |
|
| 679 | device_property_read_u32_array(dev, "ti,nfactor", data->nfactor,
|
| 680 | data->max_channels - 1);
|
| 681 |
|
| 682 | |
| 683 | if (data->shunt_uohms > data->pga_gain * 40 * MICRO) {
|
| 684 | return dev_err_probe(dev, -EINVAL,
|
| 685 | "shunt-resistor: %u too big for pga_gain: %u\n",
|
| 686 | data->shunt_uohms, data->pga_gain);
|
| 687 | }
|
| 688 |
|
| 689 | return 0;
|
| 690 | }
|
| 691 |
|
| 692 | static void tmp51x_use_default(struct tmp51x_data *data)
|
| 693 | {
|
| 694 | data->vbus_range_uvolt = TMP51X_VBUS_RANGE_DEFAULT;
|
| 695 | data->pga_gain = TMP51X_PGA_DEFAULT;
|
| 696 | data->shunt_uohms = TMP51X_SHUNT_VALUE_DEFAULT;
|
| 697 | }
|
| 698 |
|
| 699 | static int tmp51x_configure(struct device *dev, struct tmp51x_data *data)
|
| 700 | {
|
| 701 | data->shunt_config = TMP51X_SHUNT_CONFIG_DEFAULT;
|
| 702 | data->temp_config = TMP51X_TEMP_CONFIG_DEFAULT(data->max_channels);
|
| 703 |
|
| 704 | if (dev->of_node)
|
| 705 | return tmp51x_read_properties(dev, data);
|
| 706 |
|
| 707 | tmp51x_use_default(data);
|
| 708 |
|
| 709 | return 0;
|
| 710 | }
|
| 711 |
|
| 712 | static int tmp51x_probe(struct i2c_client *client)
|
| 713 | {
|
| 714 | struct device *dev = &client->dev;
|
| 715 | struct tmp51x_data *data;
|
| 716 | struct device *hwmon_dev;
|
| 717 | int ret;
|
| 718 |
|
| 719 | data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
| 720 | if (!data)
|
| 721 | return -ENOMEM;
|
| 722 |
|
| 723 | data->max_channels = (uintptr_t)i2c_get_match_data(client);
|
| 724 |
|
| 725 | ret = tmp51x_configure(dev, data);
|
| 726 | if (ret < 0)
|
| 727 | return dev_err_probe(dev, ret, "error configuring the device\n");
|
| 728 |
|
| 729 | data->regmap = devm_regmap_init_i2c(client, &tmp51x_regmap_config);
|
| 730 | if (IS_ERR(data->regmap))
|
| 731 | return dev_err_probe(dev, PTR_ERR(data->regmap),
|
| 732 | "failed to allocate register map\n");
|
| 733 |
|
| 734 | ret = tmp51x_init(data);
|
| 735 | if (ret < 0)
|
| 736 | return dev_err_probe(dev, ret, "error configuring the device\n");
|
| 737 |
|
| 738 | hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
|
| 739 | data,
|
| 740 | &tmp51x_chip_info,
|
| 741 | NULL);
|
| 742 | if (IS_ERR(hwmon_dev))
|
| 743 | return PTR_ERR(hwmon_dev);
|
| 744 |
|
| 745 | dev_dbg(dev, "power monitor %s\n", client->name);
|
| 746 |
|
| 747 | return 0;
|
| 748 | }
|
| 749 |
|
| 750 | static struct i2c_driver tmp51x_driver = {
|
| 751 | .driver = {
|
| 752 | .name = "tmp51x",
|
| 753 | .of_match_table = tmp51x_of_match,
|
| 754 | },
|
| 755 | .probe = tmp51x_probe,
|
| 756 | .id_table = tmp51x_id,
|
| 757 | };
|
| 758 |
|
| 759 | module_i2c_driver(tmp51x_driver);
|
| 760 |
|
| 761 | MODULE_AUTHOR("Eric Tremblay <[email protected]>");
|
| 762 | MODULE_DESCRIPTION("tmp51x driver");
|
| 763 | MODULE_LICENSE("GPL");
|