1/* 2 * Hardware monitoring driver for Maxim MAX34440/MAX34441 3 * 4 * Copyright (c) 2011 Ericsson AB. 5 * Copyright (c) 2012 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/i2c.h> 27#include "pmbus.h" 28 29enum chips { max34440, max34441, max34446, max34460, max34461 }; 30 31#define MAX34440_MFR_VOUT_PEAK 0xd4 32#define MAX34440_MFR_IOUT_PEAK 0xd5 33#define MAX34440_MFR_TEMPERATURE_PEAK 0xd6 34#define MAX34440_MFR_VOUT_MIN 0xd7 35 36#define MAX34446_MFR_POUT_PEAK 0xe0 37#define MAX34446_MFR_POUT_AVG 0xe1 38#define MAX34446_MFR_IOUT_AVG 0xe2 39#define MAX34446_MFR_TEMPERATURE_AVG 0xe3 40 41#define MAX34440_STATUS_OC_WARN (1 << 0) 42#define MAX34440_STATUS_OC_FAULT (1 << 1) 43#define MAX34440_STATUS_OT_FAULT (1 << 5) 44#define MAX34440_STATUS_OT_WARN (1 << 6) 45 46struct max34440_data { 47 int id; 48 struct pmbus_driver_info info; 49}; 50 51#define to_max34440_data(x) container_of(x, struct max34440_data, info) 52 53static int max34440_read_word_data(struct i2c_client *client, int page, int reg) 54{ 55 int ret; 56 const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 57 const struct max34440_data *data = to_max34440_data(info); 58 59 switch (reg) { 60 case PMBUS_VIRT_READ_VOUT_MIN: 61 ret = pmbus_read_word_data(client, page, 62 MAX34440_MFR_VOUT_MIN); 63 break; 64 case PMBUS_VIRT_READ_VOUT_MAX: 65 ret = pmbus_read_word_data(client, page, 66 MAX34440_MFR_VOUT_PEAK); 67 break; 68 case PMBUS_VIRT_READ_IOUT_AVG: 69 if (data->id != max34446) 70 return -ENXIO; 71 ret = pmbus_read_word_data(client, page, 72 MAX34446_MFR_IOUT_AVG); 73 break; 74 case PMBUS_VIRT_READ_IOUT_MAX: 75 ret = pmbus_read_word_data(client, page, 76 MAX34440_MFR_IOUT_PEAK); 77 break; 78 case PMBUS_VIRT_READ_POUT_AVG: 79 if (data->id != max34446) 80 return -ENXIO; 81 ret = pmbus_read_word_data(client, page, 82 MAX34446_MFR_POUT_AVG); 83 break; 84 case PMBUS_VIRT_READ_POUT_MAX: 85 if (data->id != max34446) 86 return -ENXIO; 87 ret = pmbus_read_word_data(client, page, 88 MAX34446_MFR_POUT_PEAK); 89 break; 90 case PMBUS_VIRT_READ_TEMP_AVG: 91 if (data->id != max34446 && data->id != max34460 && 92 data->id != max34461) 93 return -ENXIO; 94 ret = pmbus_read_word_data(client, page, 95 MAX34446_MFR_TEMPERATURE_AVG); 96 break; 97 case PMBUS_VIRT_READ_TEMP_MAX: 98 ret = pmbus_read_word_data(client, page, 99 MAX34440_MFR_TEMPERATURE_PEAK); 100 break; 101 case PMBUS_VIRT_RESET_POUT_HISTORY: 102 if (data->id != max34446) 103 return -ENXIO; 104 ret = 0; 105 break; 106 case PMBUS_VIRT_RESET_VOUT_HISTORY: 107 case PMBUS_VIRT_RESET_IOUT_HISTORY: 108 case PMBUS_VIRT_RESET_TEMP_HISTORY: 109 ret = 0; 110 break; 111 default: 112 ret = -ENODATA; 113 break; 114 } 115 return ret; 116} 117 118static int max34440_write_word_data(struct i2c_client *client, int page, 119 int reg, u16 word) 120{ 121 const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 122 const struct max34440_data *data = to_max34440_data(info); 123 int ret; 124 125 switch (reg) { 126 case PMBUS_VIRT_RESET_POUT_HISTORY: 127 ret = pmbus_write_word_data(client, page, 128 MAX34446_MFR_POUT_PEAK, 0); 129 if (ret) 130 break; 131 ret = pmbus_write_word_data(client, page, 132 MAX34446_MFR_POUT_AVG, 0); 133 break; 134 case PMBUS_VIRT_RESET_VOUT_HISTORY: 135 ret = pmbus_write_word_data(client, page, 136 MAX34440_MFR_VOUT_MIN, 0x7fff); 137 if (ret) 138 break; 139 ret = pmbus_write_word_data(client, page, 140 MAX34440_MFR_VOUT_PEAK, 0); 141 break; 142 case PMBUS_VIRT_RESET_IOUT_HISTORY: 143 ret = pmbus_write_word_data(client, page, 144 MAX34440_MFR_IOUT_PEAK, 0); 145 if (!ret && data->id == max34446) 146 ret = pmbus_write_word_data(client, page, 147 MAX34446_MFR_IOUT_AVG, 0); 148 149 break; 150 case PMBUS_VIRT_RESET_TEMP_HISTORY: 151 ret = pmbus_write_word_data(client, page, 152 MAX34440_MFR_TEMPERATURE_PEAK, 153 0x8000); 154 if (!ret && data->id == max34446) 155 ret = pmbus_write_word_data(client, page, 156 MAX34446_MFR_TEMPERATURE_AVG, 0); 157 break; 158 default: 159 ret = -ENODATA; 160 break; 161 } 162 return ret; 163} 164 165static int max34440_read_byte_data(struct i2c_client *client, int page, int reg) 166{ 167 int ret = 0; 168 int mfg_status; 169 170 if (page >= 0) { 171 ret = pmbus_set_page(client, page); 172 if (ret < 0) 173 return ret; 174 } 175 176 switch (reg) { 177 case PMBUS_STATUS_IOUT: 178 mfg_status = pmbus_read_word_data(client, 0, 179 PMBUS_STATUS_MFR_SPECIFIC); 180 if (mfg_status < 0) 181 return mfg_status; 182 if (mfg_status & MAX34440_STATUS_OC_WARN) 183 ret |= PB_IOUT_OC_WARNING; 184 if (mfg_status & MAX34440_STATUS_OC_FAULT) 185 ret |= PB_IOUT_OC_FAULT; 186 break; 187 case PMBUS_STATUS_TEMPERATURE: 188 mfg_status = pmbus_read_word_data(client, 0, 189 PMBUS_STATUS_MFR_SPECIFIC); 190 if (mfg_status < 0) 191 return mfg_status; 192 if (mfg_status & MAX34440_STATUS_OT_WARN) 193 ret |= PB_TEMP_OT_WARNING; 194 if (mfg_status & MAX34440_STATUS_OT_FAULT) 195 ret |= PB_TEMP_OT_FAULT; 196 break; 197 default: 198 ret = -ENODATA; 199 break; 200 } 201 return ret; 202} 203 204static struct pmbus_driver_info max34440_info[] = { 205 [max34440] = { 206 .pages = 14, 207 .format[PSC_VOLTAGE_IN] = direct, 208 .format[PSC_VOLTAGE_OUT] = direct, 209 .format[PSC_TEMPERATURE] = direct, 210 .format[PSC_CURRENT_OUT] = direct, 211 .m[PSC_VOLTAGE_IN] = 1, 212 .b[PSC_VOLTAGE_IN] = 0, 213 .R[PSC_VOLTAGE_IN] = 3, /* R = 0 in datasheet reflects mV */ 214 .m[PSC_VOLTAGE_OUT] = 1, 215 .b[PSC_VOLTAGE_OUT] = 0, 216 .R[PSC_VOLTAGE_OUT] = 3, /* R = 0 in datasheet reflects mV */ 217 .m[PSC_CURRENT_OUT] = 1, 218 .b[PSC_CURRENT_OUT] = 0, 219 .R[PSC_CURRENT_OUT] = 3, /* R = 0 in datasheet reflects mA */ 220 .m[PSC_TEMPERATURE] = 1, 221 .b[PSC_TEMPERATURE] = 0, 222 .R[PSC_TEMPERATURE] = 2, 223 .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 224 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 225 .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 226 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 227 .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 228 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 229 .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 230 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 231 .func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 232 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 233 .func[5] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 234 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 235 .func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 236 .func[7] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 237 .func[8] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 238 .func[9] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 239 .func[10] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 240 .func[11] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 241 .func[12] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 242 .func[13] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 243 .read_byte_data = max34440_read_byte_data, 244 .read_word_data = max34440_read_word_data, 245 .write_word_data = max34440_write_word_data, 246 }, 247 [max34441] = { 248 .pages = 12, 249 .format[PSC_VOLTAGE_IN] = direct, 250 .format[PSC_VOLTAGE_OUT] = direct, 251 .format[PSC_TEMPERATURE] = direct, 252 .format[PSC_CURRENT_OUT] = direct, 253 .format[PSC_FAN] = direct, 254 .m[PSC_VOLTAGE_IN] = 1, 255 .b[PSC_VOLTAGE_IN] = 0, 256 .R[PSC_VOLTAGE_IN] = 3, 257 .m[PSC_VOLTAGE_OUT] = 1, 258 .b[PSC_VOLTAGE_OUT] = 0, 259 .R[PSC_VOLTAGE_OUT] = 3, 260 .m[PSC_CURRENT_OUT] = 1, 261 .b[PSC_CURRENT_OUT] = 0, 262 .R[PSC_CURRENT_OUT] = 3, 263 .m[PSC_TEMPERATURE] = 1, 264 .b[PSC_TEMPERATURE] = 0, 265 .R[PSC_TEMPERATURE] = 2, 266 .m[PSC_FAN] = 1, 267 .b[PSC_FAN] = 0, 268 .R[PSC_FAN] = 0, 269 .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 270 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 271 .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 272 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 273 .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 274 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 275 .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 276 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 277 .func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 278 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 279 .func[5] = PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12, 280 .func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 281 .func[7] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 282 .func[8] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 283 .func[9] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 284 .func[10] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 285 .func[11] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 286 .read_byte_data = max34440_read_byte_data, 287 .read_word_data = max34440_read_word_data, 288 .write_word_data = max34440_write_word_data, 289 }, 290 [max34446] = { 291 .pages = 7, 292 .format[PSC_VOLTAGE_IN] = direct, 293 .format[PSC_VOLTAGE_OUT] = direct, 294 .format[PSC_TEMPERATURE] = direct, 295 .format[PSC_CURRENT_OUT] = direct, 296 .format[PSC_POWER] = direct, 297 .m[PSC_VOLTAGE_IN] = 1, 298 .b[PSC_VOLTAGE_IN] = 0, 299 .R[PSC_VOLTAGE_IN] = 3, 300 .m[PSC_VOLTAGE_OUT] = 1, 301 .b[PSC_VOLTAGE_OUT] = 0, 302 .R[PSC_VOLTAGE_OUT] = 3, 303 .m[PSC_CURRENT_OUT] = 1, 304 .b[PSC_CURRENT_OUT] = 0, 305 .R[PSC_CURRENT_OUT] = 3, 306 .m[PSC_POWER] = 1, 307 .b[PSC_POWER] = 0, 308 .R[PSC_POWER] = 3, 309 .m[PSC_TEMPERATURE] = 1, 310 .b[PSC_TEMPERATURE] = 0, 311 .R[PSC_TEMPERATURE] = 2, 312 .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 313 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT, 314 .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 315 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 316 .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 317 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT, 318 .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 319 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 320 .func[4] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 321 .func[5] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 322 .func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 323 .read_byte_data = max34440_read_byte_data, 324 .read_word_data = max34440_read_word_data, 325 .write_word_data = max34440_write_word_data, 326 }, 327 [max34460] = { 328 .pages = 18, 329 .format[PSC_VOLTAGE_OUT] = direct, 330 .format[PSC_TEMPERATURE] = direct, 331 .m[PSC_VOLTAGE_OUT] = 1, 332 .b[PSC_VOLTAGE_OUT] = 0, 333 .R[PSC_VOLTAGE_OUT] = 3, 334 .m[PSC_TEMPERATURE] = 1, 335 .b[PSC_TEMPERATURE] = 0, 336 .R[PSC_TEMPERATURE] = 2, 337 .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 338 .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 339 .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 340 .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 341 .func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 342 .func[5] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 343 .func[6] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 344 .func[7] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 345 .func[8] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 346 .func[9] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 347 .func[10] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 348 .func[11] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 349 .func[13] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 350 .func[14] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 351 .func[15] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 352 .func[16] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 353 .func[17] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 354 .read_byte_data = max34440_read_byte_data, 355 .read_word_data = max34440_read_word_data, 356 .write_word_data = max34440_write_word_data, 357 }, 358 [max34461] = { 359 .pages = 23, 360 .format[PSC_VOLTAGE_OUT] = direct, 361 .format[PSC_TEMPERATURE] = direct, 362 .m[PSC_VOLTAGE_OUT] = 1, 363 .b[PSC_VOLTAGE_OUT] = 0, 364 .R[PSC_VOLTAGE_OUT] = 3, 365 .m[PSC_TEMPERATURE] = 1, 366 .b[PSC_TEMPERATURE] = 0, 367 .R[PSC_TEMPERATURE] = 2, 368 .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 369 .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 370 .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 371 .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 372 .func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 373 .func[5] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 374 .func[6] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 375 .func[7] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 376 .func[8] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 377 .func[9] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 378 .func[10] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 379 .func[11] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 380 .func[12] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 381 .func[13] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 382 .func[14] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 383 .func[15] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 384 /* page 16 is reserved */ 385 .func[17] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 386 .func[18] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 387 .func[19] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 388 .func[20] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 389 .func[21] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 390 .read_byte_data = max34440_read_byte_data, 391 .read_word_data = max34440_read_word_data, 392 .write_word_data = max34440_write_word_data, 393 }, 394}; 395 396static int max34440_probe(struct i2c_client *client, 397 const struct i2c_device_id *id) 398{ 399 struct max34440_data *data; 400 401 data = devm_kzalloc(&client->dev, sizeof(struct max34440_data), 402 GFP_KERNEL); 403 if (!data) 404 return -ENOMEM; 405 data->id = id->driver_data; 406 data->info = max34440_info[id->driver_data]; 407 408 return pmbus_do_probe(client, id, &data->info); 409} 410 411static const struct i2c_device_id max34440_id[] = { 412 {"max34440", max34440}, 413 {"max34441", max34441}, 414 {"max34446", max34446}, 415 {"max34460", max34460}, 416 {"max34461", max34461}, 417 {} 418}; 419MODULE_DEVICE_TABLE(i2c, max34440_id); 420 421/* This is the driver that will be inserted */ 422static struct i2c_driver max34440_driver = { 423 .driver = { 424 .name = "max34440", 425 }, 426 .probe = max34440_probe, 427 .remove = pmbus_do_remove, 428 .id_table = max34440_id, 429}; 430 431module_i2c_driver(max34440_driver); 432 433MODULE_AUTHOR("Guenter Roeck"); 434MODULE_DESCRIPTION("PMBus driver for Maxim MAX34440/MAX34441"); 435MODULE_LICENSE("GPL"); 436