Commit 709066ac authored by Guenter Roeck's avatar Guenter Roeck

hwmon: (adm1275) Add support for ADM1278

ADM1278 is mostly compatible to other chips of the same series.
Besides the usual difference in coefficients, it supports
a temperature sensor, and it can measure both input and output
voltage at the same time.
Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
parent 54ce3a0d
...@@ -14,6 +14,10 @@ Supported chips: ...@@ -14,6 +14,10 @@ Supported chips:
Prefix: 'adm1276' Prefix: 'adm1276'
Addresses scanned: - Addresses scanned: -
Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1276.pdf Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1276.pdf
* Analog Devices ADM1278
Prefix: 'adm1278'
Addresses scanned: -
Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1278.pdf
* Analog Devices ADM1293/ADM1294 * Analog Devices ADM1293/ADM1294
Prefix: 'adm1293', 'adm1294' Prefix: 'adm1293', 'adm1294'
Addresses scanned: - Addresses scanned: -
...@@ -26,12 +30,14 @@ Description ...@@ -26,12 +30,14 @@ Description
----------- -----------
This driver supports hardware monitoring for Analog Devices ADM1075, ADM1275, This driver supports hardware monitoring for Analog Devices ADM1075, ADM1275,
ADM1276, ADM1293, and ADM1294 Hot-Swap Controller and Digital Power Monitors. ADM1276, ADM1278, ADM1293, and ADM1294 Hot-Swap Controller and Digital
Power Monitors.
ADM1075, ADM1275, ADM1276, ADM1293, and ADM1294 are hot-swap controllers that ADM1075, ADM1275, ADM1276, ADM1278, ADM1293, and ADM1294 are hot-swap
allow a circuit board to be removed from or inserted into a live backplane. controllers that allow a circuit board to be removed from or inserted into
They also feature current and voltage readback via an integrated 12 a live backplane. They also feature current and voltage readback via an
bit analog-to-digital converter (ADC), accessed using a PMBus interface. 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 The driver is a client driver to the core PMBus driver. Please see
Documentation/hwmon/pmbus for details on PMBus client drivers. Documentation/hwmon/pmbus for details on PMBus client drivers.
...@@ -96,3 +102,14 @@ power1_reset_history Write any value to reset history. ...@@ -96,3 +102,14 @@ power1_reset_history Write any value to reset history.
Power attributes are supported on ADM1075, ADM1276, Power attributes are supported on ADM1075, ADM1276,
ADM1293, and ADM1294. ADM1293, and ADM1294.
temp1_input Chip temperature.
Temperature attributes are only available on ADM1278.
temp1_max Maximum chip temperature.
temp1_max_alarm Temperature alarm.
temp1_crit Critical chip temperature.
temp1_crit_alarm Critical temperature high alarm.
temp1_highest Highest observed temperature.
temp1_reset_history Write any value to reset history.
Temperature attributes are supported on ADM1278.
...@@ -31,8 +31,8 @@ config SENSORS_ADM1275 ...@@ -31,8 +31,8 @@ config SENSORS_ADM1275
default n default n
help help
If you say yes here you get hardware monitoring support for Analog If you say yes here you get hardware monitoring support for Analog
Devices ADM1075, ADM1275, ADM1276, ADM1293, and ADM1294 Hot-Swap Devices ADM1075, ADM1275, ADM1276, ADM1278, ADM1293, and ADM1294
Controller and Digital Power Monitors. Hot-Swap Controller and Digital Power Monitors.
This driver can also be built as a module. If so, the module will This driver can also be built as a module. If so, the module will
be called adm1275. be called adm1275.
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include "pmbus.h" #include "pmbus.h"
enum chips { adm1075, adm1275, adm1276, adm1293, adm1294 }; enum chips { adm1075, adm1275, adm1276, adm1278, adm1293, adm1294 };
#define ADM1275_MFR_STATUS_IOUT_WARN2 BIT(0) #define ADM1275_MFR_STATUS_IOUT_WARN2 BIT(0)
#define ADM1293_MFR_STATUS_VAUX_UV_WARN BIT(5) #define ADM1293_MFR_STATUS_VAUX_UV_WARN BIT(5)
...@@ -41,6 +41,10 @@ enum chips { adm1075, adm1275, adm1276, adm1293, adm1294 }; ...@@ -41,6 +41,10 @@ enum chips { adm1075, adm1275, adm1276, adm1293, adm1294 };
#define ADM1075_IRANGE_25 BIT(3) #define ADM1075_IRANGE_25 BIT(3)
#define ADM1075_IRANGE_MASK (BIT(3) | BIT(4)) #define ADM1075_IRANGE_MASK (BIT(3) | BIT(4))
#define ADM1278_TEMP1_EN BIT(3)
#define ADM1278_VIN_EN BIT(2)
#define ADM1278_VOUT_EN BIT(1)
#define ADM1293_IRANGE_25 0 #define ADM1293_IRANGE_25 0
#define ADM1293_IRANGE_50 BIT(6) #define ADM1293_IRANGE_50 BIT(6)
#define ADM1293_IRANGE_100 BIT(7) #define ADM1293_IRANGE_100 BIT(7)
...@@ -54,6 +58,7 @@ enum chips { adm1075, adm1275, adm1276, adm1293, adm1294 }; ...@@ -54,6 +58,7 @@ enum chips { adm1075, adm1275, adm1276, adm1293, adm1294 };
#define ADM1293_VAUX_EN BIT(1) #define ADM1293_VAUX_EN BIT(1)
#define ADM1278_PEAK_TEMP 0xd7
#define ADM1275_IOUT_WARN2_LIMIT 0xd7 #define ADM1275_IOUT_WARN2_LIMIT 0xd7
#define ADM1275_DEVICE_CONFIG 0xd8 #define ADM1275_DEVICE_CONFIG 0xd8
...@@ -80,6 +85,7 @@ struct adm1275_data { ...@@ -80,6 +85,7 @@ struct adm1275_data {
bool have_iout_min; bool have_iout_min;
bool have_pin_min; bool have_pin_min;
bool have_pin_max; bool have_pin_max;
bool have_temp_max;
struct pmbus_driver_info info; struct pmbus_driver_info info;
}; };
...@@ -113,6 +119,13 @@ static const struct coefficients adm1276_coefficients[] = { ...@@ -113,6 +119,13 @@ static const struct coefficients adm1276_coefficients[] = {
[4] = { 2115, 0, -1 }, /* power, vrange not set */ [4] = { 2115, 0, -1 }, /* power, vrange not set */
}; };
static const struct coefficients adm1278_coefficients[] = {
[0] = { 19599, 0, -2 }, /* voltage */
[1] = { 800, 20475, -1 }, /* current */
[2] = { 6123, 0, -2 }, /* power */
[3] = { 42, 31880, -1 }, /* temperature */
};
static const struct coefficients adm1293_coefficients[] = { static const struct coefficients adm1293_coefficients[] = {
[0] = { 3333, -1, 0 }, /* voltage, vrange 1.2V */ [0] = { 3333, -1, 0 }, /* voltage, vrange 1.2V */
[1] = { 5552, -5, -1 }, /* voltage, vrange 7.4V */ [1] = { 5552, -5, -1 }, /* voltage, vrange 7.4V */
...@@ -196,6 +209,11 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg) ...@@ -196,6 +209,11 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
return -ENXIO; return -ENXIO;
ret = pmbus_read_word_data(client, 0, ADM1276_PEAK_PIN); ret = pmbus_read_word_data(client, 0, ADM1276_PEAK_PIN);
break; break;
case PMBUS_VIRT_READ_TEMP_MAX:
if (!data->have_temp_max)
return -ENXIO;
ret = pmbus_read_word_data(client, 0, ADM1278_PEAK_TEMP);
break;
case PMBUS_VIRT_RESET_IOUT_HISTORY: case PMBUS_VIRT_RESET_IOUT_HISTORY:
case PMBUS_VIRT_RESET_VOUT_HISTORY: case PMBUS_VIRT_RESET_VOUT_HISTORY:
case PMBUS_VIRT_RESET_VIN_HISTORY: case PMBUS_VIRT_RESET_VIN_HISTORY:
...@@ -204,6 +222,10 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg) ...@@ -204,6 +222,10 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
if (!data->have_pin_max) if (!data->have_pin_max)
return -ENXIO; return -ENXIO;
break; break;
case PMBUS_VIRT_RESET_TEMP_HISTORY:
if (!data->have_temp_max)
return -ENXIO;
break;
default: default:
ret = -ENODATA; ret = -ENODATA;
break; break;
...@@ -245,6 +267,9 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg, ...@@ -245,6 +267,9 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
ret = pmbus_write_word_data(client, 0, ret = pmbus_write_word_data(client, 0,
ADM1293_PIN_MIN, 0); ADM1293_PIN_MIN, 0);
break; break;
case PMBUS_VIRT_RESET_TEMP_HISTORY:
ret = pmbus_write_word_data(client, 0, ADM1278_PEAK_TEMP, 0);
break;
default: default:
ret = -ENODATA; ret = -ENODATA;
break; break;
...@@ -312,6 +337,7 @@ static const struct i2c_device_id adm1275_id[] = { ...@@ -312,6 +337,7 @@ static const struct i2c_device_id adm1275_id[] = {
{ "adm1075", adm1075 }, { "adm1075", adm1075 },
{ "adm1275", adm1275 }, { "adm1275", adm1275 },
{ "adm1276", adm1276 }, { "adm1276", adm1276 },
{ "adm1278", adm1278 },
{ "adm1293", adm1293 }, { "adm1293", adm1293 },
{ "adm1294", adm1294 }, { "adm1294", adm1294 },
{ } { }
...@@ -329,6 +355,7 @@ static int adm1275_probe(struct i2c_client *client, ...@@ -329,6 +355,7 @@ static int adm1275_probe(struct i2c_client *client,
const struct i2c_device_id *mid; const struct i2c_device_id *mid;
const struct coefficients *coefficients; const struct coefficients *coefficients;
int vindex = -1, voindex = -1, cindex = -1, pindex = -1; int vindex = -1, voindex = -1, cindex = -1, pindex = -1;
int tindex = -1;
if (!i2c_check_functionality(client->adapter, if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_READ_BYTE_DATA I2C_FUNC_SMBUS_READ_BYTE_DATA
...@@ -386,6 +413,7 @@ static int adm1275_probe(struct i2c_client *client, ...@@ -386,6 +413,7 @@ static int adm1275_probe(struct i2c_client *client,
info->format[PSC_VOLTAGE_OUT] = direct; info->format[PSC_VOLTAGE_OUT] = direct;
info->format[PSC_CURRENT_OUT] = direct; info->format[PSC_CURRENT_OUT] = direct;
info->format[PSC_POWER] = direct; info->format[PSC_POWER] = direct;
info->format[PSC_TEMPERATURE] = direct;
info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT; info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
info->read_word_data = adm1275_read_word_data; info->read_word_data = adm1275_read_word_data;
...@@ -460,6 +488,27 @@ static int adm1275_probe(struct i2c_client *client, ...@@ -460,6 +488,27 @@ static int adm1275_probe(struct i2c_client *client,
info->func[0] |= info->func[0] |=
PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
break; break;
case adm1278:
data->have_vout = true;
data->have_pin_max = true;
data->have_temp_max = true;
coefficients = adm1278_coefficients;
vindex = 0;
cindex = 1;
pindex = 2;
tindex = 3;
info->func[0] |= PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT;
if (config & ADM1278_TEMP1_EN)
info->func[0] |=
PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
if (config & ADM1278_VIN_EN)
info->func[0] |= PMBUS_HAVE_VIN;
if (config & ADM1278_VOUT_EN)
info->func[0] |=
PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
break;
case adm1293: case adm1293:
case adm1294: case adm1294:
data->have_iout_min = true; data->have_iout_min = true;
...@@ -537,6 +586,11 @@ static int adm1275_probe(struct i2c_client *client, ...@@ -537,6 +586,11 @@ static int adm1275_probe(struct i2c_client *client,
info->b[PSC_POWER] = coefficients[pindex].b; info->b[PSC_POWER] = coefficients[pindex].b;
info->R[PSC_POWER] = coefficients[pindex].R; info->R[PSC_POWER] = coefficients[pindex].R;
} }
if (tindex >= 0) {
info->m[PSC_TEMPERATURE] = coefficients[tindex].m;
info->b[PSC_TEMPERATURE] = coefficients[tindex].b;
info->R[PSC_TEMPERATURE] = coefficients[tindex].R;
}
return pmbus_do_probe(client, id, info); return pmbus_do_probe(client, id, info);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment