zl6100.c (11412B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Hardware monitoring driver for ZL6100 and compatibles 4 * 5 * Copyright (c) 2011 Ericsson AB. 6 * Copyright (c) 2012 Guenter Roeck 7 */ 8 9#include <linux/bitops.h> 10#include <linux/kernel.h> 11#include <linux/module.h> 12#include <linux/init.h> 13#include <linux/err.h> 14#include <linux/slab.h> 15#include <linux/i2c.h> 16#include <linux/ktime.h> 17#include <linux/delay.h> 18#include "pmbus.h" 19 20enum chips { zl2004, zl2005, zl2006, zl2008, zl2105, zl2106, zl6100, zl6105, 21 zl8802, zl9101, zl9117, zls1003, zls4009 }; 22 23struct zl6100_data { 24 int id; 25 ktime_t access; /* chip access time */ 26 int delay; /* Delay between chip accesses in uS */ 27 struct pmbus_driver_info info; 28}; 29 30#define to_zl6100_data(x) container_of(x, struct zl6100_data, info) 31 32#define ZL6100_MFR_CONFIG 0xd0 33#define ZL6100_DEVICE_ID 0xe4 34 35#define ZL6100_MFR_XTEMP_ENABLE BIT(7) 36 37#define ZL8802_MFR_USER_GLOBAL_CONFIG 0xe9 38#define ZL8802_MFR_TMON_ENABLE BIT(12) 39#define ZL8802_MFR_USER_CONFIG 0xd1 40#define ZL8802_MFR_XTEMP_ENABLE_2 BIT(1) 41#define ZL8802_MFR_DDC_CONFIG 0xd3 42#define ZL8802_MFR_PHASES_MASK 0x0007 43 44#define MFR_VMON_OV_FAULT_LIMIT 0xf5 45#define MFR_VMON_UV_FAULT_LIMIT 0xf6 46#define MFR_READ_VMON 0xf7 47 48#define VMON_UV_WARNING BIT(5) 49#define VMON_OV_WARNING BIT(4) 50#define VMON_UV_FAULT BIT(1) 51#define VMON_OV_FAULT BIT(0) 52 53#define ZL6100_WAIT_TIME 1000 /* uS */ 54 55static ushort delay = ZL6100_WAIT_TIME; 56module_param(delay, ushort, 0644); 57MODULE_PARM_DESC(delay, "Delay between chip accesses in uS"); 58 59/* Convert linear sensor value to milli-units */ 60static long zl6100_l2d(s16 l) 61{ 62 s16 exponent; 63 s32 mantissa; 64 long val; 65 66 exponent = l >> 11; 67 mantissa = ((s16)((l & 0x7ff) << 5)) >> 5; 68 69 val = mantissa; 70 71 /* scale result to milli-units */ 72 val = val * 1000L; 73 74 if (exponent >= 0) 75 val <<= exponent; 76 else 77 val >>= -exponent; 78 79 return val; 80} 81 82#define MAX_MANTISSA (1023 * 1000) 83#define MIN_MANTISSA (511 * 1000) 84 85static u16 zl6100_d2l(long val) 86{ 87 s16 exponent = 0, mantissa; 88 bool negative = false; 89 90 /* simple case */ 91 if (val == 0) 92 return 0; 93 94 if (val < 0) { 95 negative = true; 96 val = -val; 97 } 98 99 /* Reduce large mantissa until it fits into 10 bit */ 100 while (val >= MAX_MANTISSA && exponent < 15) { 101 exponent++; 102 val >>= 1; 103 } 104 /* Increase small mantissa to improve precision */ 105 while (val < MIN_MANTISSA && exponent > -15) { 106 exponent--; 107 val <<= 1; 108 } 109 110 /* Convert mantissa from milli-units to units */ 111 mantissa = DIV_ROUND_CLOSEST(val, 1000); 112 113 /* Ensure that resulting number is within range */ 114 if (mantissa > 0x3ff) 115 mantissa = 0x3ff; 116 117 /* restore sign */ 118 if (negative) 119 mantissa = -mantissa; 120 121 /* Convert to 5 bit exponent, 11 bit mantissa */ 122 return (mantissa & 0x7ff) | ((exponent << 11) & 0xf800); 123} 124 125/* Some chips need a delay between accesses */ 126static inline void zl6100_wait(const struct zl6100_data *data) 127{ 128 if (data->delay) { 129 s64 delta = ktime_us_delta(ktime_get(), data->access); 130 if (delta < data->delay) 131 udelay(data->delay - delta); 132 } 133} 134 135static int zl6100_read_word_data(struct i2c_client *client, int page, 136 int phase, int reg) 137{ 138 const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 139 struct zl6100_data *data = to_zl6100_data(info); 140 int ret, vreg; 141 142 if (page >= info->pages) 143 return -ENXIO; 144 145 if (data->id == zl2005) { 146 /* 147 * Limit register detection is not reliable on ZL2005. 148 * Make sure registers are not erroneously detected. 149 */ 150 switch (reg) { 151 case PMBUS_VOUT_OV_WARN_LIMIT: 152 case PMBUS_VOUT_UV_WARN_LIMIT: 153 case PMBUS_IOUT_OC_WARN_LIMIT: 154 return -ENXIO; 155 } 156 } 157 158 switch (reg) { 159 case PMBUS_VIRT_READ_VMON: 160 vreg = MFR_READ_VMON; 161 break; 162 case PMBUS_VIRT_VMON_OV_WARN_LIMIT: 163 case PMBUS_VIRT_VMON_OV_FAULT_LIMIT: 164 vreg = MFR_VMON_OV_FAULT_LIMIT; 165 break; 166 case PMBUS_VIRT_VMON_UV_WARN_LIMIT: 167 case PMBUS_VIRT_VMON_UV_FAULT_LIMIT: 168 vreg = MFR_VMON_UV_FAULT_LIMIT; 169 break; 170 default: 171 if (reg >= PMBUS_VIRT_BASE) 172 return -ENXIO; 173 vreg = reg; 174 break; 175 } 176 177 zl6100_wait(data); 178 ret = pmbus_read_word_data(client, page, phase, vreg); 179 data->access = ktime_get(); 180 if (ret < 0) 181 return ret; 182 183 switch (reg) { 184 case PMBUS_VIRT_VMON_OV_WARN_LIMIT: 185 ret = zl6100_d2l(DIV_ROUND_CLOSEST(zl6100_l2d(ret) * 9, 10)); 186 break; 187 case PMBUS_VIRT_VMON_UV_WARN_LIMIT: 188 ret = zl6100_d2l(DIV_ROUND_CLOSEST(zl6100_l2d(ret) * 11, 10)); 189 break; 190 } 191 192 return ret; 193} 194 195static int zl6100_read_byte_data(struct i2c_client *client, int page, int reg) 196{ 197 const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 198 struct zl6100_data *data = to_zl6100_data(info); 199 int ret, status; 200 201 if (page >= info->pages) 202 return -ENXIO; 203 204 zl6100_wait(data); 205 206 switch (reg) { 207 case PMBUS_VIRT_STATUS_VMON: 208 ret = pmbus_read_byte_data(client, 0, 209 PMBUS_STATUS_MFR_SPECIFIC); 210 if (ret < 0) 211 break; 212 213 status = 0; 214 if (ret & VMON_UV_WARNING) 215 status |= PB_VOLTAGE_UV_WARNING; 216 if (ret & VMON_OV_WARNING) 217 status |= PB_VOLTAGE_OV_WARNING; 218 if (ret & VMON_UV_FAULT) 219 status |= PB_VOLTAGE_UV_FAULT; 220 if (ret & VMON_OV_FAULT) 221 status |= PB_VOLTAGE_OV_FAULT; 222 ret = status; 223 break; 224 default: 225 ret = pmbus_read_byte_data(client, page, reg); 226 break; 227 } 228 data->access = ktime_get(); 229 230 return ret; 231} 232 233static int zl6100_write_word_data(struct i2c_client *client, int page, int reg, 234 u16 word) 235{ 236 const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 237 struct zl6100_data *data = to_zl6100_data(info); 238 int ret, vreg; 239 240 if (page >= info->pages) 241 return -ENXIO; 242 243 switch (reg) { 244 case PMBUS_VIRT_VMON_OV_WARN_LIMIT: 245 word = zl6100_d2l(DIV_ROUND_CLOSEST(zl6100_l2d(word) * 10, 9)); 246 vreg = MFR_VMON_OV_FAULT_LIMIT; 247 pmbus_clear_cache(client); 248 break; 249 case PMBUS_VIRT_VMON_OV_FAULT_LIMIT: 250 vreg = MFR_VMON_OV_FAULT_LIMIT; 251 pmbus_clear_cache(client); 252 break; 253 case PMBUS_VIRT_VMON_UV_WARN_LIMIT: 254 word = zl6100_d2l(DIV_ROUND_CLOSEST(zl6100_l2d(word) * 10, 11)); 255 vreg = MFR_VMON_UV_FAULT_LIMIT; 256 pmbus_clear_cache(client); 257 break; 258 case PMBUS_VIRT_VMON_UV_FAULT_LIMIT: 259 vreg = MFR_VMON_UV_FAULT_LIMIT; 260 pmbus_clear_cache(client); 261 break; 262 default: 263 if (reg >= PMBUS_VIRT_BASE) 264 return -ENXIO; 265 vreg = reg; 266 } 267 268 zl6100_wait(data); 269 ret = pmbus_write_word_data(client, page, vreg, word); 270 data->access = ktime_get(); 271 272 return ret; 273} 274 275static int zl6100_write_byte(struct i2c_client *client, int page, u8 value) 276{ 277 const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 278 struct zl6100_data *data = to_zl6100_data(info); 279 int ret; 280 281 if (page >= info->pages) 282 return -ENXIO; 283 284 zl6100_wait(data); 285 ret = pmbus_write_byte(client, page, value); 286 data->access = ktime_get(); 287 288 return ret; 289} 290 291static const struct i2c_device_id zl6100_id[] = { 292 {"bmr450", zl2005}, 293 {"bmr451", zl2005}, 294 {"bmr462", zl2008}, 295 {"bmr463", zl2008}, 296 {"bmr464", zl2008}, 297 {"bmr465", zls4009}, 298 {"bmr466", zls1003}, 299 {"bmr467", zls4009}, 300 {"bmr469", zl8802}, 301 {"zl2004", zl2004}, 302 {"zl2005", zl2005}, 303 {"zl2006", zl2006}, 304 {"zl2008", zl2008}, 305 {"zl2105", zl2105}, 306 {"zl2106", zl2106}, 307 {"zl6100", zl6100}, 308 {"zl6105", zl6105}, 309 {"zl8802", zl8802}, 310 {"zl9101", zl9101}, 311 {"zl9117", zl9117}, 312 {"zls1003", zls1003}, 313 {"zls4009", zls4009}, 314 { } 315}; 316MODULE_DEVICE_TABLE(i2c, zl6100_id); 317 318static int zl6100_probe(struct i2c_client *client) 319{ 320 int ret, i; 321 struct zl6100_data *data; 322 struct pmbus_driver_info *info; 323 u8 device_id[I2C_SMBUS_BLOCK_MAX + 1]; 324 const struct i2c_device_id *mid; 325 326 if (!i2c_check_functionality(client->adapter, 327 I2C_FUNC_SMBUS_READ_WORD_DATA 328 | I2C_FUNC_SMBUS_READ_BLOCK_DATA)) 329 return -ENODEV; 330 331 ret = i2c_smbus_read_block_data(client, ZL6100_DEVICE_ID, 332 device_id); 333 if (ret < 0) { 334 dev_err(&client->dev, "Failed to read device ID\n"); 335 return ret; 336 } 337 device_id[ret] = '\0'; 338 dev_info(&client->dev, "Device ID %s\n", device_id); 339 340 mid = NULL; 341 for (mid = zl6100_id; mid->name[0]; mid++) { 342 if (!strncasecmp(mid->name, device_id, strlen(mid->name))) 343 break; 344 } 345 if (!mid->name[0]) { 346 dev_err(&client->dev, "Unsupported device\n"); 347 return -ENODEV; 348 } 349 if (strcmp(client->name, mid->name) != 0) 350 dev_notice(&client->dev, 351 "Device mismatch: Configured %s, detected %s\n", 352 client->name, mid->name); 353 354 data = devm_kzalloc(&client->dev, sizeof(struct zl6100_data), 355 GFP_KERNEL); 356 if (!data) 357 return -ENOMEM; 358 359 data->id = mid->driver_data; 360 361 /* 362 * According to information from the chip vendor, all currently 363 * supported chips are known to require a wait time between I2C 364 * accesses. 365 */ 366 data->delay = delay; 367 368 /* 369 * Since there was a direct I2C device access above, wait before 370 * accessing the chip again. 371 */ 372 data->access = ktime_get(); 373 zl6100_wait(data); 374 375 info = &data->info; 376 377 info->pages = 1; 378 info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT 379 | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 380 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT 381 | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; 382 383 /* 384 * ZL2004, ZL8802, ZL9101M, ZL9117M and ZLS4009 support monitoring 385 * an extra voltage (VMON for ZL2004, ZL8802 and ZLS4009, 386 * VDRV for ZL9101M and ZL9117M). Report it as vmon. 387 */ 388 if (data->id == zl2004 || data->id == zl8802 || data->id == zl9101 || 389 data->id == zl9117 || data->id == zls4009) 390 info->func[0] |= PMBUS_HAVE_VMON | PMBUS_HAVE_STATUS_VMON; 391 392 /* 393 * ZL8802 has two outputs that can be used either independently or in 394 * a current sharing configuration. The driver uses the DDC_CONFIG 395 * register to check if the module is running with independent or 396 * shared outputs. If the module is in shared output mode, only one 397 * output voltage will be reported. 398 */ 399 if (data->id == zl8802) { 400 info->pages = 2; 401 info->func[0] |= PMBUS_HAVE_IIN; 402 403 ret = i2c_smbus_read_word_data(client, ZL8802_MFR_DDC_CONFIG); 404 if (ret < 0) 405 return ret; 406 407 data->access = ktime_get(); 408 zl6100_wait(data); 409 410 if (ret & ZL8802_MFR_PHASES_MASK) 411 info->func[1] |= PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT; 412 else 413 info->func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 414 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT; 415 416 for (i = 0; i < 2; i++) { 417 ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, i); 418 if (ret < 0) 419 return ret; 420 421 data->access = ktime_get(); 422 zl6100_wait(data); 423 424 ret = i2c_smbus_read_word_data(client, ZL8802_MFR_USER_CONFIG); 425 if (ret < 0) 426 return ret; 427 428 if (ret & ZL8802_MFR_XTEMP_ENABLE_2) 429 info->func[i] |= PMBUS_HAVE_TEMP2; 430 431 data->access = ktime_get(); 432 zl6100_wait(data); 433 } 434 ret = i2c_smbus_read_word_data(client, ZL8802_MFR_USER_GLOBAL_CONFIG); 435 if (ret < 0) 436 return ret; 437 438 if (ret & ZL8802_MFR_TMON_ENABLE) 439 info->func[0] |= PMBUS_HAVE_TEMP3; 440 } else { 441 ret = i2c_smbus_read_word_data(client, ZL6100_MFR_CONFIG); 442 if (ret < 0) 443 return ret; 444 445 if (ret & ZL6100_MFR_XTEMP_ENABLE) 446 info->func[0] |= PMBUS_HAVE_TEMP2; 447 } 448 449 data->access = ktime_get(); 450 zl6100_wait(data); 451 452 info->read_word_data = zl6100_read_word_data; 453 info->read_byte_data = zl6100_read_byte_data; 454 info->write_word_data = zl6100_write_word_data; 455 info->write_byte = zl6100_write_byte; 456 457 return pmbus_do_probe(client, info); 458} 459 460static struct i2c_driver zl6100_driver = { 461 .driver = { 462 .name = "zl6100", 463 }, 464 .probe_new = zl6100_probe, 465 .id_table = zl6100_id, 466}; 467 468module_i2c_driver(zl6100_driver); 469 470MODULE_AUTHOR("Guenter Roeck"); 471MODULE_DESCRIPTION("PMBus driver for ZL6100 and compatibles"); 472MODULE_LICENSE("GPL"); 473MODULE_IMPORT_NS(PMBUS);