1 /* 2 * Hardware monitoring driver for LM25056 / LM25066 / LM5064 / LM5066 3 * 4 * Copyright (c) 2011 Ericsson AB. 5 * Copyright (c) 2013 Guenter Roeck 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 */ 21 22 #include <linux/kernel.h> 23 #include <linux/module.h> 24 #include <linux/init.h> 25 #include <linux/err.h> 26 #include <linux/slab.h> 27 #include <linux/i2c.h> 28 #include "pmbus.h" 29 30 enum chips { lm25056, lm25066, lm5064, lm5066 }; 31 32 #define LM25066_READ_VAUX 0xd0 33 #define LM25066_MFR_READ_IIN 0xd1 34 #define LM25066_MFR_READ_PIN 0xd2 35 #define LM25066_MFR_IIN_OC_WARN_LIMIT 0xd3 36 #define LM25066_MFR_PIN_OP_WARN_LIMIT 0xd4 37 #define LM25066_READ_PIN_PEAK 0xd5 38 #define LM25066_CLEAR_PIN_PEAK 0xd6 39 #define LM25066_DEVICE_SETUP 0xd9 40 #define LM25066_READ_AVG_VIN 0xdc 41 #define LM25066_READ_AVG_VOUT 0xdd 42 #define LM25066_READ_AVG_IIN 0xde 43 #define LM25066_READ_AVG_PIN 0xdf 44 45 #define LM25066_DEV_SETUP_CL (1 << 4) /* Current limit */ 46 47 /* LM25056 only */ 48 49 #define LM25056_VAUX_OV_WARN_LIMIT 0xe3 50 #define LM25056_VAUX_UV_WARN_LIMIT 0xe4 51 52 #define LM25056_MFR_STS_VAUX_OV_WARN (1 << 1) 53 #define LM25056_MFR_STS_VAUX_UV_WARN (1 << 0) 54 55 struct __coeff { 56 short m, b, R; 57 }; 58 59 #define PSC_CURRENT_IN_L (PSC_NUM_CLASSES) 60 #define PSC_POWER_L (PSC_NUM_CLASSES + 1) 61 62 static struct __coeff lm25066_coeff[4][PSC_NUM_CLASSES + 2] = { 63 [lm25056] = { 64 [PSC_VOLTAGE_IN] = { 65 .m = 16296, 66 .R = -2, 67 }, 68 [PSC_CURRENT_IN] = { 69 .m = 13797, 70 .R = -2, 71 }, 72 [PSC_CURRENT_IN_L] = { 73 .m = 6726, 74 .R = -2, 75 }, 76 [PSC_POWER] = { 77 .m = 5501, 78 .R = -3, 79 }, 80 [PSC_POWER_L] = { 81 .m = 26882, 82 .R = -4, 83 }, 84 [PSC_TEMPERATURE] = { 85 .m = 1580, 86 .b = -14500, 87 .R = -2, 88 }, 89 }, 90 [lm25066] = { 91 [PSC_VOLTAGE_IN] = { 92 .m = 22070, 93 .R = -2, 94 }, 95 [PSC_VOLTAGE_OUT] = { 96 .m = 22070, 97 .R = -2, 98 }, 99 [PSC_CURRENT_IN] = { 100 .m = 13661, 101 .R = -2, 102 }, 103 [PSC_CURRENT_IN_L] = { 104 .m = 6852, 105 .R = -2, 106 }, 107 [PSC_POWER] = { 108 .m = 736, 109 .R = -2, 110 }, 111 [PSC_POWER_L] = { 112 .m = 369, 113 .R = -2, 114 }, 115 [PSC_TEMPERATURE] = { 116 .m = 16, 117 }, 118 }, 119 [lm5064] = { 120 [PSC_VOLTAGE_IN] = { 121 .m = 4611, 122 .R = -2, 123 }, 124 [PSC_VOLTAGE_OUT] = { 125 .m = 4621, 126 .R = -2, 127 }, 128 [PSC_CURRENT_IN] = { 129 .m = 10742, 130 .R = -2, 131 }, 132 [PSC_CURRENT_IN_L] = { 133 .m = 5456, 134 .R = -2, 135 }, 136 [PSC_POWER] = { 137 .m = 1204, 138 .R = -3, 139 }, 140 [PSC_POWER_L] = { 141 .m = 612, 142 .R = -3, 143 }, 144 [PSC_TEMPERATURE] = { 145 .m = 16, 146 }, 147 }, 148 [lm5066] = { 149 [PSC_VOLTAGE_IN] = { 150 .m = 4587, 151 .R = -2, 152 }, 153 [PSC_VOLTAGE_OUT] = { 154 .m = 4587, 155 .R = -2, 156 }, 157 [PSC_CURRENT_IN] = { 158 .m = 10753, 159 .R = -2, 160 }, 161 [PSC_CURRENT_IN_L] = { 162 .m = 5405, 163 .R = -2, 164 }, 165 [PSC_POWER] = { 166 .m = 1204, 167 .R = -3, 168 }, 169 [PSC_POWER_L] = { 170 .m = 605, 171 .R = -3, 172 }, 173 [PSC_TEMPERATURE] = { 174 .m = 16, 175 }, 176 }, 177 }; 178 179 struct lm25066_data { 180 int id; 181 struct pmbus_driver_info info; 182 }; 183 184 #define to_lm25066_data(x) container_of(x, struct lm25066_data, info) 185 186 static int lm25066_read_word_data(struct i2c_client *client, int page, int reg) 187 { 188 const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 189 const struct lm25066_data *data = to_lm25066_data(info); 190 int ret; 191 192 switch (reg) { 193 case PMBUS_VIRT_READ_VMON: 194 ret = pmbus_read_word_data(client, 0, LM25066_READ_VAUX); 195 if (ret < 0) 196 break; 197 /* Adjust returned value to match VIN coefficients */ 198 switch (data->id) { 199 case lm25056: 200 /* VIN: 6.14 mV VAUX: 293 uV LSB */ 201 ret = DIV_ROUND_CLOSEST(ret * 293, 6140); 202 break; 203 case lm25066: 204 /* VIN: 4.54 mV VAUX: 283.2 uV LSB */ 205 ret = DIV_ROUND_CLOSEST(ret * 2832, 45400); 206 break; 207 case lm5064: 208 /* VIN: 4.53 mV VAUX: 700 uV LSB */ 209 ret = DIV_ROUND_CLOSEST(ret * 70, 453); 210 break; 211 case lm5066: 212 /* VIN: 2.18 mV VAUX: 725 uV LSB */ 213 ret = DIV_ROUND_CLOSEST(ret * 725, 2180); 214 break; 215 } 216 break; 217 case PMBUS_READ_IIN: 218 ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_IIN); 219 break; 220 case PMBUS_READ_PIN: 221 ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_PIN); 222 break; 223 case PMBUS_IIN_OC_WARN_LIMIT: 224 ret = pmbus_read_word_data(client, 0, 225 LM25066_MFR_IIN_OC_WARN_LIMIT); 226 break; 227 case PMBUS_PIN_OP_WARN_LIMIT: 228 ret = pmbus_read_word_data(client, 0, 229 LM25066_MFR_PIN_OP_WARN_LIMIT); 230 break; 231 case PMBUS_VIRT_READ_VIN_AVG: 232 ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VIN); 233 break; 234 case PMBUS_VIRT_READ_VOUT_AVG: 235 ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VOUT); 236 break; 237 case PMBUS_VIRT_READ_IIN_AVG: 238 ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_IIN); 239 break; 240 case PMBUS_VIRT_READ_PIN_AVG: 241 ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_PIN); 242 break; 243 case PMBUS_VIRT_READ_PIN_MAX: 244 ret = pmbus_read_word_data(client, 0, LM25066_READ_PIN_PEAK); 245 break; 246 case PMBUS_VIRT_RESET_PIN_HISTORY: 247 ret = 0; 248 break; 249 default: 250 ret = -ENODATA; 251 break; 252 } 253 return ret; 254 } 255 256 static int lm25056_read_word_data(struct i2c_client *client, int page, int reg) 257 { 258 int ret; 259 260 switch (reg) { 261 case PMBUS_VIRT_VMON_UV_WARN_LIMIT: 262 ret = pmbus_read_word_data(client, 0, 263 LM25056_VAUX_UV_WARN_LIMIT); 264 if (ret < 0) 265 break; 266 /* Adjust returned value to match VIN coefficients */ 267 ret = DIV_ROUND_CLOSEST(ret * 293, 6140); 268 break; 269 case PMBUS_VIRT_VMON_OV_WARN_LIMIT: 270 ret = pmbus_read_word_data(client, 0, 271 LM25056_VAUX_OV_WARN_LIMIT); 272 if (ret < 0) 273 break; 274 /* Adjust returned value to match VIN coefficients */ 275 ret = DIV_ROUND_CLOSEST(ret * 293, 6140); 276 break; 277 default: 278 ret = lm25066_read_word_data(client, page, reg); 279 break; 280 } 281 return ret; 282 } 283 284 static int lm25056_read_byte_data(struct i2c_client *client, int page, int reg) 285 { 286 int ret, s; 287 288 switch (reg) { 289 case PMBUS_VIRT_STATUS_VMON: 290 ret = pmbus_read_byte_data(client, 0, 291 PMBUS_STATUS_MFR_SPECIFIC); 292 if (ret < 0) 293 break; 294 s = 0; 295 if (ret & LM25056_MFR_STS_VAUX_UV_WARN) 296 s |= PB_VOLTAGE_UV_WARNING; 297 if (ret & LM25056_MFR_STS_VAUX_OV_WARN) 298 s |= PB_VOLTAGE_OV_WARNING; 299 ret = s; 300 break; 301 default: 302 ret = -ENODATA; 303 break; 304 } 305 return ret; 306 } 307 308 static int lm25066_write_word_data(struct i2c_client *client, int page, int reg, 309 u16 word) 310 { 311 int ret; 312 313 switch (reg) { 314 case PMBUS_VOUT_UV_WARN_LIMIT: 315 case PMBUS_OT_FAULT_LIMIT: 316 case PMBUS_OT_WARN_LIMIT: 317 case PMBUS_VIN_UV_WARN_LIMIT: 318 case PMBUS_VIN_OV_WARN_LIMIT: 319 word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff); 320 ret = pmbus_write_word_data(client, 0, reg, word); 321 pmbus_clear_cache(client); 322 break; 323 case PMBUS_IIN_OC_WARN_LIMIT: 324 word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff); 325 ret = pmbus_write_word_data(client, 0, 326 LM25066_MFR_IIN_OC_WARN_LIMIT, 327 word); 328 pmbus_clear_cache(client); 329 break; 330 case PMBUS_PIN_OP_WARN_LIMIT: 331 word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff); 332 ret = pmbus_write_word_data(client, 0, 333 LM25066_MFR_PIN_OP_WARN_LIMIT, 334 word); 335 pmbus_clear_cache(client); 336 break; 337 case PMBUS_VIRT_VMON_UV_WARN_LIMIT: 338 /* Adjust from VIN coefficients (for LM25056) */ 339 word = DIV_ROUND_CLOSEST((int)word * 6140, 293); 340 word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff); 341 ret = pmbus_write_word_data(client, 0, 342 LM25056_VAUX_UV_WARN_LIMIT, word); 343 pmbus_clear_cache(client); 344 break; 345 case PMBUS_VIRT_VMON_OV_WARN_LIMIT: 346 /* Adjust from VIN coefficients (for LM25056) */ 347 word = DIV_ROUND_CLOSEST((int)word * 6140, 293); 348 word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff); 349 ret = pmbus_write_word_data(client, 0, 350 LM25056_VAUX_OV_WARN_LIMIT, word); 351 pmbus_clear_cache(client); 352 break; 353 case PMBUS_VIRT_RESET_PIN_HISTORY: 354 ret = pmbus_write_byte(client, 0, LM25066_CLEAR_PIN_PEAK); 355 break; 356 default: 357 ret = -ENODATA; 358 break; 359 } 360 return ret; 361 } 362 363 static int lm25066_probe(struct i2c_client *client, 364 const struct i2c_device_id *id) 365 { 366 int config; 367 struct lm25066_data *data; 368 struct pmbus_driver_info *info; 369 struct __coeff *coeff; 370 371 if (!i2c_check_functionality(client->adapter, 372 I2C_FUNC_SMBUS_READ_BYTE_DATA)) 373 return -ENODEV; 374 375 data = devm_kzalloc(&client->dev, sizeof(struct lm25066_data), 376 GFP_KERNEL); 377 if (!data) 378 return -ENOMEM; 379 380 config = i2c_smbus_read_byte_data(client, LM25066_DEVICE_SETUP); 381 if (config < 0) 382 return config; 383 384 data->id = id->driver_data; 385 info = &data->info; 386 387 info->pages = 1; 388 info->format[PSC_VOLTAGE_IN] = direct; 389 info->format[PSC_VOLTAGE_OUT] = direct; 390 info->format[PSC_CURRENT_IN] = direct; 391 info->format[PSC_TEMPERATURE] = direct; 392 info->format[PSC_POWER] = direct; 393 394 info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VMON 395 | PMBUS_HAVE_PIN | PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_INPUT 396 | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; 397 398 if (data->id == lm25056) { 399 info->func[0] |= PMBUS_HAVE_STATUS_VMON; 400 info->read_word_data = lm25056_read_word_data; 401 info->read_byte_data = lm25056_read_byte_data; 402 } else { 403 info->func[0] |= PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; 404 info->read_word_data = lm25066_read_word_data; 405 } 406 info->write_word_data = lm25066_write_word_data; 407 408 coeff = &lm25066_coeff[data->id][0]; 409 info->m[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].m; 410 info->b[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].b; 411 info->R[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].R; 412 info->m[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].m; 413 info->b[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].b; 414 info->R[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].R; 415 info->m[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].m; 416 info->b[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].b; 417 info->R[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].R; 418 info->b[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].b; 419 info->R[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].R; 420 info->b[PSC_POWER] = coeff[PSC_POWER].b; 421 info->R[PSC_POWER] = coeff[PSC_POWER].R; 422 if (config & LM25066_DEV_SETUP_CL) { 423 info->m[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN_L].m; 424 info->m[PSC_POWER] = coeff[PSC_POWER_L].m; 425 } else { 426 info->m[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].m; 427 info->m[PSC_POWER] = coeff[PSC_POWER].m; 428 } 429 430 return pmbus_do_probe(client, id, info); 431 } 432 433 static const struct i2c_device_id lm25066_id[] = { 434 {"lm25056", lm25056}, 435 {"lm25066", lm25066}, 436 {"lm5064", lm5064}, 437 {"lm5066", lm5066}, 438 { } 439 }; 440 441 MODULE_DEVICE_TABLE(i2c, lm25066_id); 442 443 /* This is the driver that will be inserted */ 444 static struct i2c_driver lm25066_driver = { 445 .driver = { 446 .name = "lm25066", 447 }, 448 .probe = lm25066_probe, 449 .remove = pmbus_do_remove, 450 .id_table = lm25066_id, 451 }; 452 453 module_i2c_driver(lm25066_driver); 454 455 MODULE_AUTHOR("Guenter Roeck"); 456 MODULE_DESCRIPTION("PMBus driver for LM25056/LM25066/LM5064/LM5066"); 457 MODULE_LICENSE("GPL"); 458