Skip to content

Commit 7b64906

Browse files
Ninad Malwadegroeck
authored andcommitted
hwmon: (ina3221) Add support for channel summation disable
The INA3221 allows the Critical alert pin to be controlled by the summation control function. This function adds the single shunt-voltage conversions for the desired channels in order to compare the combined sum to the programmed limit. The Shunt-Voltage Sum Limit register contains the programmed value that is compared to the value in the Shunt-Voltage Sum register in order to determine if the total summed limit is exceeded. If the shunt-voltage sum limit value is exceeded, the Critical alert pin pulls low. For the summation limit to have a meaningful value, we have to use the same shunt-resistor value on all included channels. Unless equal shunt-resistor values are used for each channel, the summation control function cannot be used and it is not enabled by the driver. To address this, add support to disable the summation of specific channels via device tree property "ti,summation-disable". The channel which has this property would be excluded from the calculation of summation control function. For example, summation control function calculates Shunt-Voltage Sum as: - input_shunt_voltage_summation = input_shunt_voltage_channel1 + input_shunt_voltage_channel2 + input_shunt_voltage_channel3 If we want the summation to only use channel1 and channel3, we can add 'ti,summation-disable' property in device tree node for channel2. Then the calculation will skip channel2. - input_shunt_voltage_summation = input_shunt_voltage_channel1 + input_shunt_voltage_channel3 Note that we only want the channel to be skipped for summation control function rather than completely disabled. Therefore, even if we add the property 'ti,summation-disable', the channel is still enabled and functional. Finally, create debugfs entries that display if summation is disabled for each of the channels. Signed-off-by: Rajkumar Kasirajan <[email protected]> Signed-off-by: Ninad Malwade <[email protected]> Co-developed-by: Jon Hunter <[email protected]> Signed-off-by: Jon Hunter <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Guenter Roeck <[email protected]>
1 parent 13ab5fd commit 7b64906

File tree

1 file changed

+30
-3
lines changed

1 file changed

+30
-3
lines changed

drivers/hwmon/ina3221.c

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* Andrew F. Davis <[email protected]>
77
*/
88

9+
#include <linux/debugfs.h>
910
#include <linux/hwmon.h>
1011
#include <linux/hwmon-sysfs.h>
1112
#include <linux/i2c.h>
@@ -99,11 +100,13 @@ enum ina3221_channels {
99100
* @label: label of channel input source
100101
* @shunt_resistor: shunt resistor value of channel input source
101102
* @disconnected: connection status of channel input source
103+
* @summation_disable: channel summation status of input source
102104
*/
103105
struct ina3221_input {
104106
const char *label;
105107
int shunt_resistor;
106108
bool disconnected;
109+
bool summation_disable;
107110
};
108111

109112
/**
@@ -113,8 +116,10 @@ struct ina3221_input {
113116
* @fields: Register fields of the device
114117
* @inputs: Array of channel input source specific structures
115118
* @lock: mutex lock to serialize sysfs attribute accesses
119+
* @debugfs: Pointer to debugfs entry for device
116120
* @reg_config: Register value of INA3221_CONFIG
117121
* @summation_shunt_resistor: equivalent shunt resistor value for summation
122+
* @summation_channel_control: Value written to SCC field in INA3221_MASK_ENABLE
118123
* @single_shot: running in single-shot operating mode
119124
*/
120125
struct ina3221_data {
@@ -123,8 +128,10 @@ struct ina3221_data {
123128
struct regmap_field *fields[F_MAX_FIELDS];
124129
struct ina3221_input inputs[INA3221_NUM_CHANNELS];
125130
struct mutex lock;
131+
struct dentry *debugfs;
126132
u32 reg_config;
127133
int summation_shunt_resistor;
134+
u32 summation_channel_control;
128135

129136
bool single_shot;
130137
};
@@ -154,7 +161,8 @@ static inline int ina3221_summation_shunt_resistor(struct ina3221_data *ina)
154161
int i, shunt_resistor = 0;
155162

156163
for (i = 0; i < INA3221_NUM_CHANNELS; i++) {
157-
if (input[i].disconnected || !input[i].shunt_resistor)
164+
if (input[i].disconnected || !input[i].shunt_resistor ||
165+
input[i].summation_disable)
158166
continue;
159167
if (!shunt_resistor) {
160168
/* Found the reference shunt resistor value */
@@ -786,6 +794,9 @@ static int ina3221_probe_child_from_dt(struct device *dev,
786794
/* Save the connected input label if available */
787795
of_property_read_string(child, "label", &input->label);
788796

797+
/* summation channel control */
798+
input->summation_disable = of_property_read_bool(child, "ti,summation-disable");
799+
789800
/* Overwrite default shunt resistor value optionally */
790801
if (!of_property_read_u32(child, "shunt-resistor-micro-ohms", &val)) {
791802
if (val < 1 || val > INT_MAX) {
@@ -827,6 +838,7 @@ static int ina3221_probe(struct i2c_client *client)
827838
struct device *dev = &client->dev;
828839
struct ina3221_data *ina;
829840
struct device *hwmon_dev;
841+
char name[32];
830842
int i, ret;
831843

832844
ina = devm_kzalloc(dev, sizeof(*ina), GFP_KERNEL);
@@ -873,6 +885,10 @@ static int ina3221_probe(struct i2c_client *client)
873885

874886
/* Initialize summation_shunt_resistor for summation channel control */
875887
ina->summation_shunt_resistor = ina3221_summation_shunt_resistor(ina);
888+
for (i = 0; i < INA3221_NUM_CHANNELS; i++) {
889+
if (!ina->inputs[i].summation_disable)
890+
ina->summation_channel_control |= BIT(14 - i);
891+
}
876892

877893
ina->pm_dev = dev;
878894
mutex_init(&ina->lock);
@@ -900,6 +916,15 @@ static int ina3221_probe(struct i2c_client *client)
900916
goto fail;
901917
}
902918

919+
scnprintf(name, sizeof(name), "%s-%s", INA3221_DRIVER_NAME, dev_name(dev));
920+
ina->debugfs = debugfs_create_dir(name, NULL);
921+
922+
for (i = 0; i < INA3221_NUM_CHANNELS; i++) {
923+
scnprintf(name, sizeof(name), "in%d_summation_disable", i);
924+
debugfs_create_bool(name, 0400, ina->debugfs,
925+
&ina->inputs[i].summation_disable);
926+
}
927+
903928
return 0;
904929

905930
fail:
@@ -918,6 +943,8 @@ static void ina3221_remove(struct i2c_client *client)
918943
struct ina3221_data *ina = dev_get_drvdata(&client->dev);
919944
int i;
920945

946+
debugfs_remove_recursive(ina->debugfs);
947+
921948
pm_runtime_disable(ina->pm_dev);
922949
pm_runtime_set_suspended(ina->pm_dev);
923950

@@ -978,13 +1005,13 @@ static int ina3221_resume(struct device *dev)
9781005
/* Initialize summation channel control */
9791006
if (ina->summation_shunt_resistor) {
9801007
/*
981-
* Take all three channels into summation by default
1008+
* Sum only channels that are not disabled for summation.
9821009
* Shunt measurements of disconnected channels should
9831010
* be 0, so it does not matter for summation.
9841011
*/
9851012
ret = regmap_update_bits(ina->regmap, INA3221_MASK_ENABLE,
9861013
INA3221_MASK_ENABLE_SCC_MASK,
987-
INA3221_MASK_ENABLE_SCC_MASK);
1014+
ina->summation_channel_control);
9881015
if (ret) {
9891016
dev_err(dev, "Unable to control summation channel\n");
9901017
return ret;

0 commit comments

Comments
 (0)