=====================
Supported chips:
+ * Analog Devices ADM1075
+ Prefix: 'adm1075'
+ Addresses scanned: -
+ Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1075.pdf
* Analog Devices ADM1275
Prefix: 'adm1275'
Addresses scanned: -
Description
-----------
-This driver supports hardware montoring for Analog Devices ADM1275 and ADM1276
-Hot-Swap Controller and Digital Power Monitor.
+This driver supports hardware montoring for Analog Devices ADM1075, ADM1275,
+and ADM1276 Hot-Swap Controller and Digital Power Monitor.
-ADM1275 and ADM1276 are hot-swap controllers that allow a circuit board to be
-removed from or inserted into a live backplane. They also feature current and
-voltage readback via an integrated 12-bit analog-to-digital converter (ADC),
-accessed using a PMBus interface.
+ADM1075, ADM1275, and ADM1276 are hot-swap controllers that allow a circuit
+board to be removed from or inserted into a live backplane. They also feature
+current and voltage readback via an integrated 12-bit analog-to-digital
+converter (ADC), accessed using a PMBus interface.
The driver is a client driver to the core PMBus driver. Please see
Documentation/hwmon/pmbus for details on PMBus client drivers.
devices explicitly. Please see Documentation/i2c/instantiating-devices for
details.
+The ADM1075, unlike many other PMBus devices, does not support internal voltage
+or current scaling. Reported voltages, currents, and power are raw measurements,
+and will typically have to be scaled.
+
Platform data support
---------------------
attributes are write-only, all other attributes are read-only.
in1_label "vin1" or "vout1" depending on chip variant and
- configuration.
+ configuration. On ADM1075, vout1 reports the voltage on
+ the VAUX pin.
in1_input Measured voltage.
in1_min Minumum Voltage.
in1_max Maximum voltage.
curr1_crit_alarm Critical current high alarm.
curr1_highest Historical maximum current.
curr1_reset_history Write any value to reset history.
+
+power1_label "pin1"
+power1_input Input power.
+power1_reset_history Write any value to reset history.
+
+ Power attributes are supported on ADM1075 and ADM1276
+ only.
#include <linux/i2c.h>
#include "pmbus.h"
-enum chips { adm1275, adm1276 };
+enum chips { adm1075, adm1275, adm1276 };
#define ADM1275_PEAK_IOUT 0xd0
#define ADM1275_PEAK_VIN 0xd1
#define ADM1275_VIN_VOUT_SELECT (1 << 6)
#define ADM1275_VRANGE (1 << 5)
+#define ADM1075_IRANGE_50 (1 << 4)
+#define ADM1075_IRANGE_25 (1 << 3)
+#define ADM1075_IRANGE_MASK ((1 << 3) | (1 << 4))
#define ADM1275_IOUT_WARN2_LIMIT 0xd7
#define ADM1275_DEVICE_CONFIG 0xd8
#define ADM1275_MFR_STATUS_IOUT_WARN2 (1 << 0)
+#define ADM1075_READ_VAUX 0xdd
+#define ADM1075_VAUX_OV_WARN_LIMIT 0xde
+#define ADM1075_VAUX_UV_WARN_LIMIT 0xdf
+#define ADM1075_VAUX_STATUS 0xf6
+
+#define ADM1075_VAUX_OV_WARN (1<<7)
+#define ADM1075_VAUX_UV_WARN (1<<6)
+
struct adm1275_data {
int id;
bool have_oc_fault;
}
ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT);
break;
+ case PMBUS_VOUT_OV_WARN_LIMIT:
+ if (data->id != adm1075) {
+ ret = -ENODATA;
+ break;
+ }
+ ret = pmbus_read_word_data(client, 0,
+ ADM1075_VAUX_OV_WARN_LIMIT);
+ break;
+ case PMBUS_VOUT_UV_WARN_LIMIT:
+ if (data->id != adm1075) {
+ ret = -ENODATA;
+ break;
+ }
+ ret = pmbus_read_word_data(client, 0,
+ ADM1075_VAUX_UV_WARN_LIMIT);
+ break;
+ case PMBUS_READ_VOUT:
+ if (data->id != adm1075) {
+ ret = -ENODATA;
+ break;
+ }
+ ret = pmbus_read_word_data(client, 0, ADM1075_READ_VAUX);
+ break;
case PMBUS_VIRT_READ_IOUT_MAX:
ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_IOUT);
break;
ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN);
break;
case PMBUS_VIRT_READ_PIN_MAX:
- if (data->id != adm1276) {
+ if (data->id == adm1275) {
ret = -ENXIO;
break;
}
case PMBUS_VIRT_RESET_VIN_HISTORY:
break;
case PMBUS_VIRT_RESET_PIN_HISTORY:
- if (data->id != adm1276)
+ if (data->id == adm1275)
ret = -ENXIO;
break;
default:
PB_IOUT_OC_FAULT : PB_IOUT_UC_FAULT;
}
break;
+ case PMBUS_STATUS_VOUT:
+ if (data->id != adm1075) {
+ ret = -ENODATA;
+ break;
+ }
+ ret = 0;
+ mfr_status = pmbus_read_byte_data(client, 0,
+ ADM1075_VAUX_STATUS);
+ if (mfr_status & ADM1075_VAUX_OV_WARN)
+ ret |= PB_VOLTAGE_OV_WARNING;
+ if (mfr_status & ADM1075_VAUX_UV_WARN)
+ ret |= PB_VOLTAGE_UV_WARNING;
+ break;
default:
ret = -ENODATA;
break;
}
static const struct i2c_device_id adm1275_id[] = {
+ { "adm1075", adm1075 },
{ "adm1275", adm1275 },
{ "adm1276", adm1276 },
{ }
info->read_byte_data = adm1275_read_byte_data;
info->write_word_data = adm1275_write_word_data;
- if (config & ADM1275_VRANGE) {
+ if (data->id == adm1075) {
+ info->m[PSC_VOLTAGE_IN] = 27169;
+ info->b[PSC_VOLTAGE_IN] = 0;
+ info->R[PSC_VOLTAGE_IN] = -1;
+ info->m[PSC_VOLTAGE_OUT] = 27169;
+ info->b[PSC_VOLTAGE_OUT] = 0;
+ info->R[PSC_VOLTAGE_OUT] = -1;
+ } else if (config & ADM1275_VRANGE) {
info->m[PSC_VOLTAGE_IN] = 19199;
info->b[PSC_VOLTAGE_IN] = 0;
info->R[PSC_VOLTAGE_IN] = -2;
data->have_oc_fault = true;
switch (data->id) {
+ case adm1075:
+ info->format[PSC_POWER] = direct;
+ info->b[PSC_POWER] = 0;
+ info->R[PSC_POWER] = -1;
+ switch (config & ADM1075_IRANGE_MASK) {
+ case ADM1075_IRANGE_25:
+ info->m[PSC_POWER] = 8549;
+ info->m[PSC_CURRENT_OUT] = 806;
+ break;
+ case ADM1075_IRANGE_50:
+ info->m[PSC_POWER] = 4279;
+ info->m[PSC_CURRENT_OUT] = 404;
+ break;
+ default:
+ dev_err(&client->dev, "Invalid input current range");
+ info->m[PSC_POWER] = 0;
+ info->m[PSC_CURRENT_OUT] = 0;
+ break;
+ }
+ info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_PIN
+ | PMBUS_HAVE_STATUS_INPUT;
+ if (config & ADM1275_VIN_VOUT_SELECT)
+ info->func[0] |=
+ PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
+ break;
case adm1275:
if (config & ADM1275_VIN_VOUT_SELECT)
info->func[0] |=