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