212 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Hardware monitoring driver for LTC38154 *5 * Copyright (c) 2015 Linear Technology6 * Copyright (c) 2015 Guenter Roeck7 */8 9#include <linux/err.h>10#include <linux/i2c.h>11#include <linux/init.h>12#include <linux/jiffies.h>13#include <linux/kernel.h>14#include <linux/module.h>15#include "pmbus.h"16 17#define LTC3815_MFR_IOUT_PEAK 0xd718#define LTC3815_MFR_VOUT_PEAK 0xdd19#define LTC3815_MFR_VIN_PEAK 0xde20#define LTC3815_MFR_TEMP_PEAK 0xdf21#define LTC3815_MFR_IIN_PEAK 0xe122#define LTC3815_MFR_SPECIAL_ID 0xe723 24#define LTC3815_ID 0x800025#define LTC3815_ID_MASK 0xff0026 27static int ltc3815_read_byte_data(struct i2c_client *client, int page, int reg)28{29 int ret;30 31 switch (reg) {32 case PMBUS_VOUT_MODE:33 /*34 * The chip returns 0x3e, suggesting VID mode with manufacturer35 * specific VID codes. Since the output voltage is reported36 * with a LSB of 0.5mV, override and report direct mode with37 * appropriate coefficients.38 */39 ret = 0x40;40 break;41 default:42 ret = -ENODATA;43 break;44 }45 return ret;46}47 48static int ltc3815_write_byte(struct i2c_client *client, int page, u8 reg)49{50 int ret;51 52 switch (reg) {53 case PMBUS_CLEAR_FAULTS:54 /*55 * LTC3815 does not support the CLEAR_FAULTS command.56 * Emulate it by clearing the status register.57 */58 ret = pmbus_read_word_data(client, 0, 0xff, PMBUS_STATUS_WORD);59 if (ret > 0) {60 pmbus_write_word_data(client, 0, PMBUS_STATUS_WORD,61 ret);62 ret = 0;63 }64 break;65 default:66 ret = -ENODATA;67 break;68 }69 return ret;70}71 72static int ltc3815_read_word_data(struct i2c_client *client, int page,73 int phase, int reg)74{75 int ret;76 77 switch (reg) {78 case PMBUS_VIRT_READ_VIN_MAX:79 ret = pmbus_read_word_data(client, page, phase,80 LTC3815_MFR_VIN_PEAK);81 break;82 case PMBUS_VIRT_READ_VOUT_MAX:83 ret = pmbus_read_word_data(client, page, phase,84 LTC3815_MFR_VOUT_PEAK);85 break;86 case PMBUS_VIRT_READ_TEMP_MAX:87 ret = pmbus_read_word_data(client, page, phase,88 LTC3815_MFR_TEMP_PEAK);89 break;90 case PMBUS_VIRT_READ_IOUT_MAX:91 ret = pmbus_read_word_data(client, page, phase,92 LTC3815_MFR_IOUT_PEAK);93 break;94 case PMBUS_VIRT_READ_IIN_MAX:95 ret = pmbus_read_word_data(client, page, phase,96 LTC3815_MFR_IIN_PEAK);97 break;98 case PMBUS_VIRT_RESET_VOUT_HISTORY:99 case PMBUS_VIRT_RESET_VIN_HISTORY:100 case PMBUS_VIRT_RESET_TEMP_HISTORY:101 case PMBUS_VIRT_RESET_IOUT_HISTORY:102 case PMBUS_VIRT_RESET_IIN_HISTORY:103 ret = 0;104 break;105 default:106 ret = -ENODATA;107 break;108 }109 return ret;110}111 112static int ltc3815_write_word_data(struct i2c_client *client, int page,113 int reg, u16 word)114{115 int ret;116 117 switch (reg) {118 case PMBUS_VIRT_RESET_IIN_HISTORY:119 ret = pmbus_write_word_data(client, page,120 LTC3815_MFR_IIN_PEAK, 0);121 break;122 case PMBUS_VIRT_RESET_IOUT_HISTORY:123 ret = pmbus_write_word_data(client, page,124 LTC3815_MFR_IOUT_PEAK, 0);125 break;126 case PMBUS_VIRT_RESET_VOUT_HISTORY:127 ret = pmbus_write_word_data(client, page,128 LTC3815_MFR_VOUT_PEAK, 0);129 break;130 case PMBUS_VIRT_RESET_VIN_HISTORY:131 ret = pmbus_write_word_data(client, page,132 LTC3815_MFR_VIN_PEAK, 0);133 break;134 case PMBUS_VIRT_RESET_TEMP_HISTORY:135 ret = pmbus_write_word_data(client, page,136 LTC3815_MFR_TEMP_PEAK, 0);137 break;138 default:139 ret = -ENODATA;140 break;141 }142 return ret;143}144 145static const struct i2c_device_id ltc3815_id[] = {146 {"ltc3815"},147 { }148};149MODULE_DEVICE_TABLE(i2c, ltc3815_id);150 151static struct pmbus_driver_info ltc3815_info = {152 .pages = 1,153 .format[PSC_VOLTAGE_IN] = direct,154 .format[PSC_VOLTAGE_OUT] = direct,155 .format[PSC_CURRENT_IN] = direct,156 .format[PSC_CURRENT_OUT] = direct,157 .format[PSC_TEMPERATURE] = direct,158 .m[PSC_VOLTAGE_IN] = 250,159 .b[PSC_VOLTAGE_IN] = 0,160 .R[PSC_VOLTAGE_IN] = 0,161 .m[PSC_VOLTAGE_OUT] = 2,162 .b[PSC_VOLTAGE_OUT] = 0,163 .R[PSC_VOLTAGE_OUT] = 3,164 .m[PSC_CURRENT_IN] = 1,165 .b[PSC_CURRENT_IN] = 0,166 .R[PSC_CURRENT_IN] = 2,167 .m[PSC_CURRENT_OUT] = 1,168 .b[PSC_CURRENT_OUT] = 0,169 .R[PSC_CURRENT_OUT] = 2,170 .m[PSC_TEMPERATURE] = 1,171 .b[PSC_TEMPERATURE] = 0,172 .R[PSC_TEMPERATURE] = 0,173 .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN | PMBUS_HAVE_VOUT |174 PMBUS_HAVE_IOUT | PMBUS_HAVE_TEMP,175 .read_byte_data = ltc3815_read_byte_data,176 .read_word_data = ltc3815_read_word_data,177 .write_byte = ltc3815_write_byte,178 .write_word_data = ltc3815_write_word_data,179};180 181static int ltc3815_probe(struct i2c_client *client)182{183 int chip_id;184 185 if (!i2c_check_functionality(client->adapter,186 I2C_FUNC_SMBUS_READ_WORD_DATA))187 return -ENODEV;188 189 chip_id = i2c_smbus_read_word_data(client, LTC3815_MFR_SPECIAL_ID);190 if (chip_id < 0)191 return chip_id;192 if ((chip_id & LTC3815_ID_MASK) != LTC3815_ID)193 return -ENODEV;194 195 return pmbus_do_probe(client, <c3815_info);196}197 198static struct i2c_driver ltc3815_driver = {199 .driver = {200 .name = "ltc3815",201 },202 .probe = ltc3815_probe,203 .id_table = ltc3815_id,204};205 206module_i2c_driver(ltc3815_driver);207 208MODULE_AUTHOR("Guenter Roeck");209MODULE_DESCRIPTION("PMBus driver for LTC3815");210MODULE_LICENSE("GPL");211MODULE_IMPORT_NS(PMBUS);212