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/
11 #include <linux/hwmon-sysfs.h>
54 #define INA3221_CONFIG_CHx_EN(x) BIT(14 - (x))
71 /* Alert Flags: SF is the summation-alert flag */
99 * struct ina3221_input - channel input source specific information
100 * @label: label of channel input source
101 * @shunt_resistor: shunt resistor value of channel input source
102 * @disconnected: connection status of channel input source
103 * @summation_disable: channel summation status of input source
113 * struct ina3221_data - device specific information
117 * @inputs: Array of channel input source specific structures
123 * @single_shot: running in single-shot operating mode
139 static inline bool ina3221_is_enabled(struct ina3221_data *ina, int channel) in ina3221_is_enabled() argument
141 /* Summation channel checks shunt resistor values */ in ina3221_is_enabled()
142 if (channel > INA3221_CHANNEL3) in ina3221_is_enabled()
143 return ina->summation_shunt_resistor != 0; in ina3221_is_enabled()
145 return pm_runtime_active(ina->pm_dev) && in ina3221_is_enabled()
146 (ina->reg_config & INA3221_CONFIG_CHx_EN(channel)); in ina3221_is_enabled()
152 * There is a condition to calculate current summation -- all the shunt
160 struct ina3221_input *input = ina->inputs; in ina3221_summation_shunt_resistor()
218 wait = ina3221_reg_to_interval_us(ina->reg_config); in ina3221_wait_for_data()
221 return regmap_field_read_poll_timeout(ina->fields[F_CVRF], in ina3221_wait_for_data()
231 ret = regmap_read(ina->regmap, reg, ®val); in ina3221_read_value()
236 * Shunt Voltage Sum register has 14-bit value with 1-bit shift in ina3221_read_value()
237 * Other Shunt Voltage registers have 12 bits with 3-bit shift in ina3221_read_value()
264 regval = INA3221_CONFIG_AVG(ina->reg_config); in ina3221_read_chip()
269 *val = ina3221_reg_to_interval_us(ina->reg_config); in ina3221_read_chip()
273 return -EOPNOTSUPP; in ina3221_read_chip()
277 static int ina3221_read_in(struct device *dev, u32 attr, int channel, long *val) in ina3221_read_in() argument
279 const bool is_shunt = channel > INA3221_CHANNEL3; in ina3221_read_in()
281 u8 reg = ina3221_in_reg[channel]; in ina3221_read_in()
285 * Translate shunt channel index to sensor channel index except in ina3221_read_in()
286 * the 7th channel (6 since being 0-aligned) is for summation. in ina3221_read_in()
288 if (channel != 6) in ina3221_read_in()
289 channel %= INA3221_NUM_CHANNELS; in ina3221_read_in()
293 if (!ina3221_is_enabled(ina, channel)) in ina3221_read_in()
294 return -ENODATA; in ina3221_read_in()
296 /* Write CONFIG register to trigger a single-shot measurement */ in ina3221_read_in()
297 if (ina->single_shot) { in ina3221_read_in()
298 regmap_write(ina->regmap, INA3221_CONFIG, in ina3221_read_in()
299 ina->reg_config); in ina3221_read_in()
317 *val = ina3221_is_enabled(ina, channel); in ina3221_read_in()
320 return -EOPNOTSUPP; in ina3221_read_in()
335 int channel, long *val) in ina3221_read_curr() argument
338 struct ina3221_input *input = ina->inputs; in ina3221_read_curr()
339 u8 reg = ina3221_curr_reg[attr][channel]; in ina3221_read_curr()
343 if (channel > INA3221_CHANNEL3) in ina3221_read_curr()
344 resistance_uo = ina->summation_shunt_resistor; in ina3221_read_curr()
346 resistance_uo = input[channel].shunt_resistor; in ina3221_read_curr()
350 if (!ina3221_is_enabled(ina, channel)) in ina3221_read_curr()
351 return -ENODATA; in ina3221_read_curr()
353 /* Write CONFIG register to trigger a single-shot measurement */ in ina3221_read_curr()
354 if (ina->single_shot) { in ina3221_read_curr()
355 regmap_write(ina->regmap, INA3221_CONFIG, in ina3221_read_curr()
356 ina->reg_config); in ina3221_read_curr()
367 return -ENODATA; in ina3221_read_curr()
380 /* No actual register read if channel is disabled */ in ina3221_read_curr()
381 if (!ina3221_is_enabled(ina, channel)) { in ina3221_read_curr()
386 ret = regmap_field_read(ina->fields[reg], ®val); in ina3221_read_curr()
392 return -EOPNOTSUPP; in ina3221_read_curr()
407 tmp = (ina->reg_config & ~INA3221_CONFIG_AVG_MASK) | in ina3221_write_chip()
409 ret = regmap_write(ina->regmap, INA3221_CONFIG, tmp); in ina3221_write_chip()
414 ina->reg_config = tmp; in ina3221_write_chip()
417 tmp = ina3221_interval_ms_to_conv_time(ina->reg_config, val); in ina3221_write_chip()
423 tmp = (ina->reg_config & ~tmp) | in ina3221_write_chip()
426 ret = regmap_write(ina->regmap, INA3221_CONFIG, tmp); in ina3221_write_chip()
431 ina->reg_config = tmp; in ina3221_write_chip()
434 return -EOPNOTSUPP; in ina3221_write_chip()
439 int channel, long val) in ina3221_write_curr() argument
442 struct ina3221_input *input = ina->inputs; in ina3221_write_curr()
443 u8 reg = ina3221_curr_reg[attr][channel]; in ina3221_write_curr()
447 if (channel > INA3221_CHANNEL3) in ina3221_write_curr()
448 resistance_uo = ina->summation_shunt_resistor; in ina3221_write_curr()
450 resistance_uo = input[channel].shunt_resistor; in ina3221_write_curr()
453 return -EOPNOTSUPP; in ina3221_write_curr()
463 voltage_uv = clamp_val(voltage_uv, -163800, 163800); in ina3221_write_curr()
470 * Shunt Voltage Sum register left-shifts 1 bit in ina3221_write_curr()
474 * SHUNT[1-3]: (1 / 40uV) << 3 = 1 / 5uV in ina3221_write_curr()
481 return regmap_write(ina->regmap, reg, regval); in ina3221_write_curr()
484 static int ina3221_write_enable(struct device *dev, int channel, bool enable) in ina3221_write_enable() argument
487 u16 config, mask = INA3221_CONFIG_CHx_EN(channel); in ina3221_write_enable()
488 u16 config_old = ina->reg_config & mask; in ina3221_write_enable()
500 ret = pm_runtime_resume_and_get(ina->pm_dev); in ina3221_write_enable()
507 /* Enable or disable the channel */ in ina3221_write_enable()
508 tmp = (ina->reg_config & ~mask) | (config & mask); in ina3221_write_enable()
509 ret = regmap_write(ina->regmap, INA3221_CONFIG, tmp); in ina3221_write_enable()
514 ina->reg_config = tmp; in ina3221_write_enable()
518 pm_runtime_put_sync(ina->pm_dev); in ina3221_write_enable()
524 dev_err(dev, "Failed to enable channel %d: error %d\n", in ina3221_write_enable()
525 channel, ret); in ina3221_write_enable()
526 pm_runtime_put_sync(ina->pm_dev); in ina3221_write_enable()
533 u32 attr, int channel, long *val) in ina3221_read() argument
538 mutex_lock(&ina->lock); in ina3221_read()
545 /* 0-align channel ID */ in ina3221_read()
546 ret = ina3221_read_in(dev, attr, channel - 1, val); in ina3221_read()
549 ret = ina3221_read_curr(dev, attr, channel, val); in ina3221_read()
552 ret = -EOPNOTSUPP; in ina3221_read()
556 mutex_unlock(&ina->lock); in ina3221_read()
562 u32 attr, int channel, long val) in ina3221_write() argument
567 mutex_lock(&ina->lock); in ina3221_write()
574 /* 0-align channel ID */ in ina3221_write()
575 ret = ina3221_write_enable(dev, channel - 1, val); in ina3221_write()
578 ret = ina3221_write_curr(dev, attr, channel, val); in ina3221_write()
581 ret = -EOPNOTSUPP; in ina3221_write()
585 mutex_unlock(&ina->lock); in ina3221_write()
591 u32 attr, int channel, const char **str) in ina3221_read_string() argument
594 int index = channel - 1; in ina3221_read_string()
596 if (channel == 7) in ina3221_read_string()
599 *str = ina->inputs[index].label; in ina3221_read_string()
606 u32 attr, int channel) in ina3221_is_visible() argument
622 if (channel == 0) in ina3221_is_visible()
627 if (channel - 1 <= INA3221_CHANNEL3) in ina3221_is_visible()
628 input = &ina->inputs[channel - 1]; in ina3221_is_visible()
629 else if (channel == 7) in ina3221_is_visible()
632 return (input && input->label) ? 0444 : 0; in ina3221_is_visible()
668 /* 1-3: input voltage Channels */
672 /* 4-6: shunt voltage Channels */
679 /* 1-3: current channels*/
706 unsigned int channel = sd_attr->index; in ina3221_shunt_show() local
707 struct ina3221_input *input = &ina->inputs[channel]; in ina3221_shunt_show()
709 return sysfs_emit(buf, "%d\n", input->shunt_resistor); in ina3221_shunt_show()
718 unsigned int channel = sd_attr->index; in ina3221_shunt_store() local
719 struct ina3221_input *input = &ina->inputs[channel]; in ina3221_shunt_store()
729 input->shunt_resistor = val; in ina3221_shunt_store()
731 /* Update summation_shunt_resistor for summation channel */ in ina3221_shunt_store()
732 ina->summation_shunt_resistor = ina3221_summation_shunt_resistor(ina); in ina3221_shunt_store()
783 return -EINVAL; in ina3221_probe_child_from_dt()
786 input = &ina->inputs[val]; in ina3221_probe_child_from_dt()
788 /* Log the disconnected channel input */ in ina3221_probe_child_from_dt()
790 input->disconnected = true; in ina3221_probe_child_from_dt()
795 of_property_read_string(child, "label", &input->label); in ina3221_probe_child_from_dt()
797 /* summation channel control */ in ina3221_probe_child_from_dt()
798 input->summation_disable = of_property_read_bool(child, "ti,summation-disable"); in ina3221_probe_child_from_dt()
801 if (!of_property_read_u32(child, "shunt-resistor-micro-ohms", &val)) { in ina3221_probe_child_from_dt()
805 return -EINVAL; in ina3221_probe_child_from_dt()
807 input->shunt_resistor = val; in ina3221_probe_child_from_dt()
815 const struct device_node *np = dev->of_node; in ina3221_probe_from_dt()
818 /* Compatible with non-DT platforms */ in ina3221_probe_from_dt()
822 ina->single_shot = of_property_read_bool(np, "ti,single-shot"); in ina3221_probe_from_dt()
835 struct device *dev = &client->dev; in ina3221_probe()
843 return -ENOMEM; in ina3221_probe()
845 ina->regmap = devm_regmap_init_i2c(client, &ina3221_regmap_config); in ina3221_probe()
846 if (IS_ERR(ina->regmap)) { in ina3221_probe()
848 return PTR_ERR(ina->regmap); in ina3221_probe()
852 ina->fields[i] = devm_regmap_field_alloc(dev, in ina3221_probe()
853 ina->regmap, in ina3221_probe()
855 if (IS_ERR(ina->fields[i])) { in ina3221_probe()
857 return PTR_ERR(ina->fields[i]); in ina3221_probe()
862 ina->inputs[i].shunt_resistor = INA3221_RSHUNT_DEFAULT; in ina3221_probe()
871 ina->reg_config = INA3221_CONFIG_DEFAULT; in ina3221_probe()
873 /* Clear continuous bit to use single-shot mode */ in ina3221_probe()
874 if (ina->single_shot) in ina3221_probe()
875 ina->reg_config &= ~INA3221_CONFIG_MODE_CONTINUOUS; in ina3221_probe()
879 if (ina->inputs[i].disconnected) in ina3221_probe()
880 ina->reg_config &= ~INA3221_CONFIG_CHx_EN(i); in ina3221_probe()
883 /* Initialize summation_shunt_resistor for summation channel control */ in ina3221_probe()
884 ina->summation_shunt_resistor = ina3221_summation_shunt_resistor(ina); in ina3221_probe()
886 if (!ina->inputs[i].summation_disable) in ina3221_probe()
887 ina->summation_channel_control |= BIT(14 - i); in ina3221_probe()
890 ina->pm_dev = dev; in ina3221_probe()
891 mutex_init(&ina->lock); in ina3221_probe()
894 /* Enable PM runtime -- status is suspended by default */ in ina3221_probe()
895 pm_runtime_enable(ina->pm_dev); in ina3221_probe()
899 if (ina->inputs[i].disconnected) in ina3221_probe()
902 ret = pm_runtime_get_sync(ina->pm_dev); in ina3221_probe()
907 hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, ina, in ina3221_probe()
916 scnprintf(name, sizeof(name), "%s-%s", INA3221_DRIVER_NAME, dev_name(dev)); in ina3221_probe()
917 ina->debugfs = debugfs_create_dir(name, NULL); in ina3221_probe()
921 debugfs_create_bool(name, 0400, ina->debugfs, in ina3221_probe()
922 &ina->inputs[i].summation_disable); in ina3221_probe()
928 pm_runtime_disable(ina->pm_dev); in ina3221_probe()
929 pm_runtime_set_suspended(ina->pm_dev); in ina3221_probe()
932 pm_runtime_put_noidle(ina->pm_dev); in ina3221_probe()
933 mutex_destroy(&ina->lock); in ina3221_probe()
940 struct ina3221_data *ina = dev_get_drvdata(&client->dev); in ina3221_remove()
943 debugfs_remove_recursive(ina->debugfs); in ina3221_remove()
945 pm_runtime_disable(ina->pm_dev); in ina3221_remove()
946 pm_runtime_set_suspended(ina->pm_dev); in ina3221_remove()
950 pm_runtime_put_noidle(ina->pm_dev); in ina3221_remove()
952 mutex_destroy(&ina->lock); in ina3221_remove()
960 /* Save config register value and enable cache-only */ in ina3221_suspend()
961 ret = regmap_read(ina->regmap, INA3221_CONFIG, &ina->reg_config); in ina3221_suspend()
965 /* Set to power-down mode for power saving */ in ina3221_suspend()
966 ret = regmap_update_bits(ina->regmap, INA3221_CONFIG, in ina3221_suspend()
972 regcache_cache_only(ina->regmap, true); in ina3221_suspend()
973 regcache_mark_dirty(ina->regmap); in ina3221_suspend()
983 regcache_cache_only(ina->regmap, false); in ina3221_resume()
986 ret = regmap_field_write(ina->fields[F_RST], true); in ina3221_resume()
993 ret = regcache_sync(ina->regmap); in ina3221_resume()
998 ret = regmap_write(ina->regmap, INA3221_CONFIG, ina->reg_config); in ina3221_resume()
1002 /* Initialize summation channel control */ in ina3221_resume()
1003 if (ina->summation_shunt_resistor) { in ina3221_resume()
1009 ret = regmap_update_bits(ina->regmap, INA3221_MASK_ENABLE, in ina3221_resume()
1011 ina->summation_channel_control); in ina3221_resume()
1013 dev_err(dev, "Unable to control summation channel\n"); in ina3221_resume()