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 struct lm25066_data *data; 180 struct pmbus_driver_info *info; 181 182 if (!i2c_check_functionality(client->adapter, 183 I2C_FUNC_SMBUS_READ_BYTE_DATA)) 184 return -ENODEV; 185 186 data = devm_kzalloc(&client->dev, sizeof(struct lm25066_data), 187 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 return config; 194 195 data->id = id->driver_data; 196 info = &data->info; 197 198 info->pages = 2; 199 info->format[PSC_VOLTAGE_IN] = direct; 200 info->format[PSC_VOLTAGE_OUT] = direct; 201 info->format[PSC_CURRENT_IN] = direct; 202 info->format[PSC_TEMPERATURE] = direct; 203 info->format[PSC_POWER] = direct; 204 205 info->m[PSC_TEMPERATURE] = 16; 206 info->b[PSC_TEMPERATURE] = 0; 207 info->R[PSC_TEMPERATURE] = 0; 208 209 info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT 210 | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_PIN | PMBUS_HAVE_IIN 211 | PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; 212 info->func[1] = PMBUS_HAVE_VOUT; 213 214 info->read_word_data = lm25066_read_word_data; 215 info->write_word_data = lm25066_write_word_data; 216 info->write_byte = lm25066_write_byte; 217 218 switch (id->driver_data) { 219 case lm25066: 220 info->m[PSC_VOLTAGE_IN] = 22070; 221 info->b[PSC_VOLTAGE_IN] = 0; 222 info->R[PSC_VOLTAGE_IN] = -2; 223 info->m[PSC_VOLTAGE_OUT] = 22070; 224 info->b[PSC_VOLTAGE_OUT] = 0; 225 info->R[PSC_VOLTAGE_OUT] = -2; 226 227 if (config & LM25066_DEV_SETUP_CL) { 228 info->m[PSC_CURRENT_IN] = 6852; 229 info->b[PSC_CURRENT_IN] = 0; 230 info->R[PSC_CURRENT_IN] = -2; 231 info->m[PSC_POWER] = 369; 232 info->b[PSC_POWER] = 0; 233 info->R[PSC_POWER] = -2; 234 } else { 235 info->m[PSC_CURRENT_IN] = 13661; 236 info->b[PSC_CURRENT_IN] = 0; 237 info->R[PSC_CURRENT_IN] = -2; 238 info->m[PSC_POWER] = 736; 239 info->b[PSC_POWER] = 0; 240 info->R[PSC_POWER] = -2; 241 } 242 break; 243 case lm5064: 244 info->m[PSC_VOLTAGE_IN] = 22075; 245 info->b[PSC_VOLTAGE_IN] = 0; 246 info->R[PSC_VOLTAGE_IN] = -2; 247 info->m[PSC_VOLTAGE_OUT] = 22075; 248 info->b[PSC_VOLTAGE_OUT] = 0; 249 info->R[PSC_VOLTAGE_OUT] = -2; 250 251 if (config & LM25066_DEV_SETUP_CL) { 252 info->m[PSC_CURRENT_IN] = 6713; 253 info->b[PSC_CURRENT_IN] = 0; 254 info->R[PSC_CURRENT_IN] = -2; 255 info->m[PSC_POWER] = 3619; 256 info->b[PSC_POWER] = 0; 257 info->R[PSC_POWER] = -3; 258 } else { 259 info->m[PSC_CURRENT_IN] = 13426; 260 info->b[PSC_CURRENT_IN] = 0; 261 info->R[PSC_CURRENT_IN] = -2; 262 info->m[PSC_POWER] = 7238; 263 info->b[PSC_POWER] = 0; 264 info->R[PSC_POWER] = -3; 265 } 266 break; 267 case lm5066: 268 info->m[PSC_VOLTAGE_IN] = 4587; 269 info->b[PSC_VOLTAGE_IN] = 0; 270 info->R[PSC_VOLTAGE_IN] = -2; 271 info->m[PSC_VOLTAGE_OUT] = 4587; 272 info->b[PSC_VOLTAGE_OUT] = 0; 273 info->R[PSC_VOLTAGE_OUT] = -2; 274 275 if (config & LM25066_DEV_SETUP_CL) { 276 info->m[PSC_CURRENT_IN] = 10753; 277 info->b[PSC_CURRENT_IN] = 0; 278 info->R[PSC_CURRENT_IN] = -2; 279 info->m[PSC_POWER] = 1204; 280 info->b[PSC_POWER] = 0; 281 info->R[PSC_POWER] = -3; 282 } else { 283 info->m[PSC_CURRENT_IN] = 5405; 284 info->b[PSC_CURRENT_IN] = 0; 285 info->R[PSC_CURRENT_IN] = -2; 286 info->m[PSC_POWER] = 605; 287 info->b[PSC_POWER] = 0; 288 info->R[PSC_POWER] = -3; 289 } 290 break; 291 default: 292 return -ENODEV; 293 } 294 295 return pmbus_do_probe(client, id, info); 296 } 297 298 static const struct i2c_device_id lm25066_id[] = { 299 {"lm25066", lm25066}, 300 {"lm5064", lm5064}, 301 {"lm5066", lm5066}, 302 { } 303 }; 304 305 MODULE_DEVICE_TABLE(i2c, lm25066_id); 306 307 /* This is the driver that will be inserted */ 308 static struct i2c_driver lm25066_driver = { 309 .driver = { 310 .name = "lm25066", 311 }, 312 .probe = lm25066_probe, 313 .remove = pmbus_do_remove, 314 .id_table = lm25066_id, 315 }; 316 317 module_i2c_driver(lm25066_driver); 318 319 MODULE_AUTHOR("Guenter Roeck"); 320 MODULE_DESCRIPTION("PMBus driver for LM25066/LM5064/LM5066"); 321 MODULE_LICENSE("GPL"); 322