#define ADM1075_VAUX_OV_WARN BIT(7)
#define ADM1075_VAUX_UV_WARN BIT(6)
-#define ADM1275_PWR_AVG_MASK GENMASK(13, 11)
-#define ADM1275_VI_AVG_MASK GENMASK(10, 8)
-#define ADM1275_SAMPLES_AVG_MAX 128
+#define ADM1275_VI_AVG_SHIFT 0
+#define ADM1275_VI_AVG_MASK GENMASK(ADM1275_VI_AVG_SHIFT + 2, \
+ ADM1275_VI_AVG_SHIFT)
+#define ADM1275_SAMPLES_AVG_MAX 128
+
+#define ADM1278_PWR_AVG_SHIFT 11
+#define ADM1278_PWR_AVG_MASK GENMASK(ADM1278_PWR_AVG_SHIFT + 2, \
+ ADM1278_PWR_AVG_SHIFT)
+#define ADM1278_VI_AVG_SHIFT 8
+#define ADM1278_VI_AVG_MASK GENMASK(ADM1278_VI_AVG_SHIFT + 2, \
+ ADM1278_VI_AVG_SHIFT)
struct adm1275_data {
int id;
bool have_pin_min;
bool have_pin_max;
bool have_temp_max;
+ bool have_power_sampling;
struct pmbus_driver_info info;
};
[18] = { 7658, 0, -3 }, /* power, 21V, irange200 */
};
-static inline int adm1275_read_pmon_config(struct i2c_client *client, u16 mask)
+static int adm1275_read_pmon_config(const struct adm1275_data *data,
+ struct i2c_client *client, bool is_power)
{
- int ret;
-
- ret = i2c_smbus_read_word_data(client, ADM1275_PMON_CONFIG);
+ int shift, ret;
+ u16 mask;
+
+ /*
+ * The PMON configuration register is a 16-bit register only on chips
+ * supporting power average sampling. On other chips it is an 8-bit
+ * register.
+ */
+ if (data->have_power_sampling) {
+ ret = i2c_smbus_read_word_data(client, ADM1275_PMON_CONFIG);
+ mask = is_power ? ADM1278_PWR_AVG_MASK : ADM1278_VI_AVG_MASK;
+ shift = is_power ? ADM1278_PWR_AVG_SHIFT : ADM1278_VI_AVG_SHIFT;
+ } else {
+ ret = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG);
+ mask = ADM1275_VI_AVG_MASK;
+ shift = ADM1275_VI_AVG_SHIFT;
+ }
if (ret < 0)
return ret;
- return FIELD_GET(mask, (u16)ret);
+ return (ret & mask) >> shift;
}
-static inline int adm1275_write_pmon_config(struct i2c_client *client, u16 mask,
- u16 word)
+static int adm1275_write_pmon_config(const struct adm1275_data *data,
+ struct i2c_client *client,
+ bool is_power, u16 word)
{
- int ret;
-
- ret = i2c_smbus_read_word_data(client, ADM1275_PMON_CONFIG);
+ int shift, ret;
+ u16 mask;
+
+ if (data->have_power_sampling) {
+ ret = i2c_smbus_read_word_data(client, ADM1275_PMON_CONFIG);
+ mask = is_power ? ADM1278_PWR_AVG_MASK : ADM1278_VI_AVG_MASK;
+ shift = is_power ? ADM1278_PWR_AVG_SHIFT : ADM1278_VI_AVG_SHIFT;
+ } else {
+ ret = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG);
+ mask = ADM1275_VI_AVG_MASK;
+ shift = ADM1275_VI_AVG_SHIFT;
+ }
if (ret < 0)
return ret;
- word = FIELD_PREP(mask, word) | (ret & ~mask);
- ret = i2c_smbus_write_word_data(client, ADM1275_PMON_CONFIG, word);
+ word = (ret & ~mask) | ((word << shift) & mask);
+ if (data->have_power_sampling)
+ ret = i2c_smbus_write_word_data(client, ADM1275_PMON_CONFIG,
+ word);
+ else
+ ret = i2c_smbus_write_byte_data(client, ADM1275_PMON_CONFIG,
+ word);
return ret;
}
return -ENXIO;
break;
case PMBUS_VIRT_POWER_SAMPLES:
- ret = adm1275_read_pmon_config(client, ADM1275_PWR_AVG_MASK);
+ if (!data->have_power_sampling)
+ return -ENXIO;
+ ret = adm1275_read_pmon_config(data, client, true);
if (ret < 0)
break;
ret = BIT(ret);
break;
case PMBUS_VIRT_IN_SAMPLES:
case PMBUS_VIRT_CURR_SAMPLES:
- ret = adm1275_read_pmon_config(client, ADM1275_VI_AVG_MASK);
+ ret = adm1275_read_pmon_config(data, client, false);
if (ret < 0)
break;
ret = BIT(ret);
ret = pmbus_write_word_data(client, 0, ADM1278_PEAK_TEMP, 0);
break;
case PMBUS_VIRT_POWER_SAMPLES:
+ if (!data->have_power_sampling)
+ return -ENXIO;
word = clamp_val(word, 1, ADM1275_SAMPLES_AVG_MAX);
- ret = adm1275_write_pmon_config(client, ADM1275_PWR_AVG_MASK,
+ ret = adm1275_write_pmon_config(data, client, true,
ilog2(word));
break;
case PMBUS_VIRT_IN_SAMPLES:
case PMBUS_VIRT_CURR_SAMPLES:
word = clamp_val(word, 1, ADM1275_SAMPLES_AVG_MAX);
- ret = adm1275_write_pmon_config(client, ADM1275_VI_AVG_MASK,
+ ret = adm1275_write_pmon_config(data, client, false,
ilog2(word));
break;
default:
data->have_vout = true;
data->have_pin_max = true;
data->have_temp_max = true;
+ data->have_power_sampling = true;
coefficients = adm1272_coefficients;
vindex = (config & ADM1275_VRANGE) ? 1 : 0;
data->have_vout = true;
data->have_pin_max = true;
data->have_temp_max = true;
+ data->have_power_sampling = true;
coefficients = adm1278_coefficients;
vindex = 0;
data->have_pin_min = true;
data->have_pin_max = true;
data->have_mfr_vaux_status = true;
+ data->have_power_sampling = true;
coefficients = adm1293_coefficients;