1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* 3 * CEC driver for SECO X86 Boards 4 * 5 * Author: Ettore Chimenti <ek5.chimenti@gmail.com> 6 * Copyright (C) 2018, SECO SpA. 7 * Copyright (C) 2018, Aidilab Srl. 8 */ 9 10 #include <linux/module.h> 11 #include <linux/acpi.h> 12 #include <linux/delay.h> 13 #include <linux/dmi.h> 14 #include <linux/gpio/consumer.h> 15 #include <linux/interrupt.h> 16 #include <linux/pci.h> 17 #include <linux/platform_device.h> 18 19 /* CEC Framework */ 20 #include <media/cec-notifier.h> 21 22 #include "seco-cec.h" 23 24 struct secocec_data { 25 struct device *dev; 26 struct platform_device *pdev; 27 struct cec_adapter *cec_adap; 28 struct cec_notifier *notifier; 29 struct rc_dev *ir; 30 char ir_input_phys[32]; 31 int irq; 32 }; 33 34 #define smb_wr16(cmd, data) smb_word_op(CMD_WORD_DATA, SECOCEC_MICRO_ADDRESS, \ 35 cmd, data, SMBUS_WRITE, NULL) 36 #define smb_rd16(cmd, res) smb_word_op(CMD_WORD_DATA, SECOCEC_MICRO_ADDRESS, \ 37 cmd, 0, SMBUS_READ, res) 38 39 static int smb_word_op(short data_format, u16 slave_addr, u8 cmd, u16 data, 40 u8 operation, u16 *result) 41 { 42 unsigned int count; 43 short _data_format; 44 int status = 0; 45 46 switch (data_format) { 47 case CMD_BYTE_DATA: 48 _data_format = BRA_SMB_CMD_BYTE_DATA; 49 break; 50 case CMD_WORD_DATA: 51 _data_format = BRA_SMB_CMD_WORD_DATA; 52 break; 53 default: 54 return -EINVAL; 55 } 56 57 /* Active wait until ready */ 58 for (count = 0; count <= SMBTIMEOUT; ++count) { 59 if (!(inb(HSTS) & BRA_INUSE_STS)) 60 break; 61 udelay(SMB_POLL_UDELAY); 62 } 63 64 if (count > SMBTIMEOUT) 65 /* Reset the lock instead of failing */ 66 outb(0xff, HSTS); 67 68 outb(0x00, HCNT); 69 outb((u8)(slave_addr & 0xfe) | operation, XMIT_SLVA); 70 outb(cmd, HCMD); 71 inb(HCNT); 72 73 if (operation == SMBUS_WRITE) { 74 outb((u8)data, HDAT0); 75 outb((u8)(data >> 8), HDAT1); 76 } 77 78 outb(BRA_START + _data_format, HCNT); 79 80 for (count = 0; count <= SMBTIMEOUT; count++) { 81 if (!(inb(HSTS) & BRA_HOST_BUSY)) 82 break; 83 udelay(SMB_POLL_UDELAY); 84 } 85 86 if (count > SMBTIMEOUT) { 87 status = -EBUSY; 88 goto err; 89 } 90 91 if (inb(HSTS) & BRA_HSTS_ERR_MASK) { 92 status = -EIO; 93 goto err; 94 } 95 96 if (operation == SMBUS_READ) 97 *result = ((inb(HDAT0) & 0xff) + ((inb(HDAT1) & 0xff) << 8)); 98 99 err: 100 outb(0xff, HSTS); 101 return status; 102 } 103 104 static int secocec_adap_enable(struct cec_adapter *adap, bool enable) 105 { 106 struct secocec_data *cec = cec_get_drvdata(adap); 107 struct device *dev = cec->dev; 108 u16 val = 0; 109 int status; 110 111 if (enable) { 112 /* Clear the status register */ 113 status = smb_rd16(SECOCEC_STATUS_REG_1, &val); 114 if (status) 115 goto err; 116 117 status = smb_wr16(SECOCEC_STATUS_REG_1, val); 118 if (status) 119 goto err; 120 121 /* Enable the interrupts */ 122 status = smb_rd16(SECOCEC_ENABLE_REG_1, &val); 123 if (status) 124 goto err; 125 126 status = smb_wr16(SECOCEC_ENABLE_REG_1, 127 val | SECOCEC_ENABLE_REG_1_CEC); 128 if (status) 129 goto err; 130 131 dev_dbg(dev, "Device enabled\n"); 132 } else { 133 /* Clear the status register */ 134 status = smb_rd16(SECOCEC_STATUS_REG_1, &val); 135 status = smb_wr16(SECOCEC_STATUS_REG_1, val); 136 137 /* Disable the interrupts */ 138 status = smb_rd16(SECOCEC_ENABLE_REG_1, &val); 139 status = smb_wr16(SECOCEC_ENABLE_REG_1, val & 140 ~SECOCEC_ENABLE_REG_1_CEC & 141 ~SECOCEC_ENABLE_REG_1_IR); 142 143 dev_dbg(dev, "Device disabled\n"); 144 } 145 146 return 0; 147 err: 148 return status; 149 } 150 151 static int secocec_adap_log_addr(struct cec_adapter *adap, u8 logical_addr) 152 { 153 u16 enable_val = 0; 154 int status; 155 156 /* Disable device */ 157 status = smb_rd16(SECOCEC_ENABLE_REG_1, &enable_val); 158 if (status) 159 return status; 160 161 status = smb_wr16(SECOCEC_ENABLE_REG_1, 162 enable_val & ~SECOCEC_ENABLE_REG_1_CEC); 163 if (status) 164 return status; 165 166 /* Write logical address 167 * NOTE: CEC_LOG_ADDR_INVALID is mapped to the 'Unregistered' LA 168 */ 169 status = smb_wr16(SECOCEC_DEVICE_LA, logical_addr & 0xf); 170 if (status) 171 return status; 172 173 /* Re-enable device */ 174 status = smb_wr16(SECOCEC_ENABLE_REG_1, 175 enable_val | SECOCEC_ENABLE_REG_1_CEC); 176 if (status) 177 return status; 178 179 return 0; 180 } 181 182 static int secocec_adap_transmit(struct cec_adapter *adap, u8 attempts, 183 u32 signal_free_time, struct cec_msg *msg) 184 { 185 u16 payload_len, payload_id_len, destination, val = 0; 186 u8 *payload_msg; 187 int status; 188 u8 i; 189 190 /* Device msg len already accounts for header */ 191 payload_id_len = msg->len - 1; 192 193 /* Send data length */ 194 status = smb_wr16(SECOCEC_WRITE_DATA_LENGTH, payload_id_len); 195 if (status) 196 goto err; 197 198 /* Send Operation ID if present */ 199 if (payload_id_len > 0) { 200 status = smb_wr16(SECOCEC_WRITE_OPERATION_ID, msg->msg[1]); 201 if (status) 202 goto err; 203 } 204 /* Send data if present */ 205 if (payload_id_len > 1) { 206 /* Only data; */ 207 payload_len = msg->len - 2; 208 payload_msg = &msg->msg[2]; 209 210 /* Copy message into registers */ 211 for (i = 0; i < payload_len; i += 2) { 212 /* hi byte */ 213 val = payload_msg[i + 1] << 8; 214 215 /* lo byte */ 216 val |= payload_msg[i]; 217 218 status = smb_wr16(SECOCEC_WRITE_DATA_00 + i / 2, val); 219 if (status) 220 goto err; 221 } 222 } 223 /* Send msg source/destination and fire msg */ 224 destination = msg->msg[0]; 225 status = smb_wr16(SECOCEC_WRITE_BYTE0, destination); 226 if (status) 227 goto err; 228 229 return 0; 230 231 err: 232 return status; 233 } 234 235 static void secocec_tx_done(struct cec_adapter *adap, u16 status_val) 236 { 237 if (status_val & SECOCEC_STATUS_TX_ERROR_MASK) { 238 if (status_val & SECOCEC_STATUS_TX_NACK_ERROR) 239 cec_transmit_attempt_done(adap, CEC_TX_STATUS_NACK); 240 else 241 cec_transmit_attempt_done(adap, CEC_TX_STATUS_ERROR); 242 } else { 243 cec_transmit_attempt_done(adap, CEC_TX_STATUS_OK); 244 } 245 246 /* Reset status reg */ 247 status_val = SECOCEC_STATUS_TX_ERROR_MASK | 248 SECOCEC_STATUS_MSG_SENT_MASK | 249 SECOCEC_STATUS_TX_NACK_ERROR; 250 smb_wr16(SECOCEC_STATUS, status_val); 251 } 252 253 static void secocec_rx_done(struct cec_adapter *adap, u16 status_val) 254 { 255 struct secocec_data *cec = cec_get_drvdata(adap); 256 struct device *dev = cec->dev; 257 struct cec_msg msg = { }; 258 bool flag_overflow = false; 259 u8 payload_len, i = 0; 260 u8 *payload_msg; 261 u16 val = 0; 262 int status; 263 264 if (status_val & SECOCEC_STATUS_RX_OVERFLOW_MASK) { 265 /* NOTE: Untested, it also might not be necessary */ 266 dev_warn(dev, "Received more than 16 bytes. Discarding\n"); 267 flag_overflow = true; 268 } 269 270 if (status_val & SECOCEC_STATUS_RX_ERROR_MASK) { 271 dev_warn(dev, "Message received with errors. Discarding\n"); 272 status = -EIO; 273 goto rxerr; 274 } 275 276 /* Read message length */ 277 status = smb_rd16(SECOCEC_READ_DATA_LENGTH, &val); 278 if (status) 279 return; 280 281 /* Device msg len already accounts for the header */ 282 msg.len = min(val + 1, CEC_MAX_MSG_SIZE); 283 284 /* Read logical address */ 285 status = smb_rd16(SECOCEC_READ_BYTE0, &val); 286 if (status) 287 return; 288 289 /* device stores source LA and destination */ 290 msg.msg[0] = val; 291 292 /* Read operation ID */ 293 status = smb_rd16(SECOCEC_READ_OPERATION_ID, &val); 294 if (status) 295 return; 296 297 msg.msg[1] = val; 298 299 /* Read data if present */ 300 if (msg.len > 1) { 301 payload_len = msg.len - 2; 302 payload_msg = &msg.msg[2]; 303 304 /* device stores 2 bytes in every 16-bit val */ 305 for (i = 0; i < payload_len; i += 2) { 306 status = smb_rd16(SECOCEC_READ_DATA_00 + i / 2, &val); 307 if (status) 308 return; 309 310 /* low byte, skipping header */ 311 payload_msg[i] = val & 0x00ff; 312 313 /* hi byte */ 314 payload_msg[i + 1] = (val & 0xff00) >> 8; 315 } 316 } 317 318 cec_received_msg(cec->cec_adap, &msg); 319 320 /* Reset status reg */ 321 status_val = SECOCEC_STATUS_MSG_RECEIVED_MASK; 322 if (flag_overflow) 323 status_val |= SECOCEC_STATUS_RX_OVERFLOW_MASK; 324 325 status = smb_wr16(SECOCEC_STATUS, status_val); 326 327 return; 328 329 rxerr: 330 /* Reset error reg */ 331 status_val = SECOCEC_STATUS_MSG_RECEIVED_MASK | 332 SECOCEC_STATUS_RX_ERROR_MASK; 333 if (flag_overflow) 334 status_val |= SECOCEC_STATUS_RX_OVERFLOW_MASK; 335 smb_wr16(SECOCEC_STATUS, status_val); 336 } 337 338 static const struct cec_adap_ops secocec_cec_adap_ops = { 339 /* Low-level callbacks */ 340 .adap_enable = secocec_adap_enable, 341 .adap_log_addr = secocec_adap_log_addr, 342 .adap_transmit = secocec_adap_transmit, 343 }; 344 345 #ifdef CONFIG_CEC_SECO_RC 346 static int secocec_ir_probe(void *priv) 347 { 348 struct secocec_data *cec = priv; 349 struct device *dev = cec->dev; 350 int status; 351 u16 val; 352 353 /* Prepare the RC input device */ 354 cec->ir = devm_rc_allocate_device(dev, RC_DRIVER_SCANCODE); 355 if (!cec->ir) 356 return -ENOMEM; 357 358 snprintf(cec->ir_input_phys, sizeof(cec->ir_input_phys), 359 "%s/input0", dev_name(dev)); 360 361 cec->ir->device_name = dev_name(dev); 362 cec->ir->input_phys = cec->ir_input_phys; 363 cec->ir->input_id.bustype = BUS_HOST; 364 cec->ir->input_id.vendor = 0; 365 cec->ir->input_id.product = 0; 366 cec->ir->input_id.version = 1; 367 cec->ir->driver_name = SECOCEC_DEV_NAME; 368 cec->ir->allowed_protocols = RC_PROTO_BIT_RC5; 369 cec->ir->priv = cec; 370 cec->ir->map_name = RC_MAP_HAUPPAUGE; 371 cec->ir->timeout = MS_TO_US(100); 372 373 /* Clear the status register */ 374 status = smb_rd16(SECOCEC_STATUS_REG_1, &val); 375 if (status != 0) 376 goto err; 377 378 status = smb_wr16(SECOCEC_STATUS_REG_1, val); 379 if (status != 0) 380 goto err; 381 382 /* Enable the interrupts */ 383 status = smb_rd16(SECOCEC_ENABLE_REG_1, &val); 384 if (status != 0) 385 goto err; 386 387 status = smb_wr16(SECOCEC_ENABLE_REG_1, 388 val | SECOCEC_ENABLE_REG_1_IR); 389 if (status != 0) 390 goto err; 391 392 dev_dbg(dev, "IR enabled\n"); 393 394 status = devm_rc_register_device(dev, cec->ir); 395 396 if (status) { 397 dev_err(dev, "Failed to prepare input device\n"); 398 cec->ir = NULL; 399 goto err; 400 } 401 402 return 0; 403 404 err: 405 smb_rd16(SECOCEC_ENABLE_REG_1, &val); 406 407 smb_wr16(SECOCEC_ENABLE_REG_1, 408 val & ~SECOCEC_ENABLE_REG_1_IR); 409 410 dev_dbg(dev, "IR disabled\n"); 411 return status; 412 } 413 414 static int secocec_ir_rx(struct secocec_data *priv) 415 { 416 struct secocec_data *cec = priv; 417 struct device *dev = cec->dev; 418 u16 val, status, key, addr, toggle; 419 420 if (!cec->ir) 421 return -ENODEV; 422 423 status = smb_rd16(SECOCEC_IR_READ_DATA, &val); 424 if (status != 0) 425 goto err; 426 427 key = val & SECOCEC_IR_COMMAND_MASK; 428 addr = (val & SECOCEC_IR_ADDRESS_MASK) >> SECOCEC_IR_ADDRESS_SHL; 429 toggle = (val & SECOCEC_IR_TOGGLE_MASK) >> SECOCEC_IR_TOGGLE_SHL; 430 431 rc_keydown(cec->ir, RC_PROTO_RC5, RC_SCANCODE_RC5(addr, key), toggle); 432 433 dev_dbg(dev, "IR key pressed: 0x%02x addr 0x%02x toggle 0x%02x\n", key, 434 addr, toggle); 435 436 return 0; 437 438 err: 439 dev_err(dev, "IR Receive message failed (%d)\n", status); 440 return -EIO; 441 } 442 #else 443 static void secocec_ir_rx(struct secocec_data *priv) 444 { 445 } 446 447 static int secocec_ir_probe(void *priv) 448 { 449 return 0; 450 } 451 #endif 452 453 static irqreturn_t secocec_irq_handler(int irq, void *priv) 454 { 455 struct secocec_data *cec = priv; 456 struct device *dev = cec->dev; 457 u16 status_val, cec_val, val = 0; 458 int status; 459 460 /* Read status register */ 461 status = smb_rd16(SECOCEC_STATUS_REG_1, &status_val); 462 if (status) 463 goto err; 464 465 if (status_val & SECOCEC_STATUS_REG_1_CEC) { 466 /* Read CEC status register */ 467 status = smb_rd16(SECOCEC_STATUS, &cec_val); 468 if (status) 469 goto err; 470 471 if (cec_val & SECOCEC_STATUS_MSG_RECEIVED_MASK) 472 secocec_rx_done(cec->cec_adap, cec_val); 473 474 if (cec_val & SECOCEC_STATUS_MSG_SENT_MASK) 475 secocec_tx_done(cec->cec_adap, cec_val); 476 477 if ((~cec_val & SECOCEC_STATUS_MSG_SENT_MASK) && 478 (~cec_val & SECOCEC_STATUS_MSG_RECEIVED_MASK)) 479 dev_warn_once(dev, 480 "Message not received or sent, but interrupt fired"); 481 482 val = SECOCEC_STATUS_REG_1_CEC; 483 } 484 485 if (status_val & SECOCEC_STATUS_REG_1_IR) { 486 val |= SECOCEC_STATUS_REG_1_IR; 487 488 secocec_ir_rx(cec); 489 } 490 491 /* Reset status register */ 492 status = smb_wr16(SECOCEC_STATUS_REG_1, val); 493 if (status) 494 goto err; 495 496 return IRQ_HANDLED; 497 498 err: 499 dev_err_once(dev, "IRQ: R/W SMBus operation failed %d\n", status); 500 501 /* Reset status register */ 502 val = SECOCEC_STATUS_REG_1_CEC | SECOCEC_STATUS_REG_1_IR; 503 smb_wr16(SECOCEC_STATUS_REG_1, val); 504 505 return IRQ_HANDLED; 506 } 507 508 struct cec_dmi_match { 509 const char *sys_vendor; 510 const char *product_name; 511 const char *devname; 512 const char *conn; 513 }; 514 515 static const struct cec_dmi_match secocec_dmi_match_table[] = { 516 /* UDOO X86 */ 517 { "SECO", "UDOO x86", "0000:00:02.0", "Port B" }, 518 }; 519 520 static struct device *secocec_cec_find_hdmi_dev(struct device *dev, 521 const char **conn) 522 { 523 int i; 524 525 for (i = 0 ; i < ARRAY_SIZE(secocec_dmi_match_table) ; ++i) { 526 const struct cec_dmi_match *m = &secocec_dmi_match_table[i]; 527 528 if (dmi_match(DMI_SYS_VENDOR, m->sys_vendor) && 529 dmi_match(DMI_PRODUCT_NAME, m->product_name)) { 530 struct device *d; 531 532 /* Find the device, bail out if not yet registered */ 533 d = bus_find_device_by_name(&pci_bus_type, NULL, 534 m->devname); 535 if (!d) 536 return ERR_PTR(-EPROBE_DEFER); 537 538 put_device(d); 539 *conn = m->conn; 540 return d; 541 } 542 } 543 544 return ERR_PTR(-EINVAL); 545 } 546 547 static int secocec_acpi_probe(struct secocec_data *sdev) 548 { 549 struct device *dev = sdev->dev; 550 struct gpio_desc *gpio; 551 int irq = 0; 552 553 gpio = devm_gpiod_get(dev, NULL, GPIOD_IN); 554 if (IS_ERR(gpio)) { 555 dev_err(dev, "Cannot request interrupt gpio\n"); 556 return PTR_ERR(gpio); 557 } 558 559 irq = gpiod_to_irq(gpio); 560 if (irq < 0) { 561 dev_err(dev, "Cannot find valid irq\n"); 562 return -ENODEV; 563 } 564 dev_dbg(dev, "irq-gpio is bound to IRQ %d\n", irq); 565 566 sdev->irq = irq; 567 568 return 0; 569 } 570 571 static int secocec_probe(struct platform_device *pdev) 572 { 573 struct secocec_data *secocec; 574 struct device *dev = &pdev->dev; 575 struct device *hdmi_dev; 576 const char *conn = NULL; 577 int ret; 578 u16 val; 579 580 hdmi_dev = secocec_cec_find_hdmi_dev(&pdev->dev, &conn); 581 if (IS_ERR(hdmi_dev)) 582 return PTR_ERR(hdmi_dev); 583 584 secocec = devm_kzalloc(dev, sizeof(*secocec), GFP_KERNEL); 585 if (!secocec) 586 return -ENOMEM; 587 588 dev_set_drvdata(dev, secocec); 589 590 /* Request SMBus regions */ 591 if (!request_muxed_region(BRA_SMB_BASE_ADDR, 7, "CEC00001")) { 592 dev_err(dev, "Request memory region failed\n"); 593 return -ENXIO; 594 } 595 596 secocec->pdev = pdev; 597 secocec->dev = dev; 598 599 if (!has_acpi_companion(dev)) { 600 dev_dbg(dev, "Cannot find any ACPI companion\n"); 601 ret = -ENODEV; 602 goto err; 603 } 604 605 ret = secocec_acpi_probe(secocec); 606 if (ret) { 607 dev_err(dev, "Cannot assign gpio to IRQ\n"); 608 ret = -ENODEV; 609 goto err; 610 } 611 612 /* Firmware version check */ 613 ret = smb_rd16(SECOCEC_VERSION, &val); 614 if (ret) { 615 dev_err(dev, "Cannot check fw version\n"); 616 goto err; 617 } 618 if (val < SECOCEC_LATEST_FW) { 619 dev_err(dev, "CEC Firmware not supported (v.%04x). Use ver > v.%04x\n", 620 val, SECOCEC_LATEST_FW); 621 ret = -EINVAL; 622 goto err; 623 } 624 625 ret = devm_request_threaded_irq(dev, 626 secocec->irq, 627 NULL, 628 secocec_irq_handler, 629 IRQF_TRIGGER_RISING | IRQF_ONESHOT, 630 dev_name(&pdev->dev), secocec); 631 632 if (ret) { 633 dev_err(dev, "Cannot request IRQ %d\n", secocec->irq); 634 ret = -EIO; 635 goto err; 636 } 637 638 /* Allocate CEC adapter */ 639 secocec->cec_adap = cec_allocate_adapter(&secocec_cec_adap_ops, 640 secocec, 641 dev_name(dev), 642 CEC_CAP_DEFAULTS | 643 CEC_CAP_CONNECTOR_INFO, 644 SECOCEC_MAX_ADDRS); 645 646 if (IS_ERR(secocec->cec_adap)) { 647 ret = PTR_ERR(secocec->cec_adap); 648 goto err; 649 } 650 651 secocec->notifier = cec_notifier_cec_adap_register(hdmi_dev, conn, 652 secocec->cec_adap); 653 if (!secocec->notifier) { 654 ret = -ENOMEM; 655 goto err_delete_adapter; 656 } 657 658 ret = cec_register_adapter(secocec->cec_adap, dev); 659 if (ret) 660 goto err_notifier; 661 662 ret = secocec_ir_probe(secocec); 663 if (ret) 664 goto err_notifier; 665 666 platform_set_drvdata(pdev, secocec); 667 668 dev_dbg(dev, "Device registered\n"); 669 670 return ret; 671 672 err_notifier: 673 cec_notifier_cec_adap_unregister(secocec->notifier, secocec->cec_adap); 674 err_delete_adapter: 675 cec_delete_adapter(secocec->cec_adap); 676 err: 677 release_region(BRA_SMB_BASE_ADDR, 7); 678 dev_err(dev, "%s device probe failed\n", dev_name(dev)); 679 680 return ret; 681 } 682 683 static int secocec_remove(struct platform_device *pdev) 684 { 685 struct secocec_data *secocec = platform_get_drvdata(pdev); 686 u16 val; 687 688 if (secocec->ir) { 689 smb_rd16(SECOCEC_ENABLE_REG_1, &val); 690 691 smb_wr16(SECOCEC_ENABLE_REG_1, val & ~SECOCEC_ENABLE_REG_1_IR); 692 693 dev_dbg(&pdev->dev, "IR disabled\n"); 694 } 695 cec_notifier_cec_adap_unregister(secocec->notifier, secocec->cec_adap); 696 cec_unregister_adapter(secocec->cec_adap); 697 698 release_region(BRA_SMB_BASE_ADDR, 7); 699 700 dev_dbg(&pdev->dev, "CEC device removed\n"); 701 702 return 0; 703 } 704 705 #ifdef CONFIG_PM_SLEEP 706 static int secocec_suspend(struct device *dev) 707 { 708 int status; 709 u16 val; 710 711 dev_dbg(dev, "Device going to suspend, disabling\n"); 712 713 /* Clear the status register */ 714 status = smb_rd16(SECOCEC_STATUS_REG_1, &val); 715 if (status) 716 goto err; 717 718 status = smb_wr16(SECOCEC_STATUS_REG_1, val); 719 if (status) 720 goto err; 721 722 /* Disable the interrupts */ 723 status = smb_rd16(SECOCEC_ENABLE_REG_1, &val); 724 if (status) 725 goto err; 726 727 status = smb_wr16(SECOCEC_ENABLE_REG_1, val & 728 ~SECOCEC_ENABLE_REG_1_CEC & ~SECOCEC_ENABLE_REG_1_IR); 729 if (status) 730 goto err; 731 732 return 0; 733 734 err: 735 dev_err(dev, "Suspend failed: %d\n", status); 736 return status; 737 } 738 739 static int secocec_resume(struct device *dev) 740 { 741 int status; 742 u16 val; 743 744 dev_dbg(dev, "Resuming device from suspend\n"); 745 746 /* Clear the status register */ 747 status = smb_rd16(SECOCEC_STATUS_REG_1, &val); 748 if (status) 749 goto err; 750 751 status = smb_wr16(SECOCEC_STATUS_REG_1, val); 752 if (status) 753 goto err; 754 755 /* Enable the interrupts */ 756 status = smb_rd16(SECOCEC_ENABLE_REG_1, &val); 757 if (status) 758 goto err; 759 760 status = smb_wr16(SECOCEC_ENABLE_REG_1, val | SECOCEC_ENABLE_REG_1_CEC); 761 if (status) 762 goto err; 763 764 dev_dbg(dev, "Device resumed from suspend\n"); 765 766 return 0; 767 768 err: 769 dev_err(dev, "Resume failed: %d\n", status); 770 return status; 771 } 772 773 static SIMPLE_DEV_PM_OPS(secocec_pm_ops, secocec_suspend, secocec_resume); 774 #define SECOCEC_PM_OPS (&secocec_pm_ops) 775 #else 776 #define SECOCEC_PM_OPS NULL 777 #endif 778 779 #ifdef CONFIG_ACPI 780 static const struct acpi_device_id secocec_acpi_match[] = { 781 {"CEC00001", 0}, 782 {}, 783 }; 784 785 MODULE_DEVICE_TABLE(acpi, secocec_acpi_match); 786 #endif 787 788 static struct platform_driver secocec_driver = { 789 .driver = { 790 .name = SECOCEC_DEV_NAME, 791 .acpi_match_table = ACPI_PTR(secocec_acpi_match), 792 .pm = SECOCEC_PM_OPS, 793 }, 794 .probe = secocec_probe, 795 .remove = secocec_remove, 796 }; 797 798 module_platform_driver(secocec_driver); 799 800 MODULE_DESCRIPTION("SECO CEC X86 Driver"); 801 MODULE_AUTHOR("Ettore Chimenti <ek5.chimenti@gmail.com>"); 802 MODULE_LICENSE("Dual BSD/GPL"); 803