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