Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Hardware monitoring driver for LTC3815
0004  *
0005  * Copyright (c) 2015 Linear Technology
0006  * Copyright (c) 2015 Guenter Roeck
0007  */
0008 
0009 #include <linux/err.h>
0010 #include <linux/i2c.h>
0011 #include <linux/init.h>
0012 #include <linux/jiffies.h>
0013 #include <linux/kernel.h>
0014 #include <linux/module.h>
0015 #include "pmbus.h"
0016 
0017 #define LTC3815_MFR_IOUT_PEAK   0xd7
0018 #define LTC3815_MFR_VOUT_PEAK   0xdd
0019 #define LTC3815_MFR_VIN_PEAK    0xde
0020 #define LTC3815_MFR_TEMP_PEAK   0xdf
0021 #define LTC3815_MFR_IIN_PEAK    0xe1
0022 #define LTC3815_MFR_SPECIAL_ID  0xe7
0023 
0024 #define LTC3815_ID      0x8000
0025 #define LTC3815_ID_MASK     0xff00
0026 
0027 static int ltc3815_read_byte_data(struct i2c_client *client, int page, int reg)
0028 {
0029     int ret;
0030 
0031     switch (reg) {
0032     case PMBUS_VOUT_MODE:
0033         /*
0034          * The chip returns 0x3e, suggesting VID mode with manufacturer
0035          * specific VID codes. Since the output voltage is reported
0036          * with a LSB of 0.5mV, override and report direct mode with
0037          * appropriate coefficients.
0038          */
0039         ret = 0x40;
0040         break;
0041     default:
0042         ret = -ENODATA;
0043         break;
0044     }
0045     return ret;
0046 }
0047 
0048 static int ltc3815_write_byte(struct i2c_client *client, int page, u8 reg)
0049 {
0050     int ret;
0051 
0052     switch (reg) {
0053     case PMBUS_CLEAR_FAULTS:
0054         /*
0055          * LTC3815 does not support the CLEAR_FAULTS command.
0056          * Emulate it by clearing the status register.
0057          */
0058         ret = pmbus_read_word_data(client, 0, 0xff, PMBUS_STATUS_WORD);
0059         if (ret > 0) {
0060             pmbus_write_word_data(client, 0, PMBUS_STATUS_WORD,
0061                           ret);
0062             ret = 0;
0063         }
0064         break;
0065     default:
0066         ret = -ENODATA;
0067         break;
0068     }
0069     return ret;
0070 }
0071 
0072 static int ltc3815_read_word_data(struct i2c_client *client, int page,
0073                   int phase, int reg)
0074 {
0075     int ret;
0076 
0077     switch (reg) {
0078     case PMBUS_VIRT_READ_VIN_MAX:
0079         ret = pmbus_read_word_data(client, page, phase,
0080                        LTC3815_MFR_VIN_PEAK);
0081         break;
0082     case PMBUS_VIRT_READ_VOUT_MAX:
0083         ret = pmbus_read_word_data(client, page, phase,
0084                        LTC3815_MFR_VOUT_PEAK);
0085         break;
0086     case PMBUS_VIRT_READ_TEMP_MAX:
0087         ret = pmbus_read_word_data(client, page, phase,
0088                        LTC3815_MFR_TEMP_PEAK);
0089         break;
0090     case PMBUS_VIRT_READ_IOUT_MAX:
0091         ret = pmbus_read_word_data(client, page, phase,
0092                        LTC3815_MFR_IOUT_PEAK);
0093         break;
0094     case PMBUS_VIRT_READ_IIN_MAX:
0095         ret = pmbus_read_word_data(client, page, phase,
0096                        LTC3815_MFR_IIN_PEAK);
0097         break;
0098     case PMBUS_VIRT_RESET_VOUT_HISTORY:
0099     case PMBUS_VIRT_RESET_VIN_HISTORY:
0100     case PMBUS_VIRT_RESET_TEMP_HISTORY:
0101     case PMBUS_VIRT_RESET_IOUT_HISTORY:
0102     case PMBUS_VIRT_RESET_IIN_HISTORY:
0103         ret = 0;
0104         break;
0105     default:
0106         ret = -ENODATA;
0107         break;
0108     }
0109     return ret;
0110 }
0111 
0112 static int ltc3815_write_word_data(struct i2c_client *client, int page,
0113                    int reg, u16 word)
0114 {
0115     int ret;
0116 
0117     switch (reg) {
0118     case PMBUS_VIRT_RESET_IIN_HISTORY:
0119         ret = pmbus_write_word_data(client, page,
0120                         LTC3815_MFR_IIN_PEAK, 0);
0121         break;
0122     case PMBUS_VIRT_RESET_IOUT_HISTORY:
0123         ret = pmbus_write_word_data(client, page,
0124                         LTC3815_MFR_IOUT_PEAK, 0);
0125         break;
0126     case PMBUS_VIRT_RESET_VOUT_HISTORY:
0127         ret = pmbus_write_word_data(client, page,
0128                         LTC3815_MFR_VOUT_PEAK, 0);
0129         break;
0130     case PMBUS_VIRT_RESET_VIN_HISTORY:
0131         ret = pmbus_write_word_data(client, page,
0132                         LTC3815_MFR_VIN_PEAK, 0);
0133         break;
0134     case PMBUS_VIRT_RESET_TEMP_HISTORY:
0135         ret = pmbus_write_word_data(client, page,
0136                         LTC3815_MFR_TEMP_PEAK, 0);
0137         break;
0138     default:
0139         ret = -ENODATA;
0140         break;
0141     }
0142     return ret;
0143 }
0144 
0145 static const struct i2c_device_id ltc3815_id[] = {
0146     {"ltc3815", 0},
0147     { }
0148 };
0149 MODULE_DEVICE_TABLE(i2c, ltc3815_id);
0150 
0151 static struct pmbus_driver_info ltc3815_info = {
0152     .pages = 1,
0153     .format[PSC_VOLTAGE_IN] = direct,
0154     .format[PSC_VOLTAGE_OUT] = direct,
0155     .format[PSC_CURRENT_IN] = direct,
0156     .format[PSC_CURRENT_OUT] = direct,
0157     .format[PSC_TEMPERATURE] = direct,
0158     .m[PSC_VOLTAGE_IN] = 250,
0159     .b[PSC_VOLTAGE_IN] = 0,
0160     .R[PSC_VOLTAGE_IN] = 0,
0161     .m[PSC_VOLTAGE_OUT] = 2,
0162     .b[PSC_VOLTAGE_OUT] = 0,
0163     .R[PSC_VOLTAGE_OUT] = 3,
0164     .m[PSC_CURRENT_IN] = 1,
0165     .b[PSC_CURRENT_IN] = 0,
0166     .R[PSC_CURRENT_IN] = 2,
0167     .m[PSC_CURRENT_OUT] = 1,
0168     .b[PSC_CURRENT_OUT] = 0,
0169     .R[PSC_CURRENT_OUT] = 2,
0170     .m[PSC_TEMPERATURE] = 1,
0171     .b[PSC_TEMPERATURE] = 0,
0172     .R[PSC_TEMPERATURE] = 0,
0173     .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN | PMBUS_HAVE_VOUT |
0174         PMBUS_HAVE_IOUT | PMBUS_HAVE_TEMP,
0175     .read_byte_data = ltc3815_read_byte_data,
0176     .read_word_data = ltc3815_read_word_data,
0177     .write_byte = ltc3815_write_byte,
0178     .write_word_data = ltc3815_write_word_data,
0179 };
0180 
0181 static int ltc3815_probe(struct i2c_client *client)
0182 {
0183     int chip_id;
0184 
0185     if (!i2c_check_functionality(client->adapter,
0186                      I2C_FUNC_SMBUS_READ_WORD_DATA))
0187         return -ENODEV;
0188 
0189     chip_id = i2c_smbus_read_word_data(client, LTC3815_MFR_SPECIAL_ID);
0190     if (chip_id < 0)
0191         return chip_id;
0192     if ((chip_id & LTC3815_ID_MASK) != LTC3815_ID)
0193         return -ENODEV;
0194 
0195     return pmbus_do_probe(client, &ltc3815_info);
0196 }
0197 
0198 static struct i2c_driver ltc3815_driver = {
0199     .driver = {
0200            .name = "ltc3815",
0201            },
0202     .probe_new = ltc3815_probe,
0203     .id_table = ltc3815_id,
0204 };
0205 
0206 module_i2c_driver(ltc3815_driver);
0207 
0208 MODULE_AUTHOR("Guenter Roeck");
0209 MODULE_DESCRIPTION("PMBus driver for LTC3815");
0210 MODULE_LICENSE("GPL");
0211 MODULE_IMPORT_NS(PMBUS);