hwmon: (adm1275) Add support for ADM1075
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
This commit is contained in:
Родитель
590defe59e
Коммит
9271126966
|
@ -2,6 +2,10 @@ Kernel driver adm1275
|
|||
=====================
|
||||
|
||||
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: -
|
||||
|
@ -17,13 +21,13 @@ Author: Guenter Roeck <guenter.roeck@ericsson.com>
|
|||
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.
|
||||
|
@ -36,6 +40,10 @@ This driver does not auto-detect devices. You will have to instantiate the
|
|||
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
|
||||
---------------------
|
||||
|
@ -51,7 +59,8 @@ The following attributes are supported. Limits are read-write, history reset
|
|||
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.
|
||||
|
@ -74,3 +83,10 @@ curr1_crit Critical maximum current. Depending on the chip
|
|||
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.
|
||||
|
|
|
@ -31,8 +31,8 @@ config SENSORS_ADM1275
|
|||
default n
|
||||
help
|
||||
If you say yes here you get hardware monitoring support for Analog
|
||||
Devices ADM1275 and ADM1276 Hot-Swap Controller and Digital Power
|
||||
Monitor.
|
||||
Devices ADM1075, ADM1275, and ADM1276 Hot-Swap Controller and Digital
|
||||
Power Monitors.
|
||||
|
||||
This driver can also be built as a module. If so, the module will
|
||||
be called adm1275.
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#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
|
||||
|
@ -32,6 +32,9 @@ enum chips { adm1275, adm1276 };
|
|||
|
||||
#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
|
||||
|
@ -42,6 +45,14 @@ enum chips { adm1275, adm1276 };
|
|||
|
||||
#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;
|
||||
|
@ -74,6 +85,29 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
|
|||
}
|
||||
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;
|
||||
|
@ -84,7 +118,7 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
|
|||
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;
|
||||
}
|
||||
|
@ -95,7 +129,7 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
|
|||
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:
|
||||
|
@ -163,6 +197,19 @@ static int adm1275_read_byte_data(struct i2c_client *client, int page, int reg)
|
|||
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;
|
||||
|
@ -171,6 +218,7 @@ static int adm1275_read_byte_data(struct i2c_client *client, int page, int reg)
|
|||
}
|
||||
|
||||
static const struct i2c_device_id adm1275_id[] = {
|
||||
{ "adm1075", adm1075 },
|
||||
{ "adm1275", adm1275 },
|
||||
{ "adm1276", adm1276 },
|
||||
{ }
|
||||
|
@ -251,7 +299,14 @@ static int adm1275_probe(struct i2c_client *client,
|
|||
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;
|
||||
|
@ -271,6 +326,31 @@ static int adm1275_probe(struct i2c_client *client,
|
|||
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] |=
|
||||
|
|
Загрузка…
Ссылка в новой задаче