1 /* 2 * Hardware monitoring driver for LTC2978 3 * 4 * Copyright (c) 2011 Ericsson AB. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 */ 20 21 #include <linux/kernel.h> 22 #include <linux/module.h> 23 #include <linux/init.h> 24 #include <linux/err.h> 25 #include <linux/slab.h> 26 #include <linux/i2c.h> 27 #include "pmbus.h" 28 29 enum chips { ltc2978 }; 30 31 #define LTC2978_MFR_VOUT_PEAK 0xdd 32 #define LTC2978_MFR_VIN_PEAK 0xde 33 #define LTC2978_MFR_TEMPERATURE_PEAK 0xdf 34 #define LTC2978_MFR_SPECIAL_ID 0xe7 35 36 #define LTC2978_MFR_VOUT_MIN 0xfb 37 #define LTC2978_MFR_VIN_MIN 0xfc 38 #define LTC2978_MFR_TEMPERATURE_MIN 0xfd 39 40 #define LTC2978_ID_REV1 0x0121 41 #define LTC2978_ID_REV2 0x0122 42 43 /* 44 * LTC2978 clears peak data whenever the CLEAR_FAULTS command is executed, which 45 * happens pretty much each time chip data is updated. Raw peak data therefore 46 * does not provide much value. To be able to provide useful peak data, keep an 47 * internal cache of measured peak data, which is only cleared if an explicit 48 * "clear peak" command is executed for the sensor in question. 49 */ 50 struct ltc2978_data { 51 enum chips id; 52 int vin_min, vin_max; 53 int temp_min, temp_max; 54 int vout_min[8], vout_max[8]; 55 struct pmbus_driver_info info; 56 }; 57 58 #define to_ltc2978_data(x) container_of(x, struct ltc2978_data, info) 59 60 static inline int lin11_to_val(int data) 61 { 62 s16 e = ((s16)data) >> 11; 63 s32 m = (((s16)(data << 5)) >> 5); 64 65 /* 66 * mantissa is 10 bit + sign, exponent adds up to 15 bit. 67 * Add 6 bit to exponent for maximum accuracy (10 + 15 + 6 = 31). 68 */ 69 e += 6; 70 return (e < 0 ? m >> -e : m << e); 71 } 72 73 static int ltc2978_read_word_data(struct i2c_client *client, int page, int reg) 74 { 75 const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 76 struct ltc2978_data *data = to_ltc2978_data(info); 77 int ret; 78 79 switch (reg) { 80 case PMBUS_VIRT_READ_VIN_MAX: 81 ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_PEAK); 82 if (ret >= 0) { 83 if (lin11_to_val(ret) > lin11_to_val(data->vin_max)) 84 data->vin_max = ret; 85 ret = data->vin_max; 86 } 87 break; 88 case PMBUS_VIRT_READ_VOUT_MAX: 89 ret = pmbus_read_word_data(client, page, LTC2978_MFR_VOUT_PEAK); 90 if (ret >= 0) { 91 /* 92 * VOUT is 16 bit unsigned with fixed exponent, 93 * so we can compare it directly 94 */ 95 if (ret > data->vout_max[page]) 96 data->vout_max[page] = ret; 97 ret = data->vout_max[page]; 98 } 99 break; 100 case PMBUS_VIRT_READ_TEMP_MAX: 101 ret = pmbus_read_word_data(client, page, 102 LTC2978_MFR_TEMPERATURE_PEAK); 103 if (ret >= 0) { 104 if (lin11_to_val(ret) > lin11_to_val(data->temp_max)) 105 data->temp_max = ret; 106 ret = data->temp_max; 107 } 108 break; 109 case PMBUS_VIRT_READ_VIN_MIN: 110 ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_MIN); 111 if (ret >= 0) { 112 if (lin11_to_val(ret) < lin11_to_val(data->vin_min)) 113 data->vin_min = ret; 114 ret = data->vin_min; 115 } 116 break; 117 case PMBUS_VIRT_READ_VOUT_MIN: 118 ret = pmbus_read_word_data(client, page, LTC2978_MFR_VOUT_MIN); 119 if (ret >= 0) { 120 /* 121 * VOUT_MIN is known to not be supported on some lots 122 * of LTC2978 revision 1, and will return the maximum 123 * possible voltage if read. If VOUT_MAX is valid and 124 * lower than the reading of VOUT_MIN, use it instead. 125 */ 126 if (data->vout_max[page] && ret > data->vout_max[page]) 127 ret = data->vout_max[page]; 128 if (ret < data->vout_min[page]) 129 data->vout_min[page] = ret; 130 ret = data->vout_min[page]; 131 } 132 break; 133 case PMBUS_VIRT_READ_TEMP_MIN: 134 ret = pmbus_read_word_data(client, page, 135 LTC2978_MFR_TEMPERATURE_MIN); 136 if (ret >= 0) { 137 if (lin11_to_val(ret) 138 < lin11_to_val(data->temp_min)) 139 data->temp_min = ret; 140 ret = data->temp_min; 141 } 142 break; 143 case PMBUS_VIRT_RESET_VOUT_HISTORY: 144 case PMBUS_VIRT_RESET_VIN_HISTORY: 145 case PMBUS_VIRT_RESET_TEMP_HISTORY: 146 ret = 0; 147 break; 148 default: 149 ret = -ENODATA; 150 break; 151 } 152 return ret; 153 } 154 155 static int ltc2978_write_word_data(struct i2c_client *client, int page, 156 int reg, u16 word) 157 { 158 const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 159 struct ltc2978_data *data = to_ltc2978_data(info); 160 int ret; 161 162 switch (reg) { 163 case PMBUS_VIRT_RESET_VOUT_HISTORY: 164 data->vout_min[page] = 0xffff; 165 data->vout_max[page] = 0; 166 ret = pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS); 167 break; 168 case PMBUS_VIRT_RESET_VIN_HISTORY: 169 data->vin_min = 0x7bff; 170 data->vin_max = 0; 171 ret = pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS); 172 break; 173 case PMBUS_VIRT_RESET_TEMP_HISTORY: 174 data->temp_min = 0x7bff; 175 data->temp_max = 0x7fff; 176 ret = pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS); 177 break; 178 default: 179 ret = -ENODATA; 180 break; 181 } 182 return ret; 183 } 184 185 static const struct i2c_device_id ltc2978_id[] = { 186 {"ltc2978", ltc2978}, 187 {} 188 }; 189 MODULE_DEVICE_TABLE(i2c, ltc2978_id); 190 191 static int ltc2978_probe(struct i2c_client *client, 192 const struct i2c_device_id *id) 193 { 194 int chip_id, ret, i; 195 struct ltc2978_data *data; 196 struct pmbus_driver_info *info; 197 198 if (!i2c_check_functionality(client->adapter, 199 I2C_FUNC_SMBUS_READ_WORD_DATA)) 200 return -ENODEV; 201 202 data = kzalloc(sizeof(struct ltc2978_data), GFP_KERNEL); 203 if (!data) 204 return -ENOMEM; 205 206 chip_id = i2c_smbus_read_word_data(client, LTC2978_MFR_SPECIAL_ID); 207 if (chip_id < 0) { 208 ret = chip_id; 209 goto err_mem; 210 } 211 212 if (chip_id == LTC2978_ID_REV1 || chip_id == LTC2978_ID_REV2) { 213 data->id = ltc2978; 214 } else { 215 dev_err(&client->dev, "Unsupported chip ID 0x%x\n", chip_id); 216 ret = -ENODEV; 217 goto err_mem; 218 } 219 if (data->id != id->driver_data) 220 dev_warn(&client->dev, 221 "Device mismatch: Configured %s, detected %s\n", 222 id->name, 223 ltc2978_id[data->id].name); 224 225 info = &data->info; 226 info->read_word_data = ltc2978_read_word_data; 227 info->write_word_data = ltc2978_write_word_data; 228 229 data->vout_min[0] = 0xffff; 230 data->vin_min = 0x7bff; 231 data->temp_min = 0x7bff; 232 data->temp_max = 0x7fff; 233 234 switch (id->driver_data) { 235 case ltc2978: 236 info->pages = 8; 237 info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT 238 | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 239 | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; 240 for (i = 1; i < 8; i++) { 241 info->func[i] = PMBUS_HAVE_VOUT 242 | PMBUS_HAVE_STATUS_VOUT; 243 data->vout_min[i] = 0xffff; 244 } 245 break; 246 default: 247 ret = -ENODEV; 248 goto err_mem; 249 } 250 251 ret = pmbus_do_probe(client, id, info); 252 if (ret) 253 goto err_mem; 254 return 0; 255 256 err_mem: 257 kfree(data); 258 return ret; 259 } 260 261 static int ltc2978_remove(struct i2c_client *client) 262 { 263 const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 264 const struct ltc2978_data *data = to_ltc2978_data(info); 265 266 pmbus_do_remove(client); 267 kfree(data); 268 return 0; 269 } 270 271 /* This is the driver that will be inserted */ 272 static struct i2c_driver ltc2978_driver = { 273 .driver = { 274 .name = "ltc2978", 275 }, 276 .probe = ltc2978_probe, 277 .remove = ltc2978_remove, 278 .id_table = ltc2978_id, 279 }; 280 281 static int __init ltc2978_init(void) 282 { 283 return i2c_add_driver(<c2978_driver); 284 } 285 286 static void __exit ltc2978_exit(void) 287 { 288 i2c_del_driver(<c2978_driver); 289 } 290 291 MODULE_AUTHOR("Guenter Roeck"); 292 MODULE_DESCRIPTION("PMBus driver for LTC2978"); 293 MODULE_LICENSE("GPL"); 294 module_init(ltc2978_init); 295 module_exit(ltc2978_exit); 296