Lines Matching +full:rsense +full:- +full:share

1 // SPDX-License-Identifier: GPL-2.0
10 #include <linux/clk-provider.h>
15 #include <linux/hwmon-sysfs.h>
115 #define LTC4282_CLKIN_RANGE (LTC4282_CLKIN_MAX - LTC4282_CLKIN_MIN + 1)
140 * when hwmon is not enabled for that channel. Needed because they share
146 u32 rsense; member
168 return regmap_update_bits(st->map, LTC4282_CLK_DIV, LTC4282_CLKOUT_MASK, in ltc4282_set_rate()
183 int idx = find_closest(req->rate, ltc4282_out_rates, in ltc4282_determine_rate()
186 req->rate = ltc4282_out_rates[idx]; in ltc4282_determine_rate()
199 ret = regmap_read(st->map, LTC4282_CLK_DIV, &clkdiv); in ltc4282_recalc_rate()
217 regmap_clear_bits(st->map, LTC4282_CLK_DIV, LTC4282_CLKOUT_MASK); in ltc4282_disable()
226 ret = regmap_bulk_read(st->map, reg, &in, sizeof(in)); in ltc4282_read_voltage_word()
248 ret = regmap_read(st->map, reg, &in); in ltc4282_read_voltage_byte_cached()
269 ret = regmap_read(st->map, reg, &alarm); in __ltc4282_read_alarm()
277 return regmap_clear_bits(st->map, reg, mask); in __ltc4282_read_alarm()
285 guard(mutex)(&st->lock); in ltc4282_read_alarm()
292 guard(mutex)(&st->lock); in ltc4282_vdd_source_read_in()
293 if (!st->in0_1_cache[channel].en) in ltc4282_vdd_source_read_in()
294 return -ENODATA; in ltc4282_vdd_source_read_in()
296 return ltc4282_read_voltage_word(st, LTC4282_VSOURCE, st->vfs_out, val); in ltc4282_vdd_source_read_in()
304 guard(mutex)(&st->lock); in ltc4282_vdd_source_read_hist()
305 if (!st->in0_1_cache[channel].en) { in ltc4282_vdd_source_read_hist()
310 ret = ltc4282_read_voltage_word(st, reg, st->vfs_out, val); in ltc4282_vdd_source_read_hist()
321 guard(mutex)(&st->lock); in ltc4282_vdd_source_read_lim()
322 if (!st->in0_1_cache[channel].en) in ltc4282_vdd_source_read_lim()
323 return ltc4282_read_voltage_byte_cached(st, reg, st->vfs_out, in ltc4282_vdd_source_read_lim()
326 return ltc4282_read_voltage_byte(st, reg, st->vfs_out, val); in ltc4282_vdd_source_read_lim()
332 guard(mutex)(&st->lock); in ltc4282_vdd_source_read_alm()
333 if (!st->in0_1_cache[channel].en) { in ltc4282_vdd_source_read_alm()
367 &st->in0_1_cache[channel].in_highest, val); in ltc4282_read_in()
375 &st->in0_1_cache[channel].in_lowest, val); in ltc4282_read_in()
406 &st->in0_1_cache[channel].in_max_raw, val); in ltc4282_read_in()
414 &st->in0_1_cache[channel].in_min_raw, val); in ltc4282_read_in()
416 scoped_guard(mutex, &st->lock) { in ltc4282_read_in()
417 *val = st->in0_1_cache[channel].en; in ltc4282_read_in()
428 return -EOPNOTSUPP; in ltc4282_read_in()
446 *val = DIV_ROUND_CLOSEST(in * MILLI, st->rsense); in ltc4282_read_current_word()
461 *val = DIV_ROUND_CLOSEST(in * MILLI, st->rsense); in ltc4282_read_current_byte()
492 return -EOPNOTSUPP; in ltc4282_read_curr()
499 u64 temp = DECA * 40ULL * st->vfs_out * BIT(16), temp_2; in ltc4282_read_power_word()
504 ret = regmap_bulk_read(st->map, reg, &raw, sizeof(raw)); in ltc4282_read_power_word()
511 * P = CODE(16b) * 0.040 * Vfs(out) * 2^16 / ((2^16 - 1)^2 * Rsense) in ltc4282_read_power_word()
516 U16_MAX * (u64)st->rsense); in ltc4282_read_power_word()
521 st->rsense * int_pow(U16_MAX, 2)); in ltc4282_read_power_word()
533 ret = regmap_read(st->map, reg, &power); in ltc4282_read_power_byte()
537 temp = power * 40 * DECA * st->vfs_out * BIT_ULL(8); in ltc4282_read_power_byte()
539 int_pow(U8_MAX, 2) * st->rsense); in ltc4282_read_power_byte()
550 ret = regmap_bulk_read(st->map, LTC4282_ENERGY, &raw, 6); in ltc4282_read_energy()
558 * ((2^16 - 1)^2 * Rsense) in ltc4282_read_energy()
562 * E = CODE(48b) * 40 * Vfs(out) * 256 / (U16_MAX * Rsense) in ltc4282_read_energy()
564 * As Rsense can have tenths of micro-ohm resolution, we need to in ltc4282_read_energy()
567 if (check_mul_overflow(DECA * st->vfs_out * 40 * BIT(8), energy, &temp)) { in ltc4282_read_energy()
568 temp = DIV_ROUND_CLOSEST(DECA * st->vfs_out * 40 * BIT(8), U16_MAX); in ltc4282_read_energy()
569 *val = DIV_ROUND_CLOSEST_ULL(temp * energy, st->rsense); in ltc4282_read_energy()
573 *val = DIV64_U64_ROUND_CLOSEST(temp, U16_MAX * (u64)st->rsense); in ltc4282_read_energy()
599 return -EOPNOTSUPP; in ltc4282_read_power()
616 scoped_guard(mutex, &st->lock) { in ltc4282_read()
617 *val = st->energy_en; in ltc4282_read()
621 return -EOPNOTSUPP; in ltc4282_read()
631 if (val > st->power_max) in ltc4282_write_power_byte()
632 val = st->power_max; in ltc4282_write_power_byte()
634 temp = val * int_pow(U8_MAX, 2) * st->rsense; in ltc4282_write_power_byte()
636 MICRO * DECA * 256ULL * st->vfs_out * 40); in ltc4282_write_power_byte()
638 return regmap_write(st->map, reg, power); in ltc4282_write_power_byte()
644 u64 temp = int_pow(U16_MAX, 2) * st->rsense, temp_2; in ltc4282_write_power_word()
651 40ULL * BIT(16) * st->vfs_out); in ltc4282_write_power_word()
653 temp = DECA * MICRO * 40ULL * BIT(16) * st->vfs_out; in ltc4282_write_power_word()
658 return regmap_bulk_write(st->map, reg, &__raw, sizeof(__raw)); in ltc4282_write_power_word()
672 ret = regmap_bulk_write(st->map, reg, &__raw, 2); in __ltc4282_in_write_history()
680 return regmap_bulk_write(st->map, reg + 2, &__raw, 2); in __ltc4282_in_write_history()
686 guard(mutex)(&st->lock); in ltc4282_in_write_history()
694 guard(mutex)(&st->lock); in ltc4282_power_reset_hist()
697 st->power_max); in ltc4282_power_reset_hist()
706 return regmap_clear_bits(st->map, LTC4282_FAULT_LOG, in ltc4282_power_reset_hist()
721 return -EOPNOTSUPP; in ltc4282_write_power()
739 return regmap_write(st->map, reg, in); in ltc4282_write_voltage_byte_cached()
753 ret = ltc4282_read_voltage_word(st, LTC4282_VSOURCE_LOWEST, st->vfs_out, in ltc4282_cache_history()
758 st->in0_1_cache[channel].in_lowest = val; in ltc4282_cache_history()
761 st->vfs_out, &val); in ltc4282_cache_history()
765 st->in0_1_cache[channel].in_highest = val; in ltc4282_cache_history()
767 ret = regmap_read(st->map, LTC4282_VSOURCE_MIN, in ltc4282_cache_history()
768 &st->in0_1_cache[channel].in_min_raw); in ltc4282_cache_history()
772 return regmap_read(st->map, LTC4282_VSOURCE_MAX, in ltc4282_cache_history()
773 &st->in0_1_cache[channel].in_max_raw); in ltc4282_cache_history()
781 st->in0_1_cache[channel].in_lowest, in ltc4282_cache_sync()
782 st->in0_1_cache[channel].in_highest, in ltc4282_cache_sync()
783 st->vfs_out); in ltc4282_cache_sync()
787 ret = regmap_write(st->map, LTC4282_VSOURCE_MIN, in ltc4282_cache_sync()
788 st->in0_1_cache[channel].in_min_raw); in ltc4282_cache_sync()
792 return regmap_write(st->map, LTC4282_VSOURCE_MAX, in ltc4282_cache_sync()
793 st->in0_1_cache[channel].in_max_raw); in ltc4282_cache_sync()
801 guard(mutex)(&st->lock); in ltc4282_vdd_source_write_lim()
802 if (st->in0_1_cache[channel].en) in ltc4282_vdd_source_write_lim()
803 ret = ltc4282_write_voltage_byte(st, reg, st->vfs_out, val); in ltc4282_vdd_source_write_lim()
805 ret = ltc4282_write_voltage_byte_cached(st, reg, st->vfs_out, in ltc4282_vdd_source_write_lim()
813 long lowest = st->vfs_out; in ltc4282_vdd_source_reset_hist()
817 lowest = st->vdd; in ltc4282_vdd_source_reset_hist()
819 guard(mutex)(&st->lock); in ltc4282_vdd_source_reset_hist()
820 if (st->in0_1_cache[channel].en) { in ltc4282_vdd_source_reset_hist()
822 lowest, 0, st->vfs_out); in ltc4282_vdd_source_reset_hist()
827 st->in0_1_cache[channel].in_lowest = lowest; in ltc4282_vdd_source_reset_hist()
828 st->in0_1_cache[channel].in_highest = 0; in ltc4282_vdd_source_reset_hist()
839 return regmap_clear_bits(st->map, LTC4282_FAULT_LOG, in ltc4282_vdd_source_reset_hist()
842 return regmap_clear_bits(st->map, LTC4282_FAULT_LOG, in ltc4282_vdd_source_reset_hist()
851 * automatically have the reverse effect on VSOURCE and vice-versa.
859 guard(mutex)(&st->lock); in ltc4282_vdd_source_enable()
860 if (st->in0_1_cache[channel].en == !!val) in ltc4282_vdd_source_enable()
867 ret = regmap_update_bits(st->map, LTC4282_ILIM_ADJUST, in ltc4282_vdd_source_enable()
873 st->in0_1_cache[channel].en = !!val; in ltc4282_vdd_source_enable()
874 st->in0_1_cache[other_chan].en = !val; in ltc4282_vdd_source_enable()
876 if (st->in0_1_cache[channel].en) { in ltc4282_vdd_source_enable()
909 &st->in0_1_cache[channel].in_max_raw, val); in ltc4282_write_in()
917 &st->in0_1_cache[channel].in_min_raw, val); in ltc4282_write_in()
928 return -EOPNOTSUPP; in ltc4282_write_in()
936 guard(mutex)(&st->lock); in ltc4282_curr_reset_hist()
939 st->vsense_max, 0, 40 * MILLI); in ltc4282_curr_reset_hist()
944 return regmap_clear_bits(st->map, LTC4282_FAULT_LOG, in ltc4282_curr_reset_hist()
952 u32 in = DIV_ROUND_CLOSEST_ULL((u64)val * st->rsense, DECA * MICRO); in ltc4282_write_curr()
964 return -EOPNOTSUPP; in ltc4282_write_curr()
972 guard(mutex)(&st->lock); in ltc4282_energy_enable_set()
974 ret = regmap_update_bits(st->map, LTC4282_ADC_CTRL, in ltc4282_energy_enable_set()
980 st->energy_en = !!val; in ltc4282_energy_enable_set()
1001 return -EOPNOTSUPP; in ltc4282_write()
1105 return -EOPNOTSUPP; in ltc4282_read_labels()
1116 guard(mutex)(&st->lock); in ltc4282_energy_show()
1117 if (!st->energy_en) in ltc4282_energy_show()
1118 return -ENODATA; in ltc4282_energy_show()
1143 init.name = devm_kasprintf(dev, GFP_KERNEL, "%s-clk", in ltc428_clk_provider_setup()
1146 return -ENOMEM; in ltc428_clk_provider_setup()
1150 st->clk_hw.init = &init; in ltc428_clk_provider_setup()
1152 ret = devm_clk_hw_register(dev, &st->clk_hw); in ltc428_clk_provider_setup()
1157 &st->clk_hw); in ltc428_clk_provider_setup()
1180 return dev_err_probe(dev, -EINVAL, in ltc428_clks_setup()
1191 return regmap_update_bits(st->map, LTC4282_CLK_DIV, in ltc428_clks_setup()
1205 ret = regmap_read(st->map, LTC4282_ADC_CTRL, &reg_val); in ltc4282_get_defaults()
1209 st->energy_en = !FIELD_GET(LTC4282_METER_HALT_MASK, reg_val); in ltc4282_get_defaults()
1211 ret = regmap_read(st->map, LTC4282_CTRL_MSB, &reg_val); in ltc4282_get_defaults()
1217 ret = regmap_read(st->map, LTC4282_ILIM_ADJUST, &reg_val); in ltc4282_get_defaults()
1222 st->vsense_max = ltc4282_curr_lim_uv[ilm_adjust]; in ltc4282_get_defaults()
1224 st->in0_1_cache[LTC4282_CHAN_VSOURCE].en = FIELD_GET(LTC4282_VDD_MONITOR_MASK, in ltc4282_get_defaults()
1226 if (!st->in0_1_cache[LTC4282_CHAN_VSOURCE].en) { in ltc4282_get_defaults()
1227 st->in0_1_cache[LTC4282_CHAN_VDD].en = true; in ltc4282_get_defaults()
1228 return regmap_read(st->map, LTC4282_VSOURCE_MAX, in ltc4282_get_defaults()
1229 &st->in0_1_cache[LTC4282_CHAN_VSOURCE].in_max_raw); in ltc4282_get_defaults()
1232 return regmap_read(st->map, LTC4282_VSOURCE_MAX, in ltc4282_get_defaults()
1233 &st->in0_1_cache[LTC4282_CHAN_VDD].in_max_raw); in ltc4282_get_defaults()
1238 * rsense that is defined in ILIM_ADJUST. This is specially important for power
1239 * because for some rsense and vfsout values, if we allow the default raw 255
1251 st->vsense_max); in ltc4282_set_max_limits()
1256 st->power_max = DIV_ROUND_CLOSEST(st->vsense_max * DECA * MILLI, st->rsense) * st->vfs_out; in ltc4282_set_max_limits()
1257 ret = ltc4282_write_power_byte(st, LTC4282_POWER_MAX, st->power_max); in ltc4282_set_max_limits()
1261 if (st->in0_1_cache[LTC4282_CHAN_VDD].en) { in ltc4282_set_max_limits()
1262 st->in0_1_cache[LTC4282_CHAN_VSOURCE].in_lowest = st->vfs_out; in ltc4282_set_max_limits()
1264 st->vdd, 0, st->vfs_out); in ltc4282_set_max_limits()
1267 st->in0_1_cache[LTC4282_CHAN_VDD].in_lowest = st->vdd; in ltc4282_set_max_limits()
1269 st->vfs_out, 0, st->vfs_out); in ltc4282_set_max_limits()
1285 ret = device_property_read_string(dev, "adi,gpio1-mode", &func); in ltc4282_gpio_setup()
1294 ret = regmap_update_bits(st->map, LTC4282_GPIO_CONFIG, in ltc4282_gpio_setup()
1301 ret = device_property_read_string(dev, "adi,gpio2-mode", &func); in ltc4282_gpio_setup()
1311 ret = regmap_set_bits(st->map, LTC4282_ILIM_ADJUST, in ltc4282_gpio_setup()
1314 ret = regmap_update_bits(st->map, LTC4282_GPIO_CONFIG, in ltc4282_gpio_setup()
1323 if (!device_property_read_bool(dev, "adi,gpio3-monitor-enable")) in ltc4282_gpio_setup()
1327 return dev_err_probe(dev, -EINVAL, in ltc4282_gpio_setup()
1330 return regmap_clear_bits(st->map, LTC4282_ILIM_ADJUST, in ltc4282_gpio_setup()
1361 ret = device_property_read_u32(dev, "adi,rsense-nano-ohms", in ltc4282_setup()
1362 &st->rsense); in ltc4282_setup()
1365 "Failed to read adi,rsense-nano-ohms\n"); in ltc4282_setup()
1366 if (st->rsense < CENTI) in ltc4282_setup()
1367 return dev_err_probe(dev, -EINVAL, in ltc4282_setup()
1368 "adi,rsense-nano-ohms too small (< %lu)\n", in ltc4282_setup()
1372 * The resolution for rsense is tenths of micro (eg: 62.5 uOhm) which in ltc4282_setup()
1377 st->rsense /= CENTI; in ltc4282_setup()
1380 ret = device_property_read_u32(dev, "adi,vin-mode-microvolt", &val); in ltc4282_setup()
1396 return dev_err_probe(dev, -EINVAL, in ltc4282_setup()
1397 "Invalid val(%u) for vin-mode-microvolt\n", in ltc4282_setup()
1401 ret = regmap_update_bits(st->map, LTC4282_CTRL_MSB, in ltc4282_setup()
1408 ret = regmap_update_bits(st->map, LTC4282_ILIM_ADJUST, in ltc4282_setup()
1415 st->vfs_out = ltc4282_vfs_milli[val]; in ltc4282_setup()
1416 st->vdd = ltc4282_vdd_milli[val]; in ltc4282_setup()
1418 ret = device_property_read_u32(dev, "adi,current-limit-sense-microvolt", in ltc4282_setup()
1419 &st->vsense_max); in ltc4282_setup()
1449 return dev_err_probe(dev, -EINVAL, in ltc4282_setup()
1450 "Invalid val(%u) for adi,current-limit-microvolt\n", in ltc4282_setup()
1451 st->vsense_max); in ltc4282_setup()
1454 ret = regmap_update_bits(st->map, LTC4282_ILIM_ADJUST, in ltc4282_setup()
1465 ret = device_property_read_string(dev, "adi,overvoltage-dividers", in ltc4282_setup()
1471 return dev_err_probe(dev, -EINVAL, in ltc4282_setup()
1472 "Invalid val(%s) for adi,overvoltage-divider\n", in ltc4282_setup()
1475 ret = regmap_update_bits(st->map, LTC4282_CTRL_MSB, in ltc4282_setup()
1480 ret = device_property_read_string(dev, "adi,undervoltage-dividers", in ltc4282_setup()
1486 return dev_err_probe(dev, -EINVAL, in ltc4282_setup()
1487 "Invalid val(%s) for adi,undervoltage-divider\n", in ltc4282_setup()
1490 ret = regmap_update_bits(st->map, LTC4282_CTRL_MSB, in ltc4282_setup()
1495 if (device_property_read_bool(dev, "adi,overcurrent-retry")) { in ltc4282_setup()
1496 ret = regmap_set_bits(st->map, LTC4282_CTRL_LSB, in ltc4282_setup()
1502 if (device_property_read_bool(dev, "adi,overvoltage-retry-disable")) { in ltc4282_setup()
1503 ret = regmap_clear_bits(st->map, LTC4282_CTRL_LSB, in ltc4282_setup()
1509 if (device_property_read_bool(dev, "adi,undervoltage-retry-disable")) { in ltc4282_setup()
1510 ret = regmap_clear_bits(st->map, LTC4282_CTRL_LSB, in ltc4282_setup()
1516 if (device_property_read_bool(dev, "adi,fault-log-enable")) { in ltc4282_setup()
1517 ret = regmap_set_bits(st->map, LTC4282_ADC_CTRL, LTC4282_FAULT_LOG_EN_MASK); in ltc4282_setup()
1522 ret = device_property_read_u32(dev, "adi,fet-bad-timeout-ms", &val); in ltc4282_setup()
1525 return dev_err_probe(dev, -EINVAL, in ltc4282_setup()
1526 "Invalid value(%u) for adi,fet-bad-timeout-ms", in ltc4282_setup()
1529 ret = regmap_write(st->map, LTC4282_FET_BAD_FAULT_TIMEOUT, val); in ltc4282_setup()
1674 debugfs_create_file_unsafe("power1_bad_fault_log", 0400, i2c->debugfs, st, in ltc4282_debugfs_init()
1676 debugfs_create_file_unsafe("in0_fet_short_fault_log", 0400, i2c->debugfs, st, in ltc4282_debugfs_init()
1678 debugfs_create_file_unsafe("in0_fet_bad_fault_log", 0400, i2c->debugfs, st, in ltc4282_debugfs_init()
1680 debugfs_create_file_unsafe("in1_crit_fault_log", 0400, i2c->debugfs, st, in ltc4282_debugfs_init()
1682 debugfs_create_file_unsafe("in1_lcrit_fault_log", 0400, i2c->debugfs, st, in ltc4282_debugfs_init()
1684 debugfs_create_file_unsafe("curr1_crit_fault_log", 0400, i2c->debugfs, st, in ltc4282_debugfs_init()
1690 struct device *dev = &i2c->dev, *hwmon; in ltc4282_probe()
1696 return dev_err_probe(dev, -ENOMEM, in ltc4282_probe()
1699 st->map = devm_regmap_init_i2c(i2c, &ltc4282_regmap_config); in ltc4282_probe()
1700 if (IS_ERR(st->map)) in ltc4282_probe()
1701 return dev_err_probe(dev, PTR_ERR(st->map), in ltc4282_probe()
1705 ret = regmap_set_bits(st->map, LTC4282_ADC_CTRL, LTC4282_RESET_MASK); in ltc4282_probe()
1720 mutex_init(&st->lock); in ltc4282_probe()