#define INA3221_CONFIG_MODE_SHUNT      BIT(0)
 #define INA3221_CONFIG_MODE_BUS                BIT(1)
 #define INA3221_CONFIG_MODE_CONTINUOUS BIT(2)
+#define INA3221_CONFIG_CHx_EN(x)       BIT(14 - (x))
 
 #define INA3221_RSHUNT_DEFAULT         10000
 
 };
 
 static const unsigned int register_channel[] = {
+       [INA3221_BUS1] = INA3221_CHANNEL1,
+       [INA3221_BUS2] = INA3221_CHANNEL2,
+       [INA3221_BUS3] = INA3221_CHANNEL3,
        [INA3221_SHUNT1] = INA3221_CHANNEL1,
        [INA3221_SHUNT2] = INA3221_CHANNEL2,
        [INA3221_SHUNT3] = INA3221_CHANNEL3,
        [INA3221_WARN3] = INA3221_CHANNEL3,
 };
 
+/**
+ * struct ina3221_input - channel input source specific information
+ * @label: label of channel input source
+ * @shunt_resistor: shunt resistor value of channel input source
+ * @disconnected: connection status of channel input source
+ */
+struct ina3221_input {
+       const char *label;
+       int shunt_resistor;
+       bool disconnected;
+};
+
 /**
  * struct ina3221_data - device specific information
  * @regmap: Register map of the device
  * @fields: Register fields of the device
- * @shunt_resistors: Array of resistor values per channel
+ * @inputs: Array of channel input source specific structures
  * @reg_config: Register value of INA3221_CONFIG
  */
 struct ina3221_data {
        struct regmap *regmap;
        struct regmap_field *fields[F_MAX_FIELDS];
-       int shunt_resistors[INA3221_NUM_CHANNELS];
+       struct ina3221_input inputs[INA3221_NUM_CHANNELS];
        u32 reg_config;
 };
 
+static inline bool ina3221_is_enabled(struct ina3221_data *ina, int channel)
+{
+       return ina->reg_config & INA3221_CONFIG_CHx_EN(channel);
+}
+
+static ssize_t ina3221_show_label(struct device *dev,
+                                 struct device_attribute *attr, char *buf)
+{
+       struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr);
+       struct ina3221_data *ina = dev_get_drvdata(dev);
+       unsigned int channel = sd_attr->index;
+       struct ina3221_input *input = &ina->inputs[channel];
+
+       return snprintf(buf, PAGE_SIZE, "%s\n", input->label);
+}
+
+static ssize_t ina3221_show_enable(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr);
+       struct ina3221_data *ina = dev_get_drvdata(dev);
+       unsigned int channel = sd_attr->index;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       ina3221_is_enabled(ina, channel));
+}
+
+static ssize_t ina3221_set_enable(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t count)
+{
+       struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr);
+       struct ina3221_data *ina = dev_get_drvdata(dev);
+       unsigned int channel = sd_attr->index;
+       u16 config, mask = INA3221_CONFIG_CHx_EN(channel);
+       bool enable;
+       int ret;
+
+       ret = kstrtobool(buf, &enable);
+       if (ret)
+               return ret;
+
+       config = enable ? mask : 0;
+
+       /* Enable or disable the channel */
+       ret = regmap_update_bits(ina->regmap, INA3221_CONFIG, mask, config);
+       if (ret)
+               return ret;
+
+       /* Cache the latest config register value */
+       ret = regmap_read(ina->regmap, INA3221_CONFIG, &ina->reg_config);
+       if (ret)
+               return ret;
+
+       return count;
+}
+
 static int ina3221_read_value(struct ina3221_data *ina, unsigned int reg,
                              int *val)
 {
        struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr);
        struct ina3221_data *ina = dev_get_drvdata(dev);
        unsigned int reg = sd_attr->index;
+       unsigned int channel = register_channel[reg];
        int val, voltage_mv, ret;
 
+       /* No data for read-only attribute if channel is disabled */
+       if (!attr->store && !ina3221_is_enabled(ina, channel))
+               return -ENODATA;
+
        ret = ina3221_read_value(ina, reg, &val);
        if (ret)
                return ret;
        struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr);
        struct ina3221_data *ina = dev_get_drvdata(dev);
        unsigned int reg = sd_attr->index;
+       unsigned int channel = register_channel[reg];
        int val, voltage_uv, ret;
 
+       /* No data for read-only attribute if channel is disabled */
+       if (!attr->store && !ina3221_is_enabled(ina, channel))
+               return -ENODATA;
+
        ret = ina3221_read_value(ina, reg, &val);
        if (ret)
                return ret;
        struct ina3221_data *ina = dev_get_drvdata(dev);
        unsigned int reg = sd_attr->index;
        unsigned int channel = register_channel[reg];
-       int resistance_uo = ina->shunt_resistors[channel];
+       struct ina3221_input *input = &ina->inputs[channel];
+       int resistance_uo = input->shunt_resistor;
        int val, current_ma, voltage_nv, ret;
 
+       /* No data for read-only attribute if channel is disabled */
+       if (!attr->store && !ina3221_is_enabled(ina, channel))
+               return -ENODATA;
+
        ret = ina3221_read_value(ina, reg, &val);
        if (ret)
                return ret;
        struct ina3221_data *ina = dev_get_drvdata(dev);
        unsigned int reg = sd_attr->index;
        unsigned int channel = register_channel[reg];
-       int resistance_uo = ina->shunt_resistors[channel];
+       struct ina3221_input *input = &ina->inputs[channel];
+       int resistance_uo = input->shunt_resistor;
        int val, current_ma, voltage_uv, ret;
 
        ret = kstrtoint(buf, 0, ¤t_ma);
        struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr);
        struct ina3221_data *ina = dev_get_drvdata(dev);
        unsigned int channel = sd_attr->index;
-       unsigned int resistance_uo;
-
-       resistance_uo = ina->shunt_resistors[channel];
+       struct ina3221_input *input = &ina->inputs[channel];
 
-       return snprintf(buf, PAGE_SIZE, "%d\n", resistance_uo);
+       return snprintf(buf, PAGE_SIZE, "%d\n", input->shunt_resistor);
 }
 
 static ssize_t ina3221_set_shunt(struct device *dev,
        struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr);
        struct ina3221_data *ina = dev_get_drvdata(dev);
        unsigned int channel = sd_attr->index;
+       struct ina3221_input *input = &ina->inputs[channel];
        int val;
        int ret;
 
 
        val = clamp_val(val, 1, INT_MAX);
 
-       ina->shunt_resistors[channel] = val;
+       input->shunt_resistor = val;
 
        return count;
 }
        return snprintf(buf, PAGE_SIZE, "%d\n", regval);
 }
 
+/* input channel label */
+static SENSOR_DEVICE_ATTR(in1_label, 0444,
+               ina3221_show_label, NULL, INA3221_CHANNEL1);
+static SENSOR_DEVICE_ATTR(in2_label, 0444,
+               ina3221_show_label, NULL, INA3221_CHANNEL2);
+static SENSOR_DEVICE_ATTR(in3_label, 0444,
+               ina3221_show_label, NULL, INA3221_CHANNEL3);
+
+/* voltage channel enable */
+static SENSOR_DEVICE_ATTR(in1_enable, 0644,
+               ina3221_show_enable, ina3221_set_enable, INA3221_CHANNEL1);
+static SENSOR_DEVICE_ATTR(in2_enable, 0644,
+               ina3221_show_enable, ina3221_set_enable, INA3221_CHANNEL2);
+static SENSOR_DEVICE_ATTR(in3_enable, 0644,
+               ina3221_show_enable, ina3221_set_enable, INA3221_CHANNEL3);
+
 /* bus voltage */
 static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO,
                ina3221_show_bus_voltage, NULL, INA3221_BUS1);
                ina3221_show_shunt_voltage, NULL, INA3221_SHUNT3);
 
 static struct attribute *ina3221_attrs[] = {
-       /* channel 1 */
+       /* channel 1 -- make sure label at first */
+       &sensor_dev_attr_in1_label.dev_attr.attr,
+       &sensor_dev_attr_in1_enable.dev_attr.attr,
        &sensor_dev_attr_in1_input.dev_attr.attr,
        &sensor_dev_attr_curr1_input.dev_attr.attr,
        &sensor_dev_attr_shunt1_resistor.dev_attr.attr,
        &sensor_dev_attr_curr1_max_alarm.dev_attr.attr,
        &sensor_dev_attr_in4_input.dev_attr.attr,
 
-       /* channel 2 */
+       /* channel 2 -- make sure label at first */
+       &sensor_dev_attr_in2_label.dev_attr.attr,
+       &sensor_dev_attr_in2_enable.dev_attr.attr,
        &sensor_dev_attr_in2_input.dev_attr.attr,
        &sensor_dev_attr_curr2_input.dev_attr.attr,
        &sensor_dev_attr_shunt2_resistor.dev_attr.attr,
        &sensor_dev_attr_curr2_max_alarm.dev_attr.attr,
        &sensor_dev_attr_in5_input.dev_attr.attr,
 
-       /* channel 3 */
+       /* channel 3 -- make sure label at first */
+       &sensor_dev_attr_in3_label.dev_attr.attr,
+       &sensor_dev_attr_in3_enable.dev_attr.attr,
        &sensor_dev_attr_in3_input.dev_attr.attr,
        &sensor_dev_attr_curr3_input.dev_attr.attr,
        &sensor_dev_attr_shunt3_resistor.dev_attr.attr,
 
        NULL,
 };
-ATTRIBUTE_GROUPS(ina3221);
+
+static umode_t ina3221_attr_is_visible(struct kobject *kobj,
+                                      struct attribute *attr, int n)
+{
+       const int max_attrs = ARRAY_SIZE(ina3221_attrs) - 1;
+       const int num_attrs = max_attrs / INA3221_NUM_CHANNELS;
+       struct device *dev = kobj_to_dev(kobj);
+       struct ina3221_data *ina = dev_get_drvdata(dev);
+       enum ina3221_channels channel = n / num_attrs;
+       struct ina3221_input *input = &ina->inputs[channel];
+       int index = n % num_attrs;
+
+       /* Hide label node if label is not provided */
+       if (index == 0 && !input->label)
+               return 0;
+
+       return attr->mode;
+}
+
+static const struct attribute_group ina3221_group = {
+       .is_visible = ina3221_attr_is_visible,
+       .attrs = ina3221_attrs,
+};
+__ATTRIBUTE_GROUPS(ina3221);
 
 static const struct regmap_range ina3221_yes_ranges[] = {
        regmap_reg_range(INA3221_CONFIG, INA3221_BUS3),
        .volatile_table = &ina3221_volatile_table,
 };
 
+static int ina3221_probe_child_from_dt(struct device *dev,
+                                      struct device_node *child,
+                                      struct ina3221_data *ina)
+{
+       struct ina3221_input *input;
+       u32 val;
+       int ret;
+
+       ret = of_property_read_u32(child, "reg", &val);
+       if (ret) {
+               dev_err(dev, "missing reg property of %s\n", child->name);
+               return ret;
+       } else if (val > INA3221_CHANNEL3) {
+               dev_err(dev, "invalid reg %d of %s\n", val, child->name);
+               return ret;
+       }
+
+       input = &ina->inputs[val];
+
+       /* Log the disconnected channel input */
+       if (!of_device_is_available(child)) {
+               input->disconnected = true;
+               return 0;
+       }
+
+       /* Save the connected input label if available */
+       of_property_read_string(child, "label", &input->label);
+
+       /* Overwrite default shunt resistor value optionally */
+       if (!of_property_read_u32(child, "shunt-resistor-micro-ohms", &val))
+               input->shunt_resistor = val;
+
+       return 0;
+}
+
+static int ina3221_probe_from_dt(struct device *dev, struct ina3221_data *ina)
+{
+       const struct device_node *np = dev->of_node;
+       struct device_node *child;
+       int ret;
+
+       /* Compatible with non-DT platforms */
+       if (!np)
+               return 0;
+
+       for_each_child_of_node(np, child) {
+               ret = ina3221_probe_child_from_dt(dev, child, ina);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
 static int ina3221_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
 {
        }
 
        for (i = 0; i < INA3221_NUM_CHANNELS; i++)
-               ina->shunt_resistors[i] = INA3221_RSHUNT_DEFAULT;
+               ina->inputs[i].shunt_resistor = INA3221_RSHUNT_DEFAULT;
+
+       ret = ina3221_probe_from_dt(dev, ina);
+       if (ret) {
+               dev_err(dev, "Unable to probe from device tree\n");
+               return ret;
+       }
 
        ret = regmap_field_write(ina->fields[F_RST], true);
        if (ret) {
                return ret;
        }
 
+       /* Sync config register after reset */
+       ret = regmap_read(ina->regmap, INA3221_CONFIG, &ina->reg_config);
+       if (ret)
+               return ret;
+
+       /* Disable channels if their inputs are disconnected */
+       for (i = 0; i < INA3221_NUM_CHANNELS; i++) {
+               if (ina->inputs[i].disconnected)
+                       ina->reg_config &= ~INA3221_CONFIG_CHx_EN(i);
+       }
+       ret = regmap_write(ina->regmap, INA3221_CONFIG, ina->reg_config);
+       if (ret)
+               return ret;
+
        dev_set_drvdata(dev, ina);
 
        hwmon_dev = devm_hwmon_device_register_with_groups(dev,