Prefix: 'adm1275'
     Addresses scanned: -
     Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1275.pdf
+  * Analog Devices ADM1276
+    Prefix: 'adm1276'
+    Addresses scanned: -
+    Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1276.pdf
 
 Author: Guenter Roeck <guenter.roeck@ericsson.com>
 
 Description
 -----------
 
-This driver supports hardware montoring for Analog Devices ADM1275 Hot-Swap
-Controller and Digital Power Monitor.
+This driver supports hardware montoring for Analog Devices ADM1275 and ADM1276
+Hot-Swap Controller and Digital Power Monitor.
 
-The ADM1275 is a hot-swap controller that allows a circuit board to be removed
-from or inserted into a live backplane. It also features current and voltage
-readback via an integrated 12-bit analog-to-digital converter (ADC), accessed
-using a PMBus. interface.
+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.
 
 in1_label              "vin1" or "vout1" depending on chip variant and
                        configuration.
-in1_input              Measured voltage. From READ_VOUT register.
-in1_min                        Minumum Voltage. From VOUT_UV_WARN_LIMIT register.
-in1_max                        Maximum voltage. From VOUT_OV_WARN_LIMIT register.
-in1_min_alarm          Voltage low alarm. From VOLTAGE_UV_WARNING status.
-in1_max_alarm          Voltage high alarm. From VOLTAGE_OV_WARNING status.
+in1_input              Measured voltage.
+in1_min                        Minumum Voltage.
+in1_max                        Maximum voltage.
+in1_min_alarm          Voltage low alarm.
+in1_max_alarm          Voltage high alarm.
 in1_highest            Historical maximum voltage.
 in1_reset_history      Write any value to reset history.
 
 curr1_label            "iout1"
-curr1_input            Measured current. From READ_IOUT register.
-curr1_max              Maximum current. From IOUT_OC_WARN_LIMIT register.
-curr1_max_alarm                Current high alarm. From IOUT_OC_WARN_LIMIT register.
+curr1_input            Measured current.
+curr1_max              Maximum current.
+curr1_max_alarm                Current high alarm.
 curr1_lcrit            Critical minimum current. Depending on the chip
                        configuration, either curr1_lcrit or curr1_crit is
                        supported, but not both.
 
 #include <linux/i2c.h>
 #include "pmbus.h"
 
+enum chips { adm1275, adm1276 };
+
 #define ADM1275_PEAK_IOUT              0xd0
 #define ADM1275_PEAK_VIN               0xd1
 #define ADM1275_PEAK_VOUT              0xd2
 
 #define ADM1275_IOUT_WARN2_SELECT      (1 << 4)
 
+#define ADM1276_PEAK_PIN               0xda
+
 #define ADM1275_MFR_STATUS_IOUT_WARN2  (1 << 0)
 
 struct adm1275_data {
+       int id;
        bool have_oc_fault;
        struct pmbus_driver_info info;
 };
 {
        const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
        const struct adm1275_data *data = to_adm1275_data(info);
-       int ret;
+       int ret = 0;
 
        if (page)
                return -ENXIO;
        case PMBUS_VIRT_READ_VIN_MAX:
                ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN);
                break;
+       case PMBUS_VIRT_READ_PIN_MAX:
+               if (data->id != adm1276) {
+                       ret = -ENXIO;
+                       break;
+               }
+               ret = pmbus_read_word_data(client, 0, ADM1276_PEAK_PIN);
+               break;
        case PMBUS_VIRT_RESET_IOUT_HISTORY:
        case PMBUS_VIRT_RESET_VOUT_HISTORY:
        case PMBUS_VIRT_RESET_VIN_HISTORY:
-               ret = 0;
+               break;
+       case PMBUS_VIRT_RESET_PIN_HISTORY:
+               if (data->id != adm1276)
+                       ret = -ENXIO;
                break;
        default:
                ret = -ENODATA;
        case PMBUS_VIRT_RESET_VIN_HISTORY:
                ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VIN, 0);
                break;
+       case PMBUS_VIRT_RESET_PIN_HISTORY:
+               ret = pmbus_write_word_data(client, 0, ADM1276_PEAK_PIN, 0);
+               break;
        default:
                ret = -ENODATA;
                break;
                goto err_mem;
        }
 
+       data->id = id->driver_data;
        info = &data->info;
 
        info->pages = 1;
        if (device_config & ADM1275_IOUT_WARN2_SELECT)
                data->have_oc_fault = true;
 
-       if (config & ADM1275_VIN_VOUT_SELECT)
-               info->func[0] |= PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
-       else
-               info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT;
+       switch (id->driver_data) {
+       case adm1275:
+               if (config & ADM1275_VIN_VOUT_SELECT)
+                       info->func[0] |=
+                         PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
+               else
+                       info->func[0] |=
+                         PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT;
+               break;
+       case adm1276:
+               info->format[PSC_POWER] = direct;
+               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;
+               if (config & ADM1275_VRANGE) {
+                       info->m[PSC_POWER] = 6043;
+                       info->b[PSC_POWER] = 0;
+                       info->R[PSC_POWER] = -2;
+               } else {
+                       info->m[PSC_POWER] = 2115;
+                       info->b[PSC_POWER] = 0;
+                       info->R[PSC_POWER] = -1;
+               }
+               break;
+       }
 
        ret = pmbus_do_probe(client, id, info);
        if (ret)
 }
 
 static const struct i2c_device_id adm1275_id[] = {
-       {"adm1275", 0},
+       { "adm1275", adm1275 },
+       { "adm1276", adm1276 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, adm1275_id);
 }
 
 MODULE_AUTHOR("Guenter Roeck");
-MODULE_DESCRIPTION("PMBus driver for Analog Devices ADM1275");
+MODULE_DESCRIPTION("PMBus driver for Analog Devices ADM1275 and compatibles");
 MODULE_LICENSE("GPL");
 module_init(adm1275_init);
 module_exit(adm1275_exit);