1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright 2017 IBM Corp. 4 */ 5 6 #include <linux/bitfield.h> 7 #include <linux/bitops.h> 8 #include <linux/debugfs.h> 9 #include <linux/device.h> 10 #include <linux/fs.h> 11 #include <linux/i2c.h> 12 #include <linux/jiffies.h> 13 #include <linux/leds.h> 14 #include <linux/module.h> 15 #include <linux/mutex.h> 16 #include <linux/of_device.h> 17 #include <linux/pmbus.h> 18 19 #include "pmbus.h" 20 21 #define CFFPS_FRU_CMD 0x9A 22 #define CFFPS_PN_CMD 0x9B 23 #define CFFPS_HEADER_CMD 0x9C 24 #define CFFPS_SN_CMD 0x9E 25 #define CFFPS_MAX_POWER_OUT_CMD 0xA7 26 #define CFFPS_CCIN_CMD 0xBD 27 #define CFFPS_FW_CMD 0xFA 28 #define CFFPS1_FW_NUM_BYTES 4 29 #define CFFPS2_FW_NUM_WORDS 3 30 #define CFFPS_SYS_CONFIG_CMD 0xDA 31 #define CFFPS_12VCS_VOUT_CMD 0xDE 32 33 #define CFFPS_INPUT_HISTORY_CMD 0xD6 34 #define CFFPS_INPUT_HISTORY_SIZE 100 35 36 #define CFFPS_CCIN_REVISION GENMASK(7, 0) 37 #define CFFPS_CCIN_REVISION_LEGACY 0xde 38 #define CFFPS_CCIN_VERSION GENMASK(15, 8) 39 #define CFFPS_CCIN_VERSION_1 0x2b 40 #define CFFPS_CCIN_VERSION_2 0x2e 41 #define CFFPS_CCIN_VERSION_3 0x51 42 43 /* STATUS_MFR_SPECIFIC bits */ 44 #define CFFPS_MFR_FAN_FAULT BIT(0) 45 #define CFFPS_MFR_THERMAL_FAULT BIT(1) 46 #define CFFPS_MFR_OV_FAULT BIT(2) 47 #define CFFPS_MFR_UV_FAULT BIT(3) 48 #define CFFPS_MFR_PS_KILL BIT(4) 49 #define CFFPS_MFR_OC_FAULT BIT(5) 50 #define CFFPS_MFR_VAUX_FAULT BIT(6) 51 #define CFFPS_MFR_CURRENT_SHARE_WARNING BIT(7) 52 53 #define CFFPS_LED_BLINK BIT(0) 54 #define CFFPS_LED_ON BIT(1) 55 #define CFFPS_LED_OFF BIT(2) 56 #define CFFPS_BLINK_RATE_MS 250 57 58 enum { 59 CFFPS_DEBUGFS_INPUT_HISTORY = 0, 60 CFFPS_DEBUGFS_FRU, 61 CFFPS_DEBUGFS_PN, 62 CFFPS_DEBUGFS_HEADER, 63 CFFPS_DEBUGFS_SN, 64 CFFPS_DEBUGFS_MAX_POWER_OUT, 65 CFFPS_DEBUGFS_CCIN, 66 CFFPS_DEBUGFS_FW, 67 CFFPS_DEBUGFS_ON_OFF_CONFIG, 68 CFFPS_DEBUGFS_NUM_ENTRIES 69 }; 70 71 enum versions { cffps1, cffps2, cffps_unknown }; 72 73 struct ibm_cffps_input_history { 74 struct mutex update_lock; 75 unsigned long last_update; 76 77 u8 byte_count; 78 u8 data[CFFPS_INPUT_HISTORY_SIZE]; 79 }; 80 81 struct ibm_cffps { 82 enum versions version; 83 struct i2c_client *client; 84 85 struct ibm_cffps_input_history input_history; 86 87 int debugfs_entries[CFFPS_DEBUGFS_NUM_ENTRIES]; 88 89 char led_name[32]; 90 u8 led_state; 91 struct led_classdev led; 92 }; 93 94 static const struct i2c_device_id ibm_cffps_id[]; 95 96 #define to_psu(x, y) container_of((x), struct ibm_cffps, debugfs_entries[(y)]) 97 98 static ssize_t ibm_cffps_read_input_history(struct ibm_cffps *psu, 99 char __user *buf, size_t count, 100 loff_t *ppos) 101 { 102 int rc; 103 u8 msgbuf0[1] = { CFFPS_INPUT_HISTORY_CMD }; 104 u8 msgbuf1[CFFPS_INPUT_HISTORY_SIZE + 1] = { 0 }; 105 struct i2c_msg msg[2] = { 106 { 107 .addr = psu->client->addr, 108 .flags = psu->client->flags, 109 .len = 1, 110 .buf = msgbuf0, 111 }, { 112 .addr = psu->client->addr, 113 .flags = psu->client->flags | I2C_M_RD, 114 .len = CFFPS_INPUT_HISTORY_SIZE + 1, 115 .buf = msgbuf1, 116 }, 117 }; 118 119 if (!*ppos) { 120 mutex_lock(&psu->input_history.update_lock); 121 if (time_after(jiffies, psu->input_history.last_update + HZ)) { 122 /* 123 * Use a raw i2c transfer, since we need more bytes 124 * than Linux I2C supports through smbus xfr (only 32). 125 */ 126 rc = i2c_transfer(psu->client->adapter, msg, 2); 127 if (rc < 0) { 128 mutex_unlock(&psu->input_history.update_lock); 129 return rc; 130 } 131 132 psu->input_history.byte_count = msgbuf1[0]; 133 memcpy(psu->input_history.data, &msgbuf1[1], 134 CFFPS_INPUT_HISTORY_SIZE); 135 psu->input_history.last_update = jiffies; 136 } 137 138 mutex_unlock(&psu->input_history.update_lock); 139 } 140 141 return simple_read_from_buffer(buf, count, ppos, 142 psu->input_history.data, 143 psu->input_history.byte_count); 144 } 145 146 static ssize_t ibm_cffps_debugfs_read(struct file *file, char __user *buf, 147 size_t count, loff_t *ppos) 148 { 149 u8 cmd; 150 int i, rc; 151 int *idxp = file->private_data; 152 int idx = *idxp; 153 struct ibm_cffps *psu = to_psu(idxp, idx); 154 char data[I2C_SMBUS_BLOCK_MAX + 2] = { 0 }; 155 156 pmbus_set_page(psu->client, 0, 0xff); 157 158 switch (idx) { 159 case CFFPS_DEBUGFS_INPUT_HISTORY: 160 return ibm_cffps_read_input_history(psu, buf, count, ppos); 161 case CFFPS_DEBUGFS_FRU: 162 cmd = CFFPS_FRU_CMD; 163 break; 164 case CFFPS_DEBUGFS_PN: 165 cmd = CFFPS_PN_CMD; 166 break; 167 case CFFPS_DEBUGFS_HEADER: 168 cmd = CFFPS_HEADER_CMD; 169 break; 170 case CFFPS_DEBUGFS_SN: 171 cmd = CFFPS_SN_CMD; 172 break; 173 case CFFPS_DEBUGFS_MAX_POWER_OUT: 174 rc = i2c_smbus_read_word_swapped(psu->client, 175 CFFPS_MAX_POWER_OUT_CMD); 176 if (rc < 0) 177 return rc; 178 179 rc = snprintf(data, I2C_SMBUS_BLOCK_MAX, "%d", rc); 180 goto done; 181 case CFFPS_DEBUGFS_CCIN: 182 rc = i2c_smbus_read_word_swapped(psu->client, CFFPS_CCIN_CMD); 183 if (rc < 0) 184 return rc; 185 186 rc = snprintf(data, 5, "%04X", rc); 187 goto done; 188 case CFFPS_DEBUGFS_FW: 189 switch (psu->version) { 190 case cffps1: 191 for (i = 0; i < CFFPS1_FW_NUM_BYTES; ++i) { 192 rc = i2c_smbus_read_byte_data(psu->client, 193 CFFPS_FW_CMD + 194 i); 195 if (rc < 0) 196 return rc; 197 198 snprintf(&data[i * 2], 3, "%02X", rc); 199 } 200 201 rc = i * 2; 202 break; 203 case cffps2: 204 for (i = 0; i < CFFPS2_FW_NUM_WORDS; ++i) { 205 rc = i2c_smbus_read_word_data(psu->client, 206 CFFPS_FW_CMD + 207 i); 208 if (rc < 0) 209 return rc; 210 211 snprintf(&data[i * 4], 5, "%04X", rc); 212 } 213 214 rc = i * 4; 215 break; 216 default: 217 return -EOPNOTSUPP; 218 } 219 goto done; 220 case CFFPS_DEBUGFS_ON_OFF_CONFIG: 221 rc = i2c_smbus_read_byte_data(psu->client, 222 PMBUS_ON_OFF_CONFIG); 223 if (rc < 0) 224 return rc; 225 226 rc = snprintf(data, 3, "%02x", rc); 227 goto done; 228 default: 229 return -EINVAL; 230 } 231 232 rc = i2c_smbus_read_block_data(psu->client, cmd, data); 233 if (rc < 0) 234 return rc; 235 236 done: 237 data[rc] = '\n'; 238 rc += 2; 239 240 return simple_read_from_buffer(buf, count, ppos, data, rc); 241 } 242 243 static ssize_t ibm_cffps_debugfs_write(struct file *file, 244 const char __user *buf, size_t count, 245 loff_t *ppos) 246 { 247 u8 data; 248 ssize_t rc; 249 int *idxp = file->private_data; 250 int idx = *idxp; 251 struct ibm_cffps *psu = to_psu(idxp, idx); 252 253 switch (idx) { 254 case CFFPS_DEBUGFS_ON_OFF_CONFIG: 255 pmbus_set_page(psu->client, 0, 0xff); 256 257 rc = simple_write_to_buffer(&data, 1, ppos, buf, count); 258 if (rc <= 0) 259 return rc; 260 261 rc = i2c_smbus_write_byte_data(psu->client, 262 PMBUS_ON_OFF_CONFIG, data); 263 if (rc) 264 return rc; 265 266 rc = 1; 267 break; 268 default: 269 return -EINVAL; 270 } 271 272 return rc; 273 } 274 275 static const struct file_operations ibm_cffps_fops = { 276 .llseek = noop_llseek, 277 .read = ibm_cffps_debugfs_read, 278 .write = ibm_cffps_debugfs_write, 279 .open = simple_open, 280 }; 281 282 static int ibm_cffps_read_byte_data(struct i2c_client *client, int page, 283 int reg) 284 { 285 int rc, mfr; 286 287 switch (reg) { 288 case PMBUS_STATUS_VOUT: 289 case PMBUS_STATUS_IOUT: 290 case PMBUS_STATUS_TEMPERATURE: 291 case PMBUS_STATUS_FAN_12: 292 rc = pmbus_read_byte_data(client, page, reg); 293 if (rc < 0) 294 return rc; 295 296 mfr = pmbus_read_byte_data(client, page, 297 PMBUS_STATUS_MFR_SPECIFIC); 298 if (mfr < 0) 299 /* 300 * Return the status register instead of an error, 301 * since we successfully read status. 302 */ 303 return rc; 304 305 /* Add MFR_SPECIFIC bits to the standard pmbus status regs. */ 306 if (reg == PMBUS_STATUS_FAN_12) { 307 if (mfr & CFFPS_MFR_FAN_FAULT) 308 rc |= PB_FAN_FAN1_FAULT; 309 } else if (reg == PMBUS_STATUS_TEMPERATURE) { 310 if (mfr & CFFPS_MFR_THERMAL_FAULT) 311 rc |= PB_TEMP_OT_FAULT; 312 } else if (reg == PMBUS_STATUS_VOUT) { 313 if (mfr & (CFFPS_MFR_OV_FAULT | CFFPS_MFR_VAUX_FAULT)) 314 rc |= PB_VOLTAGE_OV_FAULT; 315 if (mfr & CFFPS_MFR_UV_FAULT) 316 rc |= PB_VOLTAGE_UV_FAULT; 317 } else if (reg == PMBUS_STATUS_IOUT) { 318 if (mfr & CFFPS_MFR_OC_FAULT) 319 rc |= PB_IOUT_OC_FAULT; 320 if (mfr & CFFPS_MFR_CURRENT_SHARE_WARNING) 321 rc |= PB_CURRENT_SHARE_FAULT; 322 } 323 break; 324 default: 325 rc = -ENODATA; 326 break; 327 } 328 329 return rc; 330 } 331 332 static int ibm_cffps_read_word_data(struct i2c_client *client, int page, 333 int phase, int reg) 334 { 335 int rc, mfr; 336 337 switch (reg) { 338 case PMBUS_STATUS_WORD: 339 rc = pmbus_read_word_data(client, page, phase, reg); 340 if (rc < 0) 341 return rc; 342 343 mfr = pmbus_read_byte_data(client, page, 344 PMBUS_STATUS_MFR_SPECIFIC); 345 if (mfr < 0) 346 /* 347 * Return the status register instead of an error, 348 * since we successfully read status. 349 */ 350 return rc; 351 352 if (mfr & CFFPS_MFR_PS_KILL) 353 rc |= PB_STATUS_OFF; 354 break; 355 case PMBUS_VIRT_READ_VMON: 356 rc = pmbus_read_word_data(client, page, phase, 357 CFFPS_12VCS_VOUT_CMD); 358 break; 359 default: 360 rc = -ENODATA; 361 break; 362 } 363 364 return rc; 365 } 366 367 static int ibm_cffps_led_brightness_set(struct led_classdev *led_cdev, 368 enum led_brightness brightness) 369 { 370 int rc; 371 u8 next_led_state; 372 struct ibm_cffps *psu = container_of(led_cdev, struct ibm_cffps, led); 373 374 if (brightness == LED_OFF) { 375 next_led_state = CFFPS_LED_OFF; 376 } else { 377 brightness = LED_FULL; 378 379 if (psu->led_state != CFFPS_LED_BLINK) 380 next_led_state = CFFPS_LED_ON; 381 else 382 next_led_state = CFFPS_LED_BLINK; 383 } 384 385 dev_dbg(&psu->client->dev, "LED brightness set: %d. Command: %d.\n", 386 brightness, next_led_state); 387 388 pmbus_set_page(psu->client, 0, 0xff); 389 390 rc = i2c_smbus_write_byte_data(psu->client, CFFPS_SYS_CONFIG_CMD, 391 next_led_state); 392 if (rc < 0) 393 return rc; 394 395 psu->led_state = next_led_state; 396 led_cdev->brightness = brightness; 397 398 return 0; 399 } 400 401 static int ibm_cffps_led_blink_set(struct led_classdev *led_cdev, 402 unsigned long *delay_on, 403 unsigned long *delay_off) 404 { 405 int rc; 406 struct ibm_cffps *psu = container_of(led_cdev, struct ibm_cffps, led); 407 408 dev_dbg(&psu->client->dev, "LED blink set.\n"); 409 410 pmbus_set_page(psu->client, 0, 0xff); 411 412 rc = i2c_smbus_write_byte_data(psu->client, CFFPS_SYS_CONFIG_CMD, 413 CFFPS_LED_BLINK); 414 if (rc < 0) 415 return rc; 416 417 psu->led_state = CFFPS_LED_BLINK; 418 led_cdev->brightness = LED_FULL; 419 *delay_on = CFFPS_BLINK_RATE_MS; 420 *delay_off = CFFPS_BLINK_RATE_MS; 421 422 return 0; 423 } 424 425 static void ibm_cffps_create_led_class(struct ibm_cffps *psu) 426 { 427 int rc; 428 struct i2c_client *client = psu->client; 429 struct device *dev = &client->dev; 430 431 snprintf(psu->led_name, sizeof(psu->led_name), "%s-%02x", client->name, 432 client->addr); 433 psu->led.name = psu->led_name; 434 psu->led.max_brightness = LED_FULL; 435 psu->led.brightness_set_blocking = ibm_cffps_led_brightness_set; 436 psu->led.blink_set = ibm_cffps_led_blink_set; 437 438 rc = devm_led_classdev_register(dev, &psu->led); 439 if (rc) 440 dev_warn(dev, "failed to register led class: %d\n", rc); 441 else 442 i2c_smbus_write_byte_data(client, CFFPS_SYS_CONFIG_CMD, 443 CFFPS_LED_OFF); 444 } 445 446 static struct pmbus_driver_info ibm_cffps_info[] = { 447 [cffps1] = { 448 .pages = 1, 449 .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT | 450 PMBUS_HAVE_PIN | PMBUS_HAVE_FAN12 | PMBUS_HAVE_TEMP | 451 PMBUS_HAVE_TEMP2 | PMBUS_HAVE_TEMP3 | 452 PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT | 453 PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP | 454 PMBUS_HAVE_STATUS_FAN12, 455 .read_byte_data = ibm_cffps_read_byte_data, 456 .read_word_data = ibm_cffps_read_word_data, 457 }, 458 [cffps2] = { 459 .pages = 2, 460 .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT | 461 PMBUS_HAVE_PIN | PMBUS_HAVE_FAN12 | PMBUS_HAVE_TEMP | 462 PMBUS_HAVE_TEMP2 | PMBUS_HAVE_TEMP3 | 463 PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT | 464 PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP | 465 PMBUS_HAVE_STATUS_FAN12 | PMBUS_HAVE_VMON, 466 .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT | 467 PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_TEMP3 | 468 PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT, 469 .read_byte_data = ibm_cffps_read_byte_data, 470 .read_word_data = ibm_cffps_read_word_data, 471 }, 472 }; 473 474 static struct pmbus_platform_data ibm_cffps_pdata = { 475 .flags = PMBUS_SKIP_STATUS_CHECK, 476 }; 477 478 static int ibm_cffps_probe(struct i2c_client *client) 479 { 480 int i, rc; 481 enum versions vs = cffps_unknown; 482 struct dentry *debugfs; 483 struct dentry *ibm_cffps_dir; 484 struct ibm_cffps *psu; 485 const void *md = of_device_get_match_data(&client->dev); 486 const struct i2c_device_id *id; 487 488 if (md) { 489 vs = (enum versions)md; 490 } else { 491 id = i2c_match_id(ibm_cffps_id, client); 492 if (id) 493 vs = (enum versions)id->driver_data; 494 } 495 496 if (vs == cffps_unknown) { 497 u16 ccin_revision = 0; 498 u16 ccin_version = CFFPS_CCIN_VERSION_1; 499 int ccin = i2c_smbus_read_word_swapped(client, CFFPS_CCIN_CMD); 500 501 if (ccin > 0) { 502 ccin_revision = FIELD_GET(CFFPS_CCIN_REVISION, ccin); 503 ccin_version = FIELD_GET(CFFPS_CCIN_VERSION, ccin); 504 } 505 506 switch (ccin_version) { 507 default: 508 case CFFPS_CCIN_VERSION_1: 509 vs = cffps1; 510 break; 511 case CFFPS_CCIN_VERSION_2: 512 vs = cffps2; 513 break; 514 case CFFPS_CCIN_VERSION_3: 515 if (ccin_revision == CFFPS_CCIN_REVISION_LEGACY) 516 vs = cffps1; 517 else 518 vs = cffps2; 519 break; 520 } 521 522 /* Set the client name to include the version number. */ 523 snprintf(client->name, I2C_NAME_SIZE, "cffps%d", vs + 1); 524 } 525 526 client->dev.platform_data = &ibm_cffps_pdata; 527 rc = pmbus_do_probe(client, &ibm_cffps_info[vs]); 528 if (rc) 529 return rc; 530 531 /* 532 * Don't fail the probe if there isn't enough memory for leds and 533 * debugfs. 534 */ 535 psu = devm_kzalloc(&client->dev, sizeof(*psu), GFP_KERNEL); 536 if (!psu) 537 return 0; 538 539 psu->version = vs; 540 psu->client = client; 541 mutex_init(&psu->input_history.update_lock); 542 psu->input_history.last_update = jiffies - HZ; 543 544 ibm_cffps_create_led_class(psu); 545 546 /* Don't fail the probe if we can't create debugfs */ 547 debugfs = pmbus_get_debugfs_dir(client); 548 if (!debugfs) 549 return 0; 550 551 ibm_cffps_dir = debugfs_create_dir(client->name, debugfs); 552 if (!ibm_cffps_dir) 553 return 0; 554 555 for (i = 0; i < CFFPS_DEBUGFS_NUM_ENTRIES; ++i) 556 psu->debugfs_entries[i] = i; 557 558 debugfs_create_file("input_history", 0444, ibm_cffps_dir, 559 &psu->debugfs_entries[CFFPS_DEBUGFS_INPUT_HISTORY], 560 &ibm_cffps_fops); 561 debugfs_create_file("fru", 0444, ibm_cffps_dir, 562 &psu->debugfs_entries[CFFPS_DEBUGFS_FRU], 563 &ibm_cffps_fops); 564 debugfs_create_file("part_number", 0444, ibm_cffps_dir, 565 &psu->debugfs_entries[CFFPS_DEBUGFS_PN], 566 &ibm_cffps_fops); 567 debugfs_create_file("header", 0444, ibm_cffps_dir, 568 &psu->debugfs_entries[CFFPS_DEBUGFS_HEADER], 569 &ibm_cffps_fops); 570 debugfs_create_file("serial_number", 0444, ibm_cffps_dir, 571 &psu->debugfs_entries[CFFPS_DEBUGFS_SN], 572 &ibm_cffps_fops); 573 debugfs_create_file("max_power_out", 0444, ibm_cffps_dir, 574 &psu->debugfs_entries[CFFPS_DEBUGFS_MAX_POWER_OUT], 575 &ibm_cffps_fops); 576 debugfs_create_file("ccin", 0444, ibm_cffps_dir, 577 &psu->debugfs_entries[CFFPS_DEBUGFS_CCIN], 578 &ibm_cffps_fops); 579 debugfs_create_file("fw_version", 0444, ibm_cffps_dir, 580 &psu->debugfs_entries[CFFPS_DEBUGFS_FW], 581 &ibm_cffps_fops); 582 debugfs_create_file("on_off_config", 0644, ibm_cffps_dir, 583 &psu->debugfs_entries[CFFPS_DEBUGFS_ON_OFF_CONFIG], 584 &ibm_cffps_fops); 585 586 return 0; 587 } 588 589 static const struct i2c_device_id ibm_cffps_id[] = { 590 { "ibm_cffps1", cffps1 }, 591 { "ibm_cffps2", cffps2 }, 592 { "ibm_cffps", cffps_unknown }, 593 {} 594 }; 595 MODULE_DEVICE_TABLE(i2c, ibm_cffps_id); 596 597 static const struct of_device_id ibm_cffps_of_match[] = { 598 { 599 .compatible = "ibm,cffps1", 600 .data = (void *)cffps1 601 }, 602 { 603 .compatible = "ibm,cffps2", 604 .data = (void *)cffps2 605 }, 606 { 607 .compatible = "ibm,cffps", 608 .data = (void *)cffps_unknown 609 }, 610 {} 611 }; 612 MODULE_DEVICE_TABLE(of, ibm_cffps_of_match); 613 614 static struct i2c_driver ibm_cffps_driver = { 615 .driver = { 616 .name = "ibm-cffps", 617 .of_match_table = ibm_cffps_of_match, 618 }, 619 .probe_new = ibm_cffps_probe, 620 .remove = pmbus_do_remove, 621 .id_table = ibm_cffps_id, 622 }; 623 624 module_i2c_driver(ibm_cffps_driver); 625 626 MODULE_AUTHOR("Eddie James"); 627 MODULE_DESCRIPTION("PMBus driver for IBM Common Form Factor power supplies"); 628 MODULE_LICENSE("GPL"); 629