1 /* 2 * Hardware monitoring driver for LM25066 / LM5064 / LM5066 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 { lm25066, lm5064, lm5066 }; 30 31 #define LM25066_READ_VAUX 0xd0 32 #define LM25066_MFR_READ_IIN 0xd1 33 #define LM25066_MFR_READ_PIN 0xd2 34 #define LM25066_MFR_IIN_OC_WARN_LIMIT 0xd3 35 #define LM25066_MFR_PIN_OP_WARN_LIMIT 0xd4 36 #define LM25066_READ_PIN_PEAK 0xd5 37 #define LM25066_CLEAR_PIN_PEAK 0xd6 38 #define LM25066_DEVICE_SETUP 0xd9 39 #define LM25066_READ_AVG_VIN 0xdc 40 #define LM25066_READ_AVG_VOUT 0xdd 41 #define LM25066_READ_AVG_IIN 0xde 42 #define LM25066_READ_AVG_PIN 0xdf 43 44 #define LM25066_DEV_SETUP_CL (1 << 4) /* Current limit */ 45 46 struct lm25066_data { 47 int id; 48 struct pmbus_driver_info info; 49 }; 50 51 #define to_lm25066_data(x) container_of(x, struct lm25066_data, info) 52 53 static int lm25066_read_word_data(struct i2c_client *client, int page, int reg) 54 { 55 const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 56 const struct lm25066_data *data = to_lm25066_data(info); 57 int ret; 58 59 if (page > 1) 60 return -ENXIO; 61 62 /* Map READ_VAUX into READ_VOUT register on page 1 */ 63 if (page == 1) { 64 switch (reg) { 65 case PMBUS_READ_VOUT: 66 ret = pmbus_read_word_data(client, 0, 67 LM25066_READ_VAUX); 68 if (ret < 0) 69 break; 70 /* Adjust returned value to match VOUT coefficients */ 71 switch (data->id) { 72 case lm25066: 73 /* VOUT: 4.54 mV VAUX: 283.2 uV LSB */ 74 ret = DIV_ROUND_CLOSEST(ret * 2832, 45400); 75 break; 76 case lm5064: 77 /* VOUT: 4.53 mV VAUX: 700 uV LSB */ 78 ret = DIV_ROUND_CLOSEST(ret * 70, 453); 79 break; 80 case lm5066: 81 /* VOUT: 2.18 mV VAUX: 725 uV LSB */ 82 ret = DIV_ROUND_CLOSEST(ret * 725, 2180); 83 break; 84 } 85 break; 86 default: 87 /* No other valid registers on page 1 */ 88 ret = -ENXIO; 89 break; 90 } 91 goto done; 92 } 93 94 switch (reg) { 95 case PMBUS_READ_IIN: 96 ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_IIN); 97 break; 98 case PMBUS_READ_PIN: 99 ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_PIN); 100 break; 101 case PMBUS_IIN_OC_WARN_LIMIT: 102 ret = pmbus_read_word_data(client, 0, 103 LM25066_MFR_IIN_OC_WARN_LIMIT); 104 break; 105 case PMBUS_PIN_OP_WARN_LIMIT: 106 ret = pmbus_read_word_data(client, 0, 107 LM25066_MFR_PIN_OP_WARN_LIMIT); 108 break; 109 case PMBUS_VIRT_READ_VIN_AVG: 110 ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VIN); 111 break; 112 case PMBUS_VIRT_READ_VOUT_AVG: 113 ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VOUT); 114 break; 115 case PMBUS_VIRT_READ_IIN_AVG: 116 ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_IIN); 117 break; 118 case PMBUS_VIRT_READ_PIN_AVG: 119 ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_PIN); 120 break; 121 case PMBUS_VIRT_READ_PIN_MAX: 122 ret = pmbus_read_word_data(client, 0, LM25066_READ_PIN_PEAK); 123 break; 124 case PMBUS_VIRT_RESET_PIN_HISTORY: 125 ret = 0; 126 break; 127 default: 128 ret = -ENODATA; 129 break; 130 } 131 done: 132 return ret; 133 } 134 135 static int lm25066_write_word_data(struct i2c_client *client, int page, int reg, 136 u16 word) 137 { 138 int ret; 139 140 if (page > 1) 141 return -ENXIO; 142 143 switch (reg) { 144 case PMBUS_IIN_OC_WARN_LIMIT: 145 ret = pmbus_write_word_data(client, 0, 146 LM25066_MFR_IIN_OC_WARN_LIMIT, 147 word); 148 break; 149 case PMBUS_PIN_OP_WARN_LIMIT: 150 ret = pmbus_write_word_data(client, 0, 151 LM25066_MFR_PIN_OP_WARN_LIMIT, 152 word); 153 break; 154 case PMBUS_VIRT_RESET_PIN_HISTORY: 155 ret = pmbus_write_byte(client, 0, LM25066_CLEAR_PIN_PEAK); 156 break; 157 default: 158 ret = -ENODATA; 159 break; 160 } 161 return ret; 162 } 163 164 static int lm25066_write_byte(struct i2c_client *client, int page, u8 value) 165 { 166 if (page > 1) 167 return -ENXIO; 168 169 if (page <= 0) 170 return pmbus_write_byte(client, page, value); 171 172 return 0; 173 } 174 175 static int lm25066_probe(struct i2c_client *client, 176 const struct i2c_device_id *id) 177 { 178 int config; 179 int ret; 180 struct lm25066_data *data; 181 struct pmbus_driver_info *info; 182 183 if (!i2c_check_functionality(client->adapter, 184 I2C_FUNC_SMBUS_READ_BYTE_DATA)) 185 return -ENODEV; 186 187 data = kzalloc(sizeof(struct lm25066_data), GFP_KERNEL); 188 if (!data) 189 return -ENOMEM; 190 191 config = i2c_smbus_read_byte_data(client, LM25066_DEVICE_SETUP); 192 if (config < 0) { 193 ret = config; 194 goto err_mem; 195 } 196 197 data->id = id->driver_data; 198 info = &data->info; 199 200 info->pages = 2; 201 info->format[PSC_VOLTAGE_IN] = direct; 202 info->format[PSC_VOLTAGE_OUT] = direct; 203 info->format[PSC_CURRENT_IN] = direct; 204 info->format[PSC_TEMPERATURE] = direct; 205 info->format[PSC_POWER] = direct; 206 207 info->m[PSC_TEMPERATURE] = 16; 208 info->b[PSC_TEMPERATURE] = 0; 209 info->R[PSC_TEMPERATURE] = 0; 210 211 info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT 212 | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_PIN | PMBUS_HAVE_IIN 213 | PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; 214 info->func[1] = PMBUS_HAVE_VOUT; 215 216 info->read_word_data = lm25066_read_word_data; 217 info->write_word_data = lm25066_write_word_data; 218 info->write_byte = lm25066_write_byte; 219 220 switch (id->driver_data) { 221 case lm25066: 222 info->m[PSC_VOLTAGE_IN] = 22070; 223 info->b[PSC_VOLTAGE_IN] = 0; 224 info->R[PSC_VOLTAGE_IN] = -2; 225 info->m[PSC_VOLTAGE_OUT] = 22070; 226 info->b[PSC_VOLTAGE_OUT] = 0; 227 info->R[PSC_VOLTAGE_OUT] = -2; 228 229 if (config & LM25066_DEV_SETUP_CL) { 230 info->m[PSC_CURRENT_IN] = 6852; 231 info->b[PSC_CURRENT_IN] = 0; 232 info->R[PSC_CURRENT_IN] = -2; 233 info->m[PSC_POWER] = 369; 234 info->b[PSC_POWER] = 0; 235 info->R[PSC_POWER] = -2; 236 } else { 237 info->m[PSC_CURRENT_IN] = 13661; 238 info->b[PSC_CURRENT_IN] = 0; 239 info->R[PSC_CURRENT_IN] = -2; 240 info->m[PSC_POWER] = 736; 241 info->b[PSC_POWER] = 0; 242 info->R[PSC_POWER] = -2; 243 } 244 break; 245 case lm5064: 246 info->m[PSC_VOLTAGE_IN] = 22075; 247 info->b[PSC_VOLTAGE_IN] = 0; 248 info->R[PSC_VOLTAGE_IN] = -2; 249 info->m[PSC_VOLTAGE_OUT] = 22075; 250 info->b[PSC_VOLTAGE_OUT] = 0; 251 info->R[PSC_VOLTAGE_OUT] = -2; 252 253 if (config & LM25066_DEV_SETUP_CL) { 254 info->m[PSC_CURRENT_IN] = 6713; 255 info->b[PSC_CURRENT_IN] = 0; 256 info->R[PSC_CURRENT_IN] = -2; 257 info->m[PSC_POWER] = 3619; 258 info->b[PSC_POWER] = 0; 259 info->R[PSC_POWER] = -3; 260 } else { 261 info->m[PSC_CURRENT_IN] = 13426; 262 info->b[PSC_CURRENT_IN] = 0; 263 info->R[PSC_CURRENT_IN] = -2; 264 info->m[PSC_POWER] = 7238; 265 info->b[PSC_POWER] = 0; 266 info->R[PSC_POWER] = -3; 267 } 268 break; 269 case lm5066: 270 info->m[PSC_VOLTAGE_IN] = 4587; 271 info->b[PSC_VOLTAGE_IN] = 0; 272 info->R[PSC_VOLTAGE_IN] = -2; 273 info->m[PSC_VOLTAGE_OUT] = 4587; 274 info->b[PSC_VOLTAGE_OUT] = 0; 275 info->R[PSC_VOLTAGE_OUT] = -2; 276 277 if (config & LM25066_DEV_SETUP_CL) { 278 info->m[PSC_CURRENT_IN] = 10753; 279 info->b[PSC_CURRENT_IN] = 0; 280 info->R[PSC_CURRENT_IN] = -2; 281 info->m[PSC_POWER] = 1204; 282 info->b[PSC_POWER] = 0; 283 info->R[PSC_POWER] = -3; 284 } else { 285 info->m[PSC_CURRENT_IN] = 5405; 286 info->b[PSC_CURRENT_IN] = 0; 287 info->R[PSC_CURRENT_IN] = -2; 288 info->m[PSC_POWER] = 605; 289 info->b[PSC_POWER] = 0; 290 info->R[PSC_POWER] = -3; 291 } 292 break; 293 default: 294 ret = -ENODEV; 295 goto err_mem; 296 } 297 298 ret = pmbus_do_probe(client, id, info); 299 if (ret) 300 goto err_mem; 301 return 0; 302 303 err_mem: 304 kfree(data); 305 return ret; 306 } 307 308 static int lm25066_remove(struct i2c_client *client) 309 { 310 const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 311 const struct lm25066_data *data = to_lm25066_data(info); 312 313 pmbus_do_remove(client); 314 kfree(data); 315 return 0; 316 } 317 318 static const struct i2c_device_id lm25066_id[] = { 319 {"lm25066", lm25066}, 320 {"lm5064", lm5064}, 321 {"lm5066", lm5066}, 322 { } 323 }; 324 325 MODULE_DEVICE_TABLE(i2c, lm25066_id); 326 327 /* This is the driver that will be inserted */ 328 static struct i2c_driver lm25066_driver = { 329 .driver = { 330 .name = "lm25066", 331 }, 332 .probe = lm25066_probe, 333 .remove = lm25066_remove, 334 .id_table = lm25066_id, 335 }; 336 337 static int __init lm25066_init(void) 338 { 339 return i2c_add_driver(&lm25066_driver); 340 } 341 342 static void __exit lm25066_exit(void) 343 { 344 i2c_del_driver(&lm25066_driver); 345 } 346 347 MODULE_AUTHOR("Guenter Roeck"); 348 MODULE_DESCRIPTION("PMBus driver for LM25066/LM5064/LM5066"); 349 MODULE_LICENSE("GPL"); 350 module_init(lm25066_init); 351 module_exit(lm25066_exit); 352