| diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c |
| index 188af4c..a45075d 100644 |
| --- a/drivers/hwmon/pmbus/adm1275.c |
| +++ b/drivers/hwmon/pmbus/adm1275.c |
| @@ -24,7 +24,7 @@ |
| #include <linux/bitops.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 ADM1293_MFR_STATUS_VAUX_UV_WARN BIT(5) |
| @@ -70,6 +70,22 @@ enum chips { adm1075, adm1275, adm1276, adm1293, adm1294 }; |
| #define ADM1075_VAUX_OV_WARN BIT(7) |
| #define ADM1075_VAUX_UV_WARN BIT(6) |
| |
| +#define ADM1278_PMON_CONTROL 0xd3 |
| +#define ADM1278_PMON_CONFIG 0xd4 |
| +#define ADM1278_CFG_TSFLT BIT(15) |
| +#define ADM1278_CFG_SIMULTANEOUS BIT(14) |
| +#define ADM1278_CFG_PMON_MODE BIT(4) |
| +#define ADM1278_CFG_TEMP1_EN BIT(3) |
| +#define ADM1278_CFG_VIN_EN BIT(2) |
| +#define ADM1278_CFG_VOUT_EN BIT(1) |
| +#define ADM1278_PEAK_TEMPERATURE 0xd7 |
| + |
| +#define ADM1278_R_SENSE 1000 /* R_sense resistor value in microohmsi */ |
| + |
| +static int r_sense = ADM1278_R_SENSE; |
| +module_param(r_sense, int, 0644); |
| +MODULE_PARM_DESC(r_sense, "Rsense resistor value in microohms"); |
| + |
| struct adm1275_data { |
| int id; |
| bool have_oc_fault; |
| @@ -186,6 +202,11 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg) |
| case PMBUS_VIRT_READ_VIN_MAX: |
| ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN); |
| break; |
| + case PMBUS_VIRT_READ_TEMP_MAX: |
| + if (data->id != adm1278) |
| + return -ENODATA; |
| + ret = pmbus_read_word_data(client, 0, ADM1278_PEAK_TEMPERATURE); |
| + break; |
| case PMBUS_VIRT_READ_PIN_MIN: |
| if (!data->have_pin_min) |
| return -ENXIO; |
| @@ -199,6 +220,7 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg) |
| case PMBUS_VIRT_RESET_IOUT_HISTORY: |
| case PMBUS_VIRT_RESET_VOUT_HISTORY: |
| case PMBUS_VIRT_RESET_VIN_HISTORY: |
| + case PMBUS_VIRT_RESET_TEMP_HISTORY: |
| break; |
| case PMBUS_VIRT_RESET_PIN_HISTORY: |
| if (!data->have_pin_max) |
| @@ -239,6 +261,9 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg, |
| case PMBUS_VIRT_RESET_VIN_HISTORY: |
| ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VIN, 0); |
| break; |
| + case PMBUS_VIRT_RESET_TEMP_HISTORY: |
| + ret = pmbus_write_word_data(client, 0, ADM1278_PEAK_TEMPERATURE, 0); |
| + break; |
| case PMBUS_VIRT_RESET_PIN_HISTORY: |
| ret = pmbus_write_word_data(client, 0, ADM1276_PEAK_PIN, 0); |
| if (!ret && data->have_pin_min) |
| @@ -312,6 +337,7 @@ static const struct i2c_device_id adm1275_id[] = { |
| { "adm1075", adm1075 }, |
| { "adm1275", adm1275 }, |
| { "adm1276", adm1276 }, |
| + { "adm1278", adm1278 }, |
| { "adm1293", adm1293 }, |
| { "adm1294", adm1294 }, |
| { } |
| @@ -335,6 +361,8 @@ static int adm1275_probe(struct i2c_client *client, |
| | I2C_FUNC_SMBUS_BLOCK_DATA)) |
| return -ENODEV; |
| |
| + /* i2c_aspeed driver does not handle i2c_smbus_read_block_data correctly */ |
| +#if 0 |
| ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, block_buffer); |
| if (ret < 0) { |
| dev_err(&client->dev, "Failed to read Manufacturer ID\n"); |
| @@ -363,6 +391,7 @@ static int adm1275_probe(struct i2c_client *client, |
| dev_notice(&client->dev, |
| "Device mismatch: Configured %s, detected %s\n", |
| id->name, mid->name); |
| +#endif |
| |
| config = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG); |
| if (config < 0) |
| @@ -377,7 +406,9 @@ static int adm1275_probe(struct i2c_client *client, |
| if (!data) |
| return -ENOMEM; |
| |
| - data->id = mid->driver_data; |
| + /* i2c_aspeed driver does not handle i2c_smbus_read_block_data correctly */ |
| + //data->id = mid->driver_data; |
| + data->id = adm1278; |
| |
| info = &data->info; |
| |
| @@ -460,6 +491,62 @@ static int adm1275_probe(struct i2c_client *client, |
| info->func[0] |= |
| PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; |
| break; |
| + case adm1278: |
| + /* Configure monitoring */ |
| + ret = i2c_smbus_write_byte_data(client, |
| + ADM1278_PMON_CONTROL, 0); |
| + if (ret < 0) |
| + return ret; |
| + ret = i2c_smbus_read_word_data(client, ADM1275_PMON_CONFIG); |
| + ret = i2c_smbus_write_word_data(client, ADM1275_PMON_CONFIG, |
| + ADM1278_CFG_PMON_MODE | |
| + ADM1278_CFG_TEMP1_EN | |
| + ADM1278_CFG_VIN_EN | |
| + ADM1278_CFG_VOUT_EN); |
| + if (ret < 0) |
| + return ret; |
| + ret = i2c_smbus_read_word_data(client, ADM1275_PMON_CONFIG); |
| + dev_info(&client->dev, "adm1278 config: 0x%x\n", ret); |
| + ret = i2c_smbus_write_byte_data(client, ADM1278_PMON_CONTROL,1); |
| + if (ret < 0) |
| + return ret; |
| + |
| + info->func[0] |= PMBUS_HAVE_VIN |
| + | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
| + | PMBUS_HAVE_PIN |
| + | PMBUS_HAVE_STATUS_INPUT |
| + | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; |
| + |
| + data->have_oc_fault = false; |
| + data->have_uc_fault = false; |
| + data->have_vout = true; |
| + data->have_vaux_status = false; |
| + data->have_mfr_vaux_status = false; |
| + data->have_iout_min = false; |
| + data->have_pin_min = false; |
| + data->have_pin_max = true; |
| + |
| + info->m[PSC_VOLTAGE_IN] = 19599; |
| + info->b[PSC_VOLTAGE_IN] = 0; |
| + info->R[PSC_VOLTAGE_IN] = -2; |
| + |
| + info->m[PSC_VOLTAGE_OUT] = 19599; |
| + info->b[PSC_VOLTAGE_OUT] = 0; |
| + info->R[PSC_VOLTAGE_OUT] = -2; |
| + |
| + info->m[PSC_CURRENT_OUT] = 800 * r_sense / 1000; |
| + info->b[PSC_CURRENT_OUT] = 20475; |
| + info->R[PSC_CURRENT_OUT] = -1; |
| + |
| + info->m[PSC_POWER] = 6123 * r_sense / 1000; |
| + info->b[PSC_POWER] = 0; |
| + info->R[PSC_POWER] = -2; |
| + |
| + info->format[PSC_TEMPERATURE] = direct; |
| + info->m[PSC_TEMPERATURE] = 42; |
| + info->b[PSC_TEMPERATURE] = 31880; |
| + info->R[PSC_TEMPERATURE] = -1; |
| + break; |
| case adm1293: |
| case adm1294: |
| data->have_iout_min = true; |