Lines Matching +full:shunt +full:- +full:resistor +full:- +full:micro +full:- +full:ohms

1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright (C) 2016 Texas Instruments Incorporated - https://www.ti.com/
10 #include <linux/hwmon-sysfs.h>
53 #define INA3221_CONFIG_CHx_EN(x) BIT(14 - (x))
70 /* Alert Flags: SF is the summation-alert flag */
98 * struct ina3221_input - channel input source specific information
100 * @shunt_resistor: shunt resistor value of channel input source
110 * struct ina3221_data - device specific information
117 * @summation_shunt_resistor: equivalent shunt resistor value for summation
118 * @single_shot: running in single-shot operating mode
134 /* Summation channel checks shunt resistor values */ in ina3221_is_enabled()
136 return ina->summation_shunt_resistor != 0; in ina3221_is_enabled()
138 return pm_runtime_active(ina->pm_dev) && in ina3221_is_enabled()
139 (ina->reg_config & INA3221_CONFIG_CHx_EN(channel)); in ina3221_is_enabled()
143 * Helper function to return the resistor value for current summation.
145 * There is a condition to calculate current summation -- all the shunt
146 * resistor values should be the same, so as to simply fit the formula:
147 * current summation = shunt voltage summation / shunt resistor
149 * Returns the equivalent shunt resistor value on success or 0 on failure
153 struct ina3221_input *input = ina->inputs; in ina3221_summation_shunt_resistor()
160 /* Found the reference shunt resistor value */ in ina3221_summation_shunt_resistor()
163 /* No summation if resistor values are different */ in ina3221_summation_shunt_resistor()
172 /* Lookup table for Bus and Shunt conversion times in usec */
189 /* Bisect the result to Bus and Shunt conversion times */ in ina3221_interval_ms_to_conv_time()
212 wait = ina3221_reg_to_interval_us(ina->reg_config); in ina3221_wait_for_data()
215 return regmap_field_read_poll_timeout(ina->fields[F_CVRF], in ina3221_wait_for_data()
225 ret = regmap_read(ina->regmap, reg, &regval); in ina3221_read_value()
230 * Shunt Voltage Sum register has 14-bit value with 1-bit shift in ina3221_read_value()
231 * Other Shunt Voltage registers have 12 bits with 3-bit shift in ina3221_read_value()
258 regval = INA3221_CONFIG_AVG(ina->reg_config); in ina3221_read_chip()
263 *val = ina3221_reg_to_interval_us(ina->reg_config); in ina3221_read_chip()
267 return -EOPNOTSUPP; in ina3221_read_chip()
279 * Translate shunt channel index to sensor channel index except in ina3221_read_in()
280 * the 7th channel (6 since being 0-aligned) is for summation. in ina3221_read_in()
288 return -ENODATA; in ina3221_read_in()
290 /* Write CONFIG register to trigger a single-shot measurement */ in ina3221_read_in()
291 if (ina->single_shot) in ina3221_read_in()
292 regmap_write(ina->regmap, INA3221_CONFIG, in ina3221_read_in()
293 ina->reg_config); in ina3221_read_in()
304 * Scale of shunt voltage (uV): LSB is 40uV in ina3221_read_in()
313 return -EOPNOTSUPP; in ina3221_read_in()
331 struct ina3221_input *input = ina->inputs; in ina3221_read_curr()
337 resistance_uo = ina->summation_shunt_resistor; in ina3221_read_curr()
344 return -ENODATA; in ina3221_read_curr()
346 /* Write CONFIG register to trigger a single-shot measurement */ in ina3221_read_curr()
347 if (ina->single_shot) in ina3221_read_curr()
348 regmap_write(ina->regmap, INA3221_CONFIG, in ina3221_read_curr()
349 ina->reg_config); in ina3221_read_curr()
359 return -ENODATA; in ina3221_read_curr()
365 /* Scale of shunt voltage: LSB is 40uV (40000nV) */ in ina3221_read_curr()
378 ret = regmap_field_read(ina->fields[reg], &regval); in ina3221_read_curr()
384 return -EOPNOTSUPP; in ina3221_read_curr()
399 tmp = (ina->reg_config & ~INA3221_CONFIG_AVG_MASK) | in ina3221_write_chip()
401 ret = regmap_write(ina->regmap, INA3221_CONFIG, tmp); in ina3221_write_chip()
406 ina->reg_config = tmp; in ina3221_write_chip()
409 tmp = ina3221_interval_ms_to_conv_time(ina->reg_config, val); in ina3221_write_chip()
413 /* Update Bus and Shunt voltage conversion times */ in ina3221_write_chip()
415 tmp = (ina->reg_config & ~tmp) | in ina3221_write_chip()
418 ret = regmap_write(ina->regmap, INA3221_CONFIG, tmp); in ina3221_write_chip()
423 ina->reg_config = tmp; in ina3221_write_chip()
426 return -EOPNOTSUPP; in ina3221_write_chip()
434 struct ina3221_input *input = ina->inputs; in ina3221_write_curr()
440 resistance_uo = ina->summation_shunt_resistor; in ina3221_write_curr()
445 return -EOPNOTSUPP; in ina3221_write_curr()
455 voltage_uv = clamp_val(voltage_uv, -163800, 163800); in ina3221_write_curr()
461 * The scale is 40uV for all shunt voltage registers in ina3221_write_curr()
462 * Shunt Voltage Sum register left-shifts 1 bit in ina3221_write_curr()
463 * All other Shunt Voltage registers shift 3 bits in ina3221_write_curr()
466 * SHUNT[1-3]: (1 / 40uV) << 3 = 1 / 5uV in ina3221_write_curr()
473 return regmap_write(ina->regmap, reg, regval); in ina3221_write_curr()
480 u16 config_old = ina->reg_config & mask; in ina3221_write_enable()
492 ret = pm_runtime_get_sync(ina->pm_dev); in ina3221_write_enable()
500 tmp = (ina->reg_config & ~mask) | (config & mask); in ina3221_write_enable()
501 ret = regmap_write(ina->regmap, INA3221_CONFIG, tmp); in ina3221_write_enable()
506 ina->reg_config = tmp; in ina3221_write_enable()
510 pm_runtime_put_sync(ina->pm_dev); in ina3221_write_enable()
518 pm_runtime_put_sync(ina->pm_dev); in ina3221_write_enable()
530 mutex_lock(&ina->lock); in ina3221_read()
537 /* 0-align channel ID */ in ina3221_read()
538 ret = ina3221_read_in(dev, attr, channel - 1, val); in ina3221_read()
544 ret = -EOPNOTSUPP; in ina3221_read()
548 mutex_unlock(&ina->lock); in ina3221_read()
559 mutex_lock(&ina->lock); in ina3221_write()
566 /* 0-align channel ID */ in ina3221_write()
567 ret = ina3221_write_enable(dev, channel - 1, val); in ina3221_write()
573 ret = -EOPNOTSUPP; in ina3221_write()
577 mutex_unlock(&ina->lock); in ina3221_write()
586 int index = channel - 1; in ina3221_read_string()
589 *str = "sum of shunt voltages"; in ina3221_read_string()
591 *str = ina->inputs[index].label; in ina3221_read_string()
619 if (channel - 1 <= INA3221_CHANNEL3) in ina3221_is_visible()
620 input = &ina->inputs[channel - 1]; in ina3221_is_visible()
624 return (input && input->label) ? 0444 : 0; in ina3221_is_visible()
660 /* 1-3: input voltage Channels */
664 /* 4-6: shunt voltage Channels */
668 /* 7: summation of shunt voltage channels */
671 /* 1-3: current channels*/
698 unsigned int channel = sd_attr->index; in ina3221_shunt_show()
699 struct ina3221_input *input = &ina->inputs[channel]; in ina3221_shunt_show()
701 return snprintf(buf, PAGE_SIZE, "%d\n", input->shunt_resistor); in ina3221_shunt_show()
710 unsigned int channel = sd_attr->index; in ina3221_shunt_store()
711 struct ina3221_input *input = &ina->inputs[channel]; in ina3221_shunt_store()
721 input->shunt_resistor = val; in ina3221_shunt_store()
724 ina->summation_shunt_resistor = ina3221_summation_shunt_resistor(ina); in ina3221_shunt_store()
729 /* shunt resistance */
778 input = &ina->inputs[val]; in ina3221_probe_child_from_dt()
782 input->disconnected = true; in ina3221_probe_child_from_dt()
787 of_property_read_string(child, "label", &input->label); in ina3221_probe_child_from_dt()
789 /* Overwrite default shunt resistor value optionally */ in ina3221_probe_child_from_dt()
790 if (!of_property_read_u32(child, "shunt-resistor-micro-ohms", &val)) { in ina3221_probe_child_from_dt()
792 dev_err(dev, "invalid shunt resistor value %u of %pOFn\n", in ina3221_probe_child_from_dt()
794 return -EINVAL; in ina3221_probe_child_from_dt()
796 input->shunt_resistor = val; in ina3221_probe_child_from_dt()
804 const struct device_node *np = dev->of_node; in ina3221_probe_from_dt()
808 /* Compatible with non-DT platforms */ in ina3221_probe_from_dt()
812 ina->single_shot = of_property_read_bool(np, "ti,single-shot"); in ina3221_probe_from_dt()
827 struct device *dev = &client->dev; in ina3221_probe()
834 return -ENOMEM; in ina3221_probe()
836 ina->regmap = devm_regmap_init_i2c(client, &ina3221_regmap_config); in ina3221_probe()
837 if (IS_ERR(ina->regmap)) { in ina3221_probe()
839 return PTR_ERR(ina->regmap); in ina3221_probe()
843 ina->fields[i] = devm_regmap_field_alloc(dev, in ina3221_probe()
844 ina->regmap, in ina3221_probe()
846 if (IS_ERR(ina->fields[i])) { in ina3221_probe()
848 return PTR_ERR(ina->fields[i]); in ina3221_probe()
853 ina->inputs[i].shunt_resistor = INA3221_RSHUNT_DEFAULT; in ina3221_probe()
862 ina->reg_config = INA3221_CONFIG_DEFAULT; in ina3221_probe()
864 /* Clear continuous bit to use single-shot mode */ in ina3221_probe()
865 if (ina->single_shot) in ina3221_probe()
866 ina->reg_config &= ~INA3221_CONFIG_MODE_CONTINUOUS; in ina3221_probe()
870 if (ina->inputs[i].disconnected) in ina3221_probe()
871 ina->reg_config &= ~INA3221_CONFIG_CHx_EN(i); in ina3221_probe()
875 ina->summation_shunt_resistor = ina3221_summation_shunt_resistor(ina); in ina3221_probe()
877 ina->pm_dev = dev; in ina3221_probe()
878 mutex_init(&ina->lock); in ina3221_probe()
881 /* Enable PM runtime -- status is suspended by default */ in ina3221_probe()
882 pm_runtime_enable(ina->pm_dev); in ina3221_probe()
886 if (ina->inputs[i].disconnected) in ina3221_probe()
889 ret = pm_runtime_get_sync(ina->pm_dev); in ina3221_probe()
894 hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, ina, in ina3221_probe()
906 pm_runtime_disable(ina->pm_dev); in ina3221_probe()
907 pm_runtime_set_suspended(ina->pm_dev); in ina3221_probe()
910 pm_runtime_put_noidle(ina->pm_dev); in ina3221_probe()
911 mutex_destroy(&ina->lock); in ina3221_probe()
918 struct ina3221_data *ina = dev_get_drvdata(&client->dev); in ina3221_remove()
921 pm_runtime_disable(ina->pm_dev); in ina3221_remove()
922 pm_runtime_set_suspended(ina->pm_dev); in ina3221_remove()
926 pm_runtime_put_noidle(ina->pm_dev); in ina3221_remove()
928 mutex_destroy(&ina->lock); in ina3221_remove()
938 /* Save config register value and enable cache-only */ in ina3221_suspend()
939 ret = regmap_read(ina->regmap, INA3221_CONFIG, &ina->reg_config); in ina3221_suspend()
943 /* Set to power-down mode for power saving */ in ina3221_suspend()
944 ret = regmap_update_bits(ina->regmap, INA3221_CONFIG, in ina3221_suspend()
950 regcache_cache_only(ina->regmap, true); in ina3221_suspend()
951 regcache_mark_dirty(ina->regmap); in ina3221_suspend()
961 regcache_cache_only(ina->regmap, false); in ina3221_resume()
964 ret = regmap_field_write(ina->fields[F_RST], true); in ina3221_resume()
971 ret = regcache_sync(ina->regmap); in ina3221_resume()
976 ret = regmap_write(ina->regmap, INA3221_CONFIG, ina->reg_config); in ina3221_resume()
981 if (ina->summation_shunt_resistor) { in ina3221_resume()
984 * Shunt measurements of disconnected channels should in ina3221_resume()
987 ret = regmap_update_bits(ina->regmap, INA3221_MASK_ENABLE, in ina3221_resume()