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