1c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck/* 2c24c407e963e73d3ad18b9bc0af32cf23f37a7b0Guenter Roeck * Hardware monitoring driver for LTC2974, LTC2977, LTC2978, LTC3880, 3f76992b00a4111fc4679b0b2d49fe75f05c2b04dGuenter Roeck * LTC3883, and LTM4676 4c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck * 5c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck * Copyright (c) 2011 Ericsson AB. 6f76992b00a4111fc4679b0b2d49fe75f05c2b04dGuenter Roeck * Copyright (c) 2013, 2014 Guenter Roeck 7c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck * 8c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck * This program is free software; you can redistribute it and/or modify 9c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck * it under the terms of the GNU General Public License as published by 10c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck * the Free Software Foundation; either version 2 of the License, or 11c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck * (at your option) any later version. 12c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck * 13c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck * This program is distributed in the hope that it will be useful, 14c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck * but WITHOUT ANY WARRANTY; without even the implied warranty of 15c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck * GNU General Public License for more details. 17c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck */ 18c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck 19c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck#include <linux/kernel.h> 20c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck#include <linux/module.h> 21c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck#include <linux/init.h> 22c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck#include <linux/err.h> 23c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck#include <linux/slab.h> 24c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck#include <linux/i2c.h> 25c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck#include "pmbus.h" 26c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck 27f76992b00a4111fc4679b0b2d49fe75f05c2b04dGuenter Roeckenum chips { ltc2974, ltc2977, ltc2978, ltc3880, ltc3883, ltm4676 }; 28c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck 29fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck/* Common for all chips */ 30c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck#define LTC2978_MFR_VOUT_PEAK 0xdd 31c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck#define LTC2978_MFR_VIN_PEAK 0xde 32c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck#define LTC2978_MFR_TEMPERATURE_PEAK 0xdf 33c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck#define LTC2978_MFR_SPECIAL_ID 0xe7 34c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck 35c24c407e963e73d3ad18b9bc0af32cf23f37a7b0Guenter Roeck/* LTC2974, LCT2977, and LTC2978 */ 36c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck#define LTC2978_MFR_VOUT_MIN 0xfb 37c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck#define LTC2978_MFR_VIN_MIN 0xfc 38c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck#define LTC2978_MFR_TEMPERATURE_MIN 0xfd 39c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck 40fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck/* LTC2974 only */ 41fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck#define LTC2974_MFR_IOUT_PEAK 0xd7 42fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck#define LTC2974_MFR_IOUT_MIN 0xd8 43fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck 44f76992b00a4111fc4679b0b2d49fe75f05c2b04dGuenter Roeck/* LTC3880, LTC3883, and LTM4676 */ 45ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck#define LTC3880_MFR_IOUT_PEAK 0xd7 46ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck#define LTC3880_MFR_CLEAR_PEAKS 0xe3 47ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck#define LTC3880_MFR_TEMPERATURE2_PEAK 0xf4 48ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck 49fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck/* LTC3883 only */ 50fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck#define LTC3883_MFR_IIN_PEAK 0xe1 51fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck 52a2e151074366487dcde943fdc08d88acfe476f9dGuenter Roeck#define LTC2974_ID_REV1 0x0212 53a2e151074366487dcde943fdc08d88acfe476f9dGuenter Roeck#define LTC2974_ID_REV2 0x0213 54c24c407e963e73d3ad18b9bc0af32cf23f37a7b0Guenter Roeck#define LTC2977_ID 0x0130 55c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck#define LTC2978_ID_REV1 0x0121 56c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck#define LTC2978_ID_REV2 0x0122 573f08d7f49f8365d5c9050522ee733951a503e955Guenter Roeck#define LTC2978A_ID 0x0124 58ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck#define LTC3880_ID 0x4000 59ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck#define LTC3880_ID_MASK 0xff00 60fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck#define LTC3883_ID 0x4300 61fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck#define LTC3883_ID_MASK 0xff00 62f76992b00a4111fc4679b0b2d49fe75f05c2b04dGuenter Roeck#define LTM4676_ID 0x4480 /* datasheet claims 0x440X */ 63f76992b00a4111fc4679b0b2d49fe75f05c2b04dGuenter Roeck#define LTM4676_ID_MASK 0xfff0 64c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck 65fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck#define LTC2974_NUM_PAGES 4 663d0d2839937778bd19bf505b38093d829a1cdf69Guenter Roeck#define LTC2978_NUM_PAGES 8 673d0d2839937778bd19bf505b38093d829a1cdf69Guenter Roeck#define LTC3880_NUM_PAGES 2 68fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck#define LTC3883_NUM_PAGES 1 693d0d2839937778bd19bf505b38093d829a1cdf69Guenter Roeck 70c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck/* 71c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck * LTC2978 clears peak data whenever the CLEAR_FAULTS command is executed, which 72c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck * happens pretty much each time chip data is updated. Raw peak data therefore 73c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck * does not provide much value. To be able to provide useful peak data, keep an 74c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck * internal cache of measured peak data, which is only cleared if an explicit 75c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck * "clear peak" command is executed for the sensor in question. 76c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck */ 773d0d2839937778bd19bf505b38093d829a1cdf69Guenter Roeck 78c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeckstruct ltc2978_data { 79c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck enum chips id; 803d0d2839937778bd19bf505b38093d829a1cdf69Guenter Roeck u16 vin_min, vin_max; 81fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck u16 temp_min[LTC2974_NUM_PAGES], temp_max[LTC2974_NUM_PAGES]; 823d0d2839937778bd19bf505b38093d829a1cdf69Guenter Roeck u16 vout_min[LTC2978_NUM_PAGES], vout_max[LTC2978_NUM_PAGES]; 83fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck u16 iout_min[LTC2974_NUM_PAGES], iout_max[LTC2974_NUM_PAGES]; 84fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck u16 iin_max; 853d0d2839937778bd19bf505b38093d829a1cdf69Guenter Roeck u16 temp2_max; 86c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck struct pmbus_driver_info info; 87c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck}; 88c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck 89c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck#define to_ltc2978_data(x) container_of(x, struct ltc2978_data, info) 90c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck 91c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeckstatic inline int lin11_to_val(int data) 92c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck{ 93c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck s16 e = ((s16)data) >> 11; 94c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck s32 m = (((s16)(data << 5)) >> 5); 95c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck 96c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck /* 97c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck * mantissa is 10 bit + sign, exponent adds up to 15 bit. 98c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck * Add 6 bit to exponent for maximum accuracy (10 + 15 + 6 = 31). 99c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck */ 100c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck e += 6; 101c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck return (e < 0 ? m >> -e : m << e); 102c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck} 103c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck 104ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeckstatic int ltc2978_read_word_data_common(struct i2c_client *client, int page, 105ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck int reg) 106c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck{ 107c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 108c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck struct ltc2978_data *data = to_ltc2978_data(info); 109c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck int ret; 110c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck 111c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck switch (reg) { 112c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck case PMBUS_VIRT_READ_VIN_MAX: 113c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_PEAK); 114c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck if (ret >= 0) { 115c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck if (lin11_to_val(ret) > lin11_to_val(data->vin_max)) 116c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck data->vin_max = ret; 117c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck ret = data->vin_max; 118c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck } 119c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck break; 120c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck case PMBUS_VIRT_READ_VOUT_MAX: 121c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck ret = pmbus_read_word_data(client, page, LTC2978_MFR_VOUT_PEAK); 122c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck if (ret >= 0) { 123c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck /* 124c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck * VOUT is 16 bit unsigned with fixed exponent, 125c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck * so we can compare it directly 126c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck */ 127c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck if (ret > data->vout_max[page]) 128c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck data->vout_max[page] = ret; 129c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck ret = data->vout_max[page]; 130c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck } 131c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck break; 132c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck case PMBUS_VIRT_READ_TEMP_MAX: 133c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck ret = pmbus_read_word_data(client, page, 134c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck LTC2978_MFR_TEMPERATURE_PEAK); 135c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck if (ret >= 0) { 1368c958c703ef8804093437959221951eaf0e1e664Guenter Roeck if (lin11_to_val(ret) 1378c958c703ef8804093437959221951eaf0e1e664Guenter Roeck > lin11_to_val(data->temp_max[page])) 1388c958c703ef8804093437959221951eaf0e1e664Guenter Roeck data->temp_max[page] = ret; 1398c958c703ef8804093437959221951eaf0e1e664Guenter Roeck ret = data->temp_max[page]; 140c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck } 141c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck break; 142ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck case PMBUS_VIRT_RESET_VOUT_HISTORY: 143ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck case PMBUS_VIRT_RESET_VIN_HISTORY: 144ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck case PMBUS_VIRT_RESET_TEMP_HISTORY: 145ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck ret = 0; 146ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck break; 147ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck default: 148ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck ret = -ENODATA; 149ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck break; 150ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck } 151ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck return ret; 152ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck} 153ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck 154ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeckstatic int ltc2978_read_word_data(struct i2c_client *client, int page, int reg) 155ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck{ 156ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 157ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck struct ltc2978_data *data = to_ltc2978_data(info); 158ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck int ret; 159ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck 160ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck switch (reg) { 161c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck case PMBUS_VIRT_READ_VIN_MIN: 162c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_MIN); 163c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck if (ret >= 0) { 164c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck if (lin11_to_val(ret) < lin11_to_val(data->vin_min)) 165c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck data->vin_min = ret; 166c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck ret = data->vin_min; 167c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck } 168c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck break; 169c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck case PMBUS_VIRT_READ_VOUT_MIN: 170c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck ret = pmbus_read_word_data(client, page, LTC2978_MFR_VOUT_MIN); 171c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck if (ret >= 0) { 172c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck /* 173c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck * VOUT_MIN is known to not be supported on some lots 174c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck * of LTC2978 revision 1, and will return the maximum 175c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck * possible voltage if read. If VOUT_MAX is valid and 176c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck * lower than the reading of VOUT_MIN, use it instead. 177c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck */ 178c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck if (data->vout_max[page] && ret > data->vout_max[page]) 179c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck ret = data->vout_max[page]; 180c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck if (ret < data->vout_min[page]) 181c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck data->vout_min[page] = ret; 182c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck ret = data->vout_min[page]; 183c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck } 184c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck break; 185c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck case PMBUS_VIRT_READ_TEMP_MIN: 186c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck ret = pmbus_read_word_data(client, page, 187c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck LTC2978_MFR_TEMPERATURE_MIN); 188c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck if (ret >= 0) { 189c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck if (lin11_to_val(ret) 190fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck < lin11_to_val(data->temp_min[page])) 191fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck data->temp_min[page] = ret; 192fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck ret = data->temp_min[page]; 193c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck } 194c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck break; 195ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck case PMBUS_VIRT_READ_IOUT_MAX: 196ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck case PMBUS_VIRT_RESET_IOUT_HISTORY: 197ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck case PMBUS_VIRT_READ_TEMP2_MAX: 198ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck case PMBUS_VIRT_RESET_TEMP2_HISTORY: 199ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck ret = -ENXIO; 200ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck break; 201ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck default: 202ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck ret = ltc2978_read_word_data_common(client, page, reg); 203ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck break; 204ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck } 205ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck return ret; 206ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck} 207ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck 208fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeckstatic int ltc2974_read_word_data(struct i2c_client *client, int page, int reg) 209fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck{ 210fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 211fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck struct ltc2978_data *data = to_ltc2978_data(info); 212fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck int ret; 213fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck 214fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck switch (reg) { 215fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck case PMBUS_VIRT_READ_IOUT_MAX: 216fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck ret = pmbus_read_word_data(client, page, LTC2974_MFR_IOUT_PEAK); 217fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck if (ret >= 0) { 218fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck if (lin11_to_val(ret) 219fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck > lin11_to_val(data->iout_max[page])) 220fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck data->iout_max[page] = ret; 221fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck ret = data->iout_max[page]; 222fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck } 223fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck break; 224fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck case PMBUS_VIRT_READ_IOUT_MIN: 225fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck ret = pmbus_read_word_data(client, page, LTC2974_MFR_IOUT_MIN); 226fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck if (ret >= 0) { 227fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck if (lin11_to_val(ret) 228fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck < lin11_to_val(data->iout_min[page])) 229fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck data->iout_min[page] = ret; 230fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck ret = data->iout_min[page]; 231fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck } 232fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck break; 233fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck case PMBUS_VIRT_RESET_IOUT_HISTORY: 234fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck ret = 0; 235fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck break; 236fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck default: 237fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck ret = ltc2978_read_word_data(client, page, reg); 238fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck break; 239fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck } 240fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck return ret; 241fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck} 242fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck 243ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeckstatic int ltc3880_read_word_data(struct i2c_client *client, int page, int reg) 244ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck{ 245ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 246ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck struct ltc2978_data *data = to_ltc2978_data(info); 247ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck int ret; 248ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck 249ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck switch (reg) { 250ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck case PMBUS_VIRT_READ_IOUT_MAX: 251ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck ret = pmbus_read_word_data(client, page, LTC3880_MFR_IOUT_PEAK); 252ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck if (ret >= 0) { 253ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck if (lin11_to_val(ret) 254ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck > lin11_to_val(data->iout_max[page])) 255ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck data->iout_max[page] = ret; 256ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck ret = data->iout_max[page]; 257ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck } 258ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck break; 259ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck case PMBUS_VIRT_READ_TEMP2_MAX: 260ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck ret = pmbus_read_word_data(client, page, 261ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck LTC3880_MFR_TEMPERATURE2_PEAK); 262ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck if (ret >= 0) { 263dbd712c2272764a536e29ad6841dba74989a39d9Guenter Roeck if (lin11_to_val(ret) > lin11_to_val(data->temp2_max)) 264dbd712c2272764a536e29ad6841dba74989a39d9Guenter Roeck data->temp2_max = ret; 265dbd712c2272764a536e29ad6841dba74989a39d9Guenter Roeck ret = data->temp2_max; 266ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck } 267ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck break; 268ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck case PMBUS_VIRT_READ_VIN_MIN: 269ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck case PMBUS_VIRT_READ_VOUT_MIN: 270ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck case PMBUS_VIRT_READ_TEMP_MIN: 271ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck ret = -ENXIO; 272ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck break; 273ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck case PMBUS_VIRT_RESET_IOUT_HISTORY: 274ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck case PMBUS_VIRT_RESET_TEMP2_HISTORY: 275c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck ret = 0; 276c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck break; 277c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck default: 278ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck ret = ltc2978_read_word_data_common(client, page, reg); 279c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck break; 280c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck } 281c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck return ret; 282c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck} 283c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck 284fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeckstatic int ltc3883_read_word_data(struct i2c_client *client, int page, int reg) 285fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck{ 286fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 287fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck struct ltc2978_data *data = to_ltc2978_data(info); 288fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck int ret; 289fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck 290fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck switch (reg) { 291fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck case PMBUS_VIRT_READ_IIN_MAX: 292fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck ret = pmbus_read_word_data(client, page, LTC3883_MFR_IIN_PEAK); 293fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck if (ret >= 0) { 294fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck if (lin11_to_val(ret) 295fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck > lin11_to_val(data->iin_max)) 296fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck data->iin_max = ret; 297fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck ret = data->iin_max; 298fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck } 299fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck break; 300fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck case PMBUS_VIRT_RESET_IIN_HISTORY: 301fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck ret = 0; 302fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck break; 303fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck default: 304fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck ret = ltc3880_read_word_data(client, page, reg); 305fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck break; 306fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck } 307fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck return ret; 308fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck} 309fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck 310ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeckstatic int ltc2978_clear_peaks(struct i2c_client *client, int page, 311ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck enum chips id) 312ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck{ 313ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck int ret; 314ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck 315fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck if (id == ltc3880 || id == ltc3883) 316ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck ret = pmbus_write_byte(client, 0, LTC3880_MFR_CLEAR_PEAKS); 317fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck else 318fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck ret = pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS); 319ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck 320ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck return ret; 321ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck} 322ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck 323c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeckstatic int ltc2978_write_word_data(struct i2c_client *client, int page, 324c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck int reg, u16 word) 325c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck{ 326c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 327c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck struct ltc2978_data *data = to_ltc2978_data(info); 328c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck int ret; 329c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck 330c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck switch (reg) { 331fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck case PMBUS_VIRT_RESET_IIN_HISTORY: 332fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck data->iin_max = 0x7c00; 333fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck ret = ltc2978_clear_peaks(client, page, data->id); 334fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck break; 335ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck case PMBUS_VIRT_RESET_IOUT_HISTORY: 336dbd712c2272764a536e29ad6841dba74989a39d9Guenter Roeck data->iout_max[page] = 0x7c00; 337fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck data->iout_min[page] = 0xfbff; 338ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck ret = ltc2978_clear_peaks(client, page, data->id); 339ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck break; 340ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck case PMBUS_VIRT_RESET_TEMP2_HISTORY: 341dbd712c2272764a536e29ad6841dba74989a39d9Guenter Roeck data->temp2_max = 0x7c00; 342ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck ret = ltc2978_clear_peaks(client, page, data->id); 343ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck break; 344c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck case PMBUS_VIRT_RESET_VOUT_HISTORY: 345c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck data->vout_min[page] = 0xffff; 346c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck data->vout_max[page] = 0; 347ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck ret = ltc2978_clear_peaks(client, page, data->id); 348c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck break; 349c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck case PMBUS_VIRT_RESET_VIN_HISTORY: 350c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck data->vin_min = 0x7bff; 351dbd712c2272764a536e29ad6841dba74989a39d9Guenter Roeck data->vin_max = 0x7c00; 352ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck ret = ltc2978_clear_peaks(client, page, data->id); 353c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck break; 354c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck case PMBUS_VIRT_RESET_TEMP_HISTORY: 355fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck data->temp_min[page] = 0x7bff; 3568c958c703ef8804093437959221951eaf0e1e664Guenter Roeck data->temp_max[page] = 0x7c00; 357ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck ret = ltc2978_clear_peaks(client, page, data->id); 358c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck break; 359c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck default: 360c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck ret = -ENODATA; 361c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck break; 362c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck } 363c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck return ret; 364c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck} 365c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck 366c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeckstatic const struct i2c_device_id ltc2978_id[] = { 367fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck {"ltc2974", ltc2974}, 368c24c407e963e73d3ad18b9bc0af32cf23f37a7b0Guenter Roeck {"ltc2977", ltc2977}, 369c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck {"ltc2978", ltc2978}, 370ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck {"ltc3880", ltc3880}, 371fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck {"ltc3883", ltc3883}, 372f76992b00a4111fc4679b0b2d49fe75f05c2b04dGuenter Roeck {"ltm4676", ltm4676}, 373c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck {} 374c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck}; 375c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter RoeckMODULE_DEVICE_TABLE(i2c, ltc2978_id); 376c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck 377c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeckstatic int ltc2978_probe(struct i2c_client *client, 378c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck const struct i2c_device_id *id) 379c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck{ 3808b313ca7f1b98263ce22519b25a9c2a362eeb898Guenter Roeck int chip_id, i; 381c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck struct ltc2978_data *data; 382c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck struct pmbus_driver_info *info; 383c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck 384c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck if (!i2c_check_functionality(client->adapter, 385c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck I2C_FUNC_SMBUS_READ_WORD_DATA)) 386c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck return -ENODEV; 387c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck 3888b313ca7f1b98263ce22519b25a9c2a362eeb898Guenter Roeck data = devm_kzalloc(&client->dev, sizeof(struct ltc2978_data), 3898b313ca7f1b98263ce22519b25a9c2a362eeb898Guenter Roeck GFP_KERNEL); 390c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck if (!data) 391c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck return -ENOMEM; 392c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck 393c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck chip_id = i2c_smbus_read_word_data(client, LTC2978_MFR_SPECIAL_ID); 3948b313ca7f1b98263ce22519b25a9c2a362eeb898Guenter Roeck if (chip_id < 0) 3958b313ca7f1b98263ce22519b25a9c2a362eeb898Guenter Roeck return chip_id; 396c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck 397a2e151074366487dcde943fdc08d88acfe476f9dGuenter Roeck if (chip_id == LTC2974_ID_REV1 || chip_id == LTC2974_ID_REV2) { 398fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck data->id = ltc2974; 399c24c407e963e73d3ad18b9bc0af32cf23f37a7b0Guenter Roeck } else if (chip_id == LTC2977_ID) { 400c24c407e963e73d3ad18b9bc0af32cf23f37a7b0Guenter Roeck data->id = ltc2977; 4013f08d7f49f8365d5c9050522ee733951a503e955Guenter Roeck } else if (chip_id == LTC2978_ID_REV1 || chip_id == LTC2978_ID_REV2 || 4023f08d7f49f8365d5c9050522ee733951a503e955Guenter Roeck chip_id == LTC2978A_ID) { 403c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck data->id = ltc2978; 404ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck } else if ((chip_id & LTC3880_ID_MASK) == LTC3880_ID) { 405ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck data->id = ltc3880; 406fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck } else if ((chip_id & LTC3883_ID_MASK) == LTC3883_ID) { 407fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck data->id = ltc3883; 408f76992b00a4111fc4679b0b2d49fe75f05c2b04dGuenter Roeck } else if ((chip_id & LTM4676_ID_MASK) == LTM4676_ID) { 409f76992b00a4111fc4679b0b2d49fe75f05c2b04dGuenter Roeck data->id = ltm4676; 410c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck } else { 411c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck dev_err(&client->dev, "Unsupported chip ID 0x%x\n", chip_id); 4128b313ca7f1b98263ce22519b25a9c2a362eeb898Guenter Roeck return -ENODEV; 413c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck } 414c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck if (data->id != id->driver_data) 415c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck dev_warn(&client->dev, 416c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck "Device mismatch: Configured %s, detected %s\n", 417c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck id->name, 418c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck ltc2978_id[data->id].name); 419c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck 420c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck info = &data->info; 421c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck info->write_word_data = ltc2978_write_word_data; 422c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck 423c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck data->vin_min = 0x7bff; 424dbd712c2272764a536e29ad6841dba74989a39d9Guenter Roeck data->vin_max = 0x7c00; 4253d0d2839937778bd19bf505b38093d829a1cdf69Guenter Roeck for (i = 0; i < ARRAY_SIZE(data->vout_min); i++) 4263d0d2839937778bd19bf505b38093d829a1cdf69Guenter Roeck data->vout_min[i] = 0xffff; 427fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck for (i = 0; i < ARRAY_SIZE(data->iout_min); i++) 428fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck data->iout_min[i] = 0xfbff; 429fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck for (i = 0; i < ARRAY_SIZE(data->iout_max); i++) 430fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck data->iout_max[i] = 0x7c00; 431fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck for (i = 0; i < ARRAY_SIZE(data->temp_min); i++) 432fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck data->temp_min[i] = 0x7bff; 4338c958c703ef8804093437959221951eaf0e1e664Guenter Roeck for (i = 0; i < ARRAY_SIZE(data->temp_max); i++) 4348c958c703ef8804093437959221951eaf0e1e664Guenter Roeck data->temp_max[i] = 0x7c00; 435dbd712c2272764a536e29ad6841dba74989a39d9Guenter Roeck data->temp2_max = 0x7c00; 436c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck 437f366fccd0809f13ba20d64cae3c83f7338c88af7Guenter Roeck switch (data->id) { 438fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck case ltc2974: 439fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck info->read_word_data = ltc2974_read_word_data; 440fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck info->pages = LTC2974_NUM_PAGES; 441fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT 442fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck | PMBUS_HAVE_TEMP2; 443fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck for (i = 0; i < info->pages; i++) { 444fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck info->func[i] |= PMBUS_HAVE_VOUT 445fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_POUT 446fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP 447fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT; 448fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck } 449fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck break; 450c24c407e963e73d3ad18b9bc0af32cf23f37a7b0Guenter Roeck case ltc2977: 451c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck case ltc2978: 452ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck info->read_word_data = ltc2978_read_word_data; 4533d0d2839937778bd19bf505b38093d829a1cdf69Guenter Roeck info->pages = LTC2978_NUM_PAGES; 454c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT 455c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 456c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; 4573d0d2839937778bd19bf505b38093d829a1cdf69Guenter Roeck for (i = 1; i < LTC2978_NUM_PAGES; i++) { 458c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck info->func[i] = PMBUS_HAVE_VOUT 459c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck | PMBUS_HAVE_STATUS_VOUT; 460c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck } 461c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck break; 462ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck case ltc3880: 463f76992b00a4111fc4679b0b2d49fe75f05c2b04dGuenter Roeck case ltm4676: 464ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck info->read_word_data = ltc3880_read_word_data; 4653d0d2839937778bd19bf505b38093d829a1cdf69Guenter Roeck info->pages = LTC3880_NUM_PAGES; 466ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN 467ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck | PMBUS_HAVE_STATUS_INPUT 468ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 469ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT 470ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP 471ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP; 472ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck info->func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 473ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT 474ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck | PMBUS_HAVE_POUT 475ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; 476fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck break; 477fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck case ltc3883: 478fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck info->read_word_data = ltc3883_read_word_data; 479fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck info->pages = LTC3883_NUM_PAGES; 480fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN 481fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck | PMBUS_HAVE_STATUS_INPUT 482fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 483fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT 484fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP 485fd9175d2f603509e7ddf14e7b60633f6e88fb0e7Guenter Roeck | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP; 486ddfb41ca2a33c9f5053126324597510974724a1fGuenter Roeck break; 487c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck default: 4888b313ca7f1b98263ce22519b25a9c2a362eeb898Guenter Roeck return -ENODEV; 489c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck } 4908b313ca7f1b98263ce22519b25a9c2a362eeb898Guenter Roeck return pmbus_do_probe(client, id, info); 491c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck} 492c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck 493c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck/* This is the driver that will be inserted */ 494c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeckstatic struct i2c_driver ltc2978_driver = { 495c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck .driver = { 496c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck .name = "ltc2978", 497c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck }, 498c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck .probe = ltc2978_probe, 499dd285ad7373bf5d21cceacb3b7a5eb8b72d37085Guenter Roeck .remove = pmbus_do_remove, 500c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck .id_table = ltc2978_id, 501c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck}; 502c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck 503f0967eea80ec2a19a4fe1ad27e3ff1b22c79a3c7Axel Linmodule_i2c_driver(ltc2978_driver); 504c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter Roeck 505c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter RoeckMODULE_AUTHOR("Guenter Roeck"); 506f76992b00a4111fc4679b0b2d49fe75f05c2b04dGuenter RoeckMODULE_DESCRIPTION("PMBus driver for LTC2974, LTC2978, LTC3880, LTC3883, and LTM4676"); 507c3ff9a674c2313d4f28e38d384b18b561b313eb7Guenter RoeckMODULE_LICENSE("GPL"); 508