Lines Matching +full:triple +full:- +full:channel
1 // SPDX-License-Identifier: GPL-2.0-only
3 * INA3221 Triple Current/Voltage Monitor
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
99 * @label: label of channel input source
100 * @shunt_resistor: shunt resistor value of channel input source
101 * @disconnected: connection status of channel input source
110 * struct ina3221_data - device specific information
114 * @inputs: Array of channel input source specific structures
118 * @single_shot: running in single-shot operating mode
132 static inline bool ina3221_is_enabled(struct ina3221_data *ina, int channel) in ina3221_is_enabled() argument
134 /* Summation channel checks shunt resistor values */ in ina3221_is_enabled()
135 if (channel > INA3221_CHANNEL3) 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()
145 * There is a condition to calculate current summation -- all the shunt
153 struct ina3221_input *input = ina->inputs; in ina3221_summation_shunt_resistor()
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, ®val); 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()
271 static int ina3221_read_in(struct device *dev, u32 attr, int channel, long *val) in ina3221_read_in() argument
273 const bool is_shunt = channel > INA3221_CHANNEL3; in ina3221_read_in()
275 u8 reg = ina3221_in_reg[channel]; in ina3221_read_in()
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()
282 if (channel != 6) in ina3221_read_in()
283 channel %= INA3221_NUM_CHANNELS; in ina3221_read_in()
287 if (!ina3221_is_enabled(ina, channel)) 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()
310 *val = ina3221_is_enabled(ina, channel); in ina3221_read_in()
313 return -EOPNOTSUPP; in ina3221_read_in()
328 int channel, long *val) in ina3221_read_curr() argument
331 struct ina3221_input *input = ina->inputs; in ina3221_read_curr()
332 u8 reg = ina3221_curr_reg[attr][channel]; in ina3221_read_curr()
336 if (channel > INA3221_CHANNEL3) in ina3221_read_curr()
337 resistance_uo = ina->summation_shunt_resistor; in ina3221_read_curr()
339 resistance_uo = input[channel].shunt_resistor; in ina3221_read_curr()
343 if (!ina3221_is_enabled(ina, channel)) 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()
372 /* No actual register read if channel is disabled */ in ina3221_read_curr()
373 if (!ina3221_is_enabled(ina, channel)) { in ina3221_read_curr()
378 ret = regmap_field_read(ina->fields[reg], ®val); 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()
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()
431 int channel, long val) in ina3221_write_curr() argument
434 struct ina3221_input *input = ina->inputs; in ina3221_write_curr()
435 u8 reg = ina3221_curr_reg[attr][channel]; in ina3221_write_curr()
439 if (channel > INA3221_CHANNEL3) in ina3221_write_curr()
440 resistance_uo = ina->summation_shunt_resistor; in ina3221_write_curr()
442 resistance_uo = input[channel].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()
462 * Shunt Voltage Sum register left-shifts 1 bit 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()
476 static int ina3221_write_enable(struct device *dev, int channel, bool enable) in ina3221_write_enable() argument
479 u16 config, mask = INA3221_CONFIG_CHx_EN(channel); in ina3221_write_enable()
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()
499 /* Enable or disable the channel */ 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()
516 dev_err(dev, "Failed to enable channel %d: error %d\n", in ina3221_write_enable()
517 channel, ret); in ina3221_write_enable()
518 pm_runtime_put_sync(ina->pm_dev); in ina3221_write_enable()
525 u32 attr, int channel, long *val) in ina3221_read() argument
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()
541 ret = ina3221_read_curr(dev, attr, channel, val); in ina3221_read()
544 ret = -EOPNOTSUPP; in ina3221_read()
548 mutex_unlock(&ina->lock); in ina3221_read()
554 u32 attr, int channel, long val) in ina3221_write() argument
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()
570 ret = ina3221_write_curr(dev, attr, channel, val); in ina3221_write()
573 ret = -EOPNOTSUPP; in ina3221_write()
577 mutex_unlock(&ina->lock); in ina3221_write()
583 u32 attr, int channel, const char **str) in ina3221_read_string() argument
586 int index = channel - 1; in ina3221_read_string()
588 if (channel == 7) in ina3221_read_string()
591 *str = ina->inputs[index].label; in ina3221_read_string()
598 u32 attr, int channel) in ina3221_is_visible() argument
614 if (channel == 0) in ina3221_is_visible()
619 if (channel - 1 <= INA3221_CHANNEL3) in ina3221_is_visible()
620 input = &ina->inputs[channel - 1]; in ina3221_is_visible()
621 else if (channel == 7) 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 */
671 /* 1-3: current channels*/
698 unsigned int channel = sd_attr->index; in ina3221_shunt_show() local
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() local
711 struct ina3221_input *input = &ina->inputs[channel]; in ina3221_shunt_store()
721 input->shunt_resistor = val; in ina3221_shunt_store()
723 /* Update summation_shunt_resistor for summation channel */ in ina3221_shunt_store()
724 ina->summation_shunt_resistor = ina3221_summation_shunt_resistor(ina); in ina3221_shunt_store()
778 input = &ina->inputs[val]; in ina3221_probe_child_from_dt()
780 /* Log the disconnected channel input */ 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()
790 if (!of_property_read_u32(child, "shunt-resistor-micro-ohms", &val)) { 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()
874 /* Initialize summation_shunt_resistor for summation channel control */ 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()
980 /* Initialize summation channel control */ in ina3221_resume()
981 if (ina->summation_shunt_resistor) { in ina3221_resume()
987 ret = regmap_update_bits(ina->regmap, INA3221_MASK_ENABLE, in ina3221_resume()
991 dev_err(dev, "Unable to control summation channel\n"); in ina3221_resume()