1 /* 2 * Hardware monitoring driver for IR35221 3 * 4 * Copyright (C) IBM Corporation 2017. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 */ 11 12 #include <linux/err.h> 13 #include <linux/i2c.h> 14 #include <linux/init.h> 15 #include <linux/kernel.h> 16 #include <linux/module.h> 17 #include "pmbus.h" 18 19 #define IR35221_MFR_VIN_PEAK 0xc5 20 #define IR35221_MFR_VOUT_PEAK 0xc6 21 #define IR35221_MFR_IOUT_PEAK 0xc7 22 #define IR35221_MFR_TEMP_PEAK 0xc8 23 #define IR35221_MFR_VIN_VALLEY 0xc9 24 #define IR35221_MFR_VOUT_VALLEY 0xca 25 #define IR35221_MFR_IOUT_VALLEY 0xcb 26 #define IR35221_MFR_TEMP_VALLEY 0xcc 27 28 static long ir35221_reg2data(int data, enum pmbus_sensor_classes class) 29 { 30 s16 exponent; 31 s32 mantissa; 32 long val; 33 34 /* We only modify LINEAR11 formats */ 35 exponent = ((s16)data) >> 11; 36 mantissa = ((s16)((data & 0x7ff) << 5)) >> 5; 37 38 val = mantissa * 1000L; 39 40 /* scale result to micro-units for power sensors */ 41 if (class == PSC_POWER) 42 val = val * 1000L; 43 44 if (exponent >= 0) 45 val <<= exponent; 46 else 47 val >>= -exponent; 48 49 return val; 50 } 51 52 #define MAX_MANTISSA (1023 * 1000) 53 #define MIN_MANTISSA (511 * 1000) 54 55 static u16 ir35221_data2reg(long val, enum pmbus_sensor_classes class) 56 { 57 s16 exponent = 0, mantissa; 58 bool negative = false; 59 60 if (val == 0) 61 return 0; 62 63 if (val < 0) { 64 negative = true; 65 val = -val; 66 } 67 68 /* Power is in uW. Convert to mW before converting. */ 69 if (class == PSC_POWER) 70 val = DIV_ROUND_CLOSEST(val, 1000L); 71 72 /* Reduce large mantissa until it fits into 10 bit */ 73 while (val >= MAX_MANTISSA && exponent < 15) { 74 exponent++; 75 val >>= 1; 76 } 77 /* Increase small mantissa to improve precision */ 78 while (val < MIN_MANTISSA && exponent > -15) { 79 exponent--; 80 val <<= 1; 81 } 82 83 /* Convert mantissa from milli-units to units */ 84 mantissa = DIV_ROUND_CLOSEST(val, 1000); 85 86 /* Ensure that resulting number is within range */ 87 if (mantissa > 0x3ff) 88 mantissa = 0x3ff; 89 90 /* restore sign */ 91 if (negative) 92 mantissa = -mantissa; 93 94 /* Convert to 5 bit exponent, 11 bit mantissa */ 95 return (mantissa & 0x7ff) | ((exponent << 11) & 0xf800); 96 } 97 98 static u16 ir35221_scale_result(s16 data, int shift, 99 enum pmbus_sensor_classes class) 100 { 101 long val; 102 103 val = ir35221_reg2data(data, class); 104 105 if (shift < 0) 106 val >>= -shift; 107 else 108 val <<= shift; 109 110 return ir35221_data2reg(val, class); 111 } 112 113 static int ir35221_read_word_data(struct i2c_client *client, int page, int reg) 114 { 115 int ret; 116 117 switch (reg) { 118 case PMBUS_IOUT_OC_FAULT_LIMIT: 119 case PMBUS_IOUT_OC_WARN_LIMIT: 120 ret = pmbus_read_word_data(client, page, reg); 121 if (ret < 0) 122 break; 123 ret = ir35221_scale_result(ret, 1, PSC_CURRENT_OUT); 124 break; 125 case PMBUS_VIN_OV_FAULT_LIMIT: 126 case PMBUS_VIN_OV_WARN_LIMIT: 127 case PMBUS_VIN_UV_WARN_LIMIT: 128 ret = pmbus_read_word_data(client, page, reg); 129 ret = ir35221_scale_result(ret, -4, PSC_VOLTAGE_IN); 130 break; 131 case PMBUS_IIN_OC_WARN_LIMIT: 132 ret = pmbus_read_word_data(client, page, reg); 133 if (ret < 0) 134 break; 135 ret = ir35221_scale_result(ret, -1, PSC_CURRENT_IN); 136 break; 137 case PMBUS_READ_VIN: 138 ret = pmbus_read_word_data(client, page, PMBUS_READ_VIN); 139 if (ret < 0) 140 break; 141 ret = ir35221_scale_result(ret, -5, PSC_VOLTAGE_IN); 142 break; 143 case PMBUS_READ_IIN: 144 ret = pmbus_read_word_data(client, page, PMBUS_READ_IIN); 145 if (ret < 0) 146 break; 147 if (page == 0) 148 ret = ir35221_scale_result(ret, -4, PSC_CURRENT_IN); 149 else 150 ret = ir35221_scale_result(ret, -5, PSC_CURRENT_IN); 151 break; 152 case PMBUS_READ_POUT: 153 ret = pmbus_read_word_data(client, page, PMBUS_READ_POUT); 154 if (ret < 0) 155 break; 156 ret = ir35221_scale_result(ret, -1, PSC_POWER); 157 break; 158 case PMBUS_READ_PIN: 159 ret = pmbus_read_word_data(client, page, PMBUS_READ_PIN); 160 if (ret < 0) 161 break; 162 ret = ir35221_scale_result(ret, -1, PSC_POWER); 163 break; 164 case PMBUS_READ_IOUT: 165 ret = pmbus_read_word_data(client, page, PMBUS_READ_IOUT); 166 if (ret < 0) 167 break; 168 if (page == 0) 169 ret = ir35221_scale_result(ret, -1, PSC_CURRENT_OUT); 170 else 171 ret = ir35221_scale_result(ret, -2, PSC_CURRENT_OUT); 172 break; 173 case PMBUS_VIRT_READ_VIN_MAX: 174 ret = pmbus_read_word_data(client, page, IR35221_MFR_VIN_PEAK); 175 if (ret < 0) 176 break; 177 ret = ir35221_scale_result(ret, -5, PSC_VOLTAGE_IN); 178 break; 179 case PMBUS_VIRT_READ_VOUT_MAX: 180 ret = pmbus_read_word_data(client, page, IR35221_MFR_VOUT_PEAK); 181 break; 182 case PMBUS_VIRT_READ_IOUT_MAX: 183 ret = pmbus_read_word_data(client, page, IR35221_MFR_IOUT_PEAK); 184 if (ret < 0) 185 break; 186 if (page == 0) 187 ret = ir35221_scale_result(ret, -1, PSC_CURRENT_IN); 188 else 189 ret = ir35221_scale_result(ret, -2, PSC_CURRENT_IN); 190 break; 191 case PMBUS_VIRT_READ_TEMP_MAX: 192 ret = pmbus_read_word_data(client, page, IR35221_MFR_TEMP_PEAK); 193 break; 194 case PMBUS_VIRT_READ_VIN_MIN: 195 ret = pmbus_read_word_data(client, page, 196 IR35221_MFR_VIN_VALLEY); 197 if (ret < 0) 198 break; 199 ret = ir35221_scale_result(ret, -5, PSC_VOLTAGE_IN); 200 break; 201 case PMBUS_VIRT_READ_VOUT_MIN: 202 ret = pmbus_read_word_data(client, page, 203 IR35221_MFR_VOUT_VALLEY); 204 break; 205 case PMBUS_VIRT_READ_IOUT_MIN: 206 ret = pmbus_read_word_data(client, page, 207 IR35221_MFR_IOUT_VALLEY); 208 if (ret < 0) 209 break; 210 if (page == 0) 211 ret = ir35221_scale_result(ret, -1, PSC_CURRENT_IN); 212 else 213 ret = ir35221_scale_result(ret, -2, PSC_CURRENT_IN); 214 break; 215 case PMBUS_VIRT_READ_TEMP_MIN: 216 ret = pmbus_read_word_data(client, page, 217 IR35221_MFR_TEMP_VALLEY); 218 break; 219 default: 220 ret = -ENODATA; 221 break; 222 } 223 224 return ret; 225 } 226 227 static int ir35221_write_word_data(struct i2c_client *client, int page, int reg, 228 u16 word) 229 { 230 int ret; 231 u16 val; 232 233 switch (reg) { 234 case PMBUS_IOUT_OC_FAULT_LIMIT: 235 case PMBUS_IOUT_OC_WARN_LIMIT: 236 val = ir35221_scale_result(word, -1, PSC_CURRENT_OUT); 237 ret = pmbus_write_word_data(client, page, reg, val); 238 break; 239 case PMBUS_VIN_OV_FAULT_LIMIT: 240 case PMBUS_VIN_OV_WARN_LIMIT: 241 case PMBUS_VIN_UV_WARN_LIMIT: 242 val = ir35221_scale_result(word, 4, PSC_VOLTAGE_IN); 243 ret = pmbus_write_word_data(client, page, reg, val); 244 break; 245 case PMBUS_IIN_OC_WARN_LIMIT: 246 val = ir35221_scale_result(word, 1, PSC_CURRENT_IN); 247 ret = pmbus_write_word_data(client, page, reg, val); 248 break; 249 default: 250 ret = -ENODATA; 251 break; 252 } 253 254 return ret; 255 } 256 257 static int ir35221_probe(struct i2c_client *client, 258 const struct i2c_device_id *id) 259 { 260 struct pmbus_driver_info *info; 261 u8 buf[I2C_SMBUS_BLOCK_MAX]; 262 int ret; 263 264 if (!i2c_check_functionality(client->adapter, 265 I2C_FUNC_SMBUS_READ_BYTE_DATA 266 | I2C_FUNC_SMBUS_READ_WORD_DATA 267 | I2C_FUNC_SMBUS_READ_BLOCK_DATA)) 268 return -ENODEV; 269 270 ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, buf); 271 if (ret < 0) { 272 dev_err(&client->dev, "Failed to read PMBUS_MFR_ID\n"); 273 return ret; 274 } 275 if (ret != 2 || strncmp(buf, "RI", strlen("RI"))) { 276 dev_err(&client->dev, "MFR_ID unrecognised\n"); 277 return -ENODEV; 278 } 279 280 ret = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL, buf); 281 if (ret < 0) { 282 dev_err(&client->dev, "Failed to read PMBUS_MFR_MODEL\n"); 283 return ret; 284 } 285 if (ret != 2 || !(buf[0] == 0x6c && buf[1] == 0x00)) { 286 dev_err(&client->dev, "MFR_MODEL unrecognised\n"); 287 return -ENODEV; 288 } 289 290 info = devm_kzalloc(&client->dev, sizeof(struct pmbus_driver_info), 291 GFP_KERNEL); 292 if (!info) 293 return -ENOMEM; 294 295 info->write_word_data = ir35221_write_word_data; 296 info->read_word_data = ir35221_read_word_data; 297 298 info->pages = 2; 299 info->format[PSC_VOLTAGE_IN] = linear; 300 info->format[PSC_VOLTAGE_OUT] = linear; 301 info->format[PSC_CURRENT_IN] = linear; 302 info->format[PSC_CURRENT_OUT] = linear; 303 info->format[PSC_POWER] = linear; 304 info->format[PSC_TEMPERATURE] = linear; 305 306 info->func[0] = PMBUS_HAVE_VIN 307 | PMBUS_HAVE_VOUT | PMBUS_HAVE_IIN 308 | PMBUS_HAVE_IOUT | PMBUS_HAVE_PIN 309 | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP 310 | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT 311 | PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP; 312 info->func[1] = info->func[0]; 313 314 return pmbus_do_probe(client, id, info); 315 } 316 317 static const struct i2c_device_id ir35221_id[] = { 318 {"ir35221", 0}, 319 {} 320 }; 321 322 MODULE_DEVICE_TABLE(i2c, ir35221_id); 323 324 static struct i2c_driver ir35221_driver = { 325 .driver = { 326 .name = "ir35221", 327 }, 328 .probe = ir35221_probe, 329 .remove = pmbus_do_remove, 330 .id_table = ir35221_id, 331 }; 332 333 module_i2c_driver(ir35221_driver); 334 335 MODULE_AUTHOR("Samuel Mendoza-Jonas <sam@mendozajonas.com"); 336 MODULE_DESCRIPTION("PMBus driver for IR35221"); 337 MODULE_LICENSE("GPL"); 338