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