1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
3 * CEC driver for SECO X86 Boards
5 * Author: Ettore Chimenti <ek5.chimenti@gmail.com>
6 * Copyright (C) 2018, SECO SpA.
7 * Copyright (C) 2018, Aidilab Srl.
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>
21 #include <media/cec-notifier.h>
27 struct platform_device
*pdev
;
28 struct cec_adapter
*cec_adap
;
29 struct cec_notifier
*notifier
;
31 char ir_input_phys
[32];
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)
40 static int smb_word_op(short data_format
, u16 slave_addr
, u8 cmd
, u16 data
,
41 u8 operation
, u16
*result
)
47 switch (data_format
) {
49 _data_format
= BRA_SMB_CMD_BYTE_DATA
;
52 _data_format
= BRA_SMB_CMD_WORD_DATA
;
58 /* Active wait until ready */
59 for (count
= 0; count
<= SMBTIMEOUT
; ++count
) {
60 if (!(inb(HSTS
) & BRA_INUSE_STS
))
62 udelay(SMB_POLL_UDELAY
);
65 if (count
> SMBTIMEOUT
)
66 /* Reset the lock instead of failing */
70 outb((u8
)(slave_addr
& 0xfe) | operation
, XMIT_SLVA
);
74 if (operation
== SMBUS_WRITE
) {
75 outb((u8
)data
, HDAT0
);
76 outb((u8
)(data
>> 8), HDAT1
);
79 outb(BRA_START
+ _data_format
, HCNT
);
81 for (count
= 0; count
<= SMBTIMEOUT
; count
++) {
82 if (!(inb(HSTS
) & BRA_HOST_BUSY
))
84 udelay(SMB_POLL_UDELAY
);
87 if (count
> SMBTIMEOUT
) {
92 if (inb(HSTS
) & BRA_HSTS_ERR_MASK
) {
97 if (operation
== SMBUS_READ
)
98 *result
= ((inb(HDAT0
) & 0xff) + ((inb(HDAT1
) & 0xff) << 8));
105 static int secocec_adap_enable(struct cec_adapter
*adap
, bool enable
)
107 struct secocec_data
*cec
= cec_get_drvdata(adap
);
108 struct device
*dev
= cec
->dev
;
113 /* Clear the status register */
114 status
= smb_rd16(SECOCEC_STATUS_REG_1
, &val
);
118 status
= smb_wr16(SECOCEC_STATUS_REG_1
, val
);
122 /* Enable the interrupts */
123 status
= smb_rd16(SECOCEC_ENABLE_REG_1
, &val
);
127 status
= smb_wr16(SECOCEC_ENABLE_REG_1
,
128 val
| SECOCEC_ENABLE_REG_1_CEC
);
132 dev_dbg(dev
, "Device enabled");
134 /* Clear the status register */
135 status
= smb_rd16(SECOCEC_STATUS_REG_1
, &val
);
136 status
= smb_wr16(SECOCEC_STATUS_REG_1
, val
);
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
);
144 dev_dbg(dev
, "Device disabled");
152 static int secocec_adap_log_addr(struct cec_adapter
*adap
, u8 logical_addr
)
158 status
= smb_rd16(SECOCEC_ENABLE_REG_1
, &enable_val
);
162 status
= smb_wr16(SECOCEC_ENABLE_REG_1
,
163 enable_val
& ~SECOCEC_ENABLE_REG_1_CEC
);
167 /* Write logical address
168 * NOTE: CEC_LOG_ADDR_INVALID is mapped to the 'Unregistered' LA
170 status
= smb_wr16(SECOCEC_DEVICE_LA
, logical_addr
& 0xf);
174 /* Re-enable device */
175 status
= smb_wr16(SECOCEC_ENABLE_REG_1
,
176 enable_val
| SECOCEC_ENABLE_REG_1_CEC
);
183 static int secocec_adap_transmit(struct cec_adapter
*adap
, u8 attempts
,
184 u32 signal_free_time
, struct cec_msg
*msg
)
186 u16 payload_len
, payload_id_len
, destination
, val
= 0;
191 /* Device msg len already accounts for header */
192 payload_id_len
= msg
->len
- 1;
194 /* Send data length */
195 status
= smb_wr16(SECOCEC_WRITE_DATA_LENGTH
, payload_id_len
);
199 /* Send Operation ID if present */
200 if (payload_id_len
> 0) {
201 status
= smb_wr16(SECOCEC_WRITE_OPERATION_ID
, msg
->msg
[1]);
205 /* Send data if present */
206 if (payload_id_len
> 1) {
208 payload_len
= msg
->len
- 2;
209 payload_msg
= &msg
->msg
[2];
211 /* Copy message into registers */
212 for (i
= 0; i
< payload_len
; i
+= 2) {
214 val
= payload_msg
[i
+ 1] << 8;
217 val
|= payload_msg
[i
];
219 status
= smb_wr16(SECOCEC_WRITE_DATA_00
+ i
/ 2, val
);
224 /* Send msg source/destination and fire msg */
225 destination
= msg
->msg
[0];
226 status
= smb_wr16(SECOCEC_WRITE_BYTE0
, destination
);
236 static void secocec_tx_done(struct cec_adapter
*adap
, u16 status_val
)
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
);
242 cec_transmit_attempt_done(adap
, CEC_TX_STATUS_ERROR
);
244 cec_transmit_attempt_done(adap
, CEC_TX_STATUS_OK
);
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
);
254 static void secocec_rx_done(struct cec_adapter
*adap
, u16 status_val
)
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;
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;
271 if (status_val
& SECOCEC_STATUS_RX_ERROR_MASK
) {
272 dev_warn(dev
, "Message received with errors. Discarding");
277 /* Read message length */
278 status
= smb_rd16(SECOCEC_READ_DATA_LENGTH
, &val
);
282 /* Device msg len already accounts for the header */
283 msg
.len
= min(val
+ 1, CEC_MAX_MSG_SIZE
);
285 /* Read logical address */
286 status
= smb_rd16(SECOCEC_READ_BYTE0
, &val
);
290 /* device stores source LA and destination */
293 /* Read operation ID */
294 status
= smb_rd16(SECOCEC_READ_OPERATION_ID
, &val
);
300 /* Read data if present */
302 payload_len
= msg
.len
- 2;
303 payload_msg
= &msg
.msg
[2];
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
);
311 /* low byte, skipping header */
312 payload_msg
[i
] = val
& 0x00ff;
315 payload_msg
[i
+ 1] = (val
& 0xff00) >> 8;
319 cec_received_msg(cec
->cec_adap
, &msg
);
321 /* Reset status reg */
322 status_val
= SECOCEC_STATUS_MSG_RECEIVED_MASK
;
324 status_val
|= SECOCEC_STATUS_RX_OVERFLOW_MASK
;
326 status
= smb_wr16(SECOCEC_STATUS
, status_val
);
331 /* Reset error reg */
332 status_val
= SECOCEC_STATUS_MSG_RECEIVED_MASK
|
333 SECOCEC_STATUS_RX_ERROR_MASK
;
335 status_val
|= SECOCEC_STATUS_RX_OVERFLOW_MASK
;
336 smb_wr16(SECOCEC_STATUS
, status_val
);
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
,
346 #ifdef CONFIG_VIDEO_SECO_RC
347 static int secocec_ir_probe(void *priv
)
349 struct secocec_data
*cec
= priv
;
350 struct device
*dev
= cec
->dev
;
354 /* Prepare the RC input device */
355 cec
->ir
= devm_rc_allocate_device(dev
, RC_DRIVER_SCANCODE
);
359 snprintf(cec
->ir_input_phys
, sizeof(cec
->ir_input_phys
),
360 "%s/input0", dev_name(dev
));
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
;
371 cec
->ir
->map_name
= RC_MAP_HAUPPAUGE
;
372 cec
->ir
->timeout
= MS_TO_NS(100);
374 /* Clear the status register */
375 status
= smb_rd16(SECOCEC_STATUS_REG_1
, &val
);
379 status
= smb_wr16(SECOCEC_STATUS_REG_1
, val
);
383 /* Enable the interrupts */
384 status
= smb_rd16(SECOCEC_ENABLE_REG_1
, &val
);
388 status
= smb_wr16(SECOCEC_ENABLE_REG_1
,
389 val
| SECOCEC_ENABLE_REG_1_IR
);
393 dev_dbg(dev
, "IR enabled");
395 status
= devm_rc_register_device(dev
, cec
->ir
);
398 dev_err(dev
, "Failed to prepare input device");
406 smb_rd16(SECOCEC_ENABLE_REG_1
, &val
);
408 smb_wr16(SECOCEC_ENABLE_REG_1
,
409 val
& ~SECOCEC_ENABLE_REG_1_IR
);
411 dev_dbg(dev
, "IR disabled");
415 static int secocec_ir_rx(struct secocec_data
*priv
)
417 struct secocec_data
*cec
= priv
;
418 struct device
*dev
= cec
->dev
;
419 u16 val
, status
, key
, addr
, toggle
;
424 status
= smb_rd16(SECOCEC_IR_READ_DATA
, &val
);
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
;
432 rc_keydown(cec
->ir
, RC_PROTO_RC5
, RC_SCANCODE_RC5(addr
, key
), toggle
);
434 dev_dbg(dev
, "IR key pressed: 0x%02x addr 0x%02x toggle 0x%02x", key
,
440 dev_err(dev
, "IR Receive message failed (%d)", status
);
444 static void secocec_ir_rx(struct secocec_data
*priv
)
448 static int secocec_ir_probe(void *priv
)
454 static irqreturn_t
secocec_irq_handler(int irq
, void *priv
)
456 struct secocec_data
*cec
= priv
;
457 struct device
*dev
= cec
->dev
;
458 u16 status_val
, cec_val
, val
= 0;
461 /* Read status register */
462 status
= smb_rd16(SECOCEC_STATUS_REG_1
, &status_val
);
466 if (status_val
& SECOCEC_STATUS_REG_1_CEC
) {
467 /* Read CEC status register */
468 status
= smb_rd16(SECOCEC_STATUS
, &cec_val
);
472 if (cec_val
& SECOCEC_STATUS_MSG_RECEIVED_MASK
)
473 secocec_rx_done(cec
->cec_adap
, cec_val
);
475 if (cec_val
& SECOCEC_STATUS_MSG_SENT_MASK
)
476 secocec_tx_done(cec
->cec_adap
, cec_val
);
478 if ((~cec_val
& SECOCEC_STATUS_MSG_SENT_MASK
) &&
479 (~cec_val
& SECOCEC_STATUS_MSG_RECEIVED_MASK
))
481 "Message not received or sent, but interrupt fired");
483 val
= SECOCEC_STATUS_REG_1_CEC
;
486 if (status_val
& SECOCEC_STATUS_REG_1_IR
) {
487 val
|= SECOCEC_STATUS_REG_1_IR
;
492 /* Reset status register */
493 status
= smb_wr16(SECOCEC_STATUS_REG_1
, val
);
500 dev_err_once(dev
, "IRQ: R/W SMBus operation failed (%d)", status
);
502 /* Reset status register */
503 val
= SECOCEC_STATUS_REG_1_CEC
| SECOCEC_STATUS_REG_1_IR
;
504 smb_wr16(SECOCEC_STATUS_REG_1
, val
);
509 struct cec_dmi_match
{
510 const char *sys_vendor
;
511 const char *product_name
;
516 static const struct cec_dmi_match secocec_dmi_match_table
[] = {
518 { "SECO", "UDOO x86", "0000:00:02.0", "Port B" },
521 static struct device
*secocec_cec_find_hdmi_dev(struct device
*dev
,
526 for (i
= 0 ; i
< ARRAY_SIZE(secocec_dmi_match_table
) ; ++i
) {
527 const struct cec_dmi_match
*m
= &secocec_dmi_match_table
[i
];
529 if (dmi_match(DMI_SYS_VENDOR
, m
->sys_vendor
) &&
530 dmi_match(DMI_PRODUCT_NAME
, m
->product_name
)) {
533 /* Find the device, bail out if not yet registered */
534 d
= bus_find_device_by_name(&pci_bus_type
, NULL
,
537 return ERR_PTR(-EPROBE_DEFER
);
545 return ERR_PTR(-EINVAL
);
548 static int secocec_acpi_probe(struct secocec_data
*sdev
)
550 struct device
*dev
= sdev
->dev
;
551 struct gpio_desc
*gpio
;
554 gpio
= devm_gpiod_get(dev
, NULL
, GPIOF_IN
);
556 dev_err(dev
, "Cannot request interrupt gpio");
557 return PTR_ERR(gpio
);
560 irq
= gpiod_to_irq(gpio
);
562 dev_err(dev
, "Cannot find valid irq");
565 dev_dbg(dev
, "irq-gpio is bound to IRQ %d", irq
);
572 static int secocec_probe(struct platform_device
*pdev
)
574 struct secocec_data
*secocec
;
575 struct device
*dev
= &pdev
->dev
;
576 struct device
*hdmi_dev
;
577 const char *conn
= NULL
;
581 hdmi_dev
= secocec_cec_find_hdmi_dev(&pdev
->dev
, &conn
);
582 if (IS_ERR(hdmi_dev
))
583 return PTR_ERR(hdmi_dev
);
585 secocec
= devm_kzalloc(dev
, sizeof(*secocec
), GFP_KERNEL
);
589 dev_set_drvdata(dev
, secocec
);
591 /* Request SMBus regions */
592 if (!request_muxed_region(BRA_SMB_BASE_ADDR
, 7, "CEC00001")) {
593 dev_err(dev
, "Request memory region failed");
597 secocec
->pdev
= pdev
;
600 if (!has_acpi_companion(dev
)) {
601 dev_dbg(dev
, "Cannot find any ACPI companion");
606 ret
= secocec_acpi_probe(secocec
);
608 dev_err(dev
, "Cannot assign gpio to IRQ");
613 /* Firmware version check */
614 ret
= smb_rd16(SECOCEC_VERSION
, &val
);
616 dev_err(dev
, "Cannot check fw version");
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
);
626 ret
= devm_request_threaded_irq(dev
,
630 IRQF_TRIGGER_RISING
| IRQF_ONESHOT
,
631 dev_name(&pdev
->dev
), secocec
);
634 dev_err(dev
, "Cannot request IRQ %d", secocec
->irq
);
639 /* Allocate CEC adapter */
640 secocec
->cec_adap
= cec_allocate_adapter(&secocec_cec_adap_ops
,
644 CEC_CAP_CONNECTOR_INFO
,
647 if (IS_ERR(secocec
->cec_adap
)) {
648 ret
= PTR_ERR(secocec
->cec_adap
);
652 secocec
->notifier
= cec_notifier_cec_adap_register(hdmi_dev
, conn
,
654 if (!secocec
->notifier
) {
656 goto err_delete_adapter
;
659 ret
= cec_register_adapter(secocec
->cec_adap
, dev
);
663 ret
= secocec_ir_probe(secocec
);
667 platform_set_drvdata(pdev
, secocec
);
669 dev_dbg(dev
, "Device registered");
674 cec_notifier_cec_adap_unregister(secocec
->notifier
, secocec
->cec_adap
);
676 cec_delete_adapter(secocec
->cec_adap
);
678 release_region(BRA_SMB_BASE_ADDR
, 7);
679 dev_err(dev
, "%s device probe failed\n", dev_name(dev
));
684 static int secocec_remove(struct platform_device
*pdev
)
686 struct secocec_data
*secocec
= platform_get_drvdata(pdev
);
690 smb_rd16(SECOCEC_ENABLE_REG_1
, &val
);
692 smb_wr16(SECOCEC_ENABLE_REG_1
, val
& ~SECOCEC_ENABLE_REG_1_IR
);
694 dev_dbg(&pdev
->dev
, "IR disabled");
696 cec_notifier_cec_adap_unregister(secocec
->notifier
, secocec
->cec_adap
);
697 cec_unregister_adapter(secocec
->cec_adap
);
699 release_region(BRA_SMB_BASE_ADDR
, 7);
701 dev_dbg(&pdev
->dev
, "CEC device removed");
706 #ifdef CONFIG_PM_SLEEP
707 static int secocec_suspend(struct device
*dev
)
712 dev_dbg(dev
, "Device going to suspend, disabling");
714 /* Clear the status register */
715 status
= smb_rd16(SECOCEC_STATUS_REG_1
, &val
);
719 status
= smb_wr16(SECOCEC_STATUS_REG_1
, val
);
723 /* Disable the interrupts */
724 status
= smb_rd16(SECOCEC_ENABLE_REG_1
, &val
);
728 status
= smb_wr16(SECOCEC_ENABLE_REG_1
, val
&
729 ~SECOCEC_ENABLE_REG_1_CEC
& ~SECOCEC_ENABLE_REG_1_IR
);
736 dev_err(dev
, "Suspend failed (err: %d)", status
);
740 static int secocec_resume(struct device
*dev
)
745 dev_dbg(dev
, "Resuming device from suspend");
747 /* Clear the status register */
748 status
= smb_rd16(SECOCEC_STATUS_REG_1
, &val
);
752 status
= smb_wr16(SECOCEC_STATUS_REG_1
, val
);
756 /* Enable the interrupts */
757 status
= smb_rd16(SECOCEC_ENABLE_REG_1
, &val
);
761 status
= smb_wr16(SECOCEC_ENABLE_REG_1
, val
| SECOCEC_ENABLE_REG_1_CEC
);
765 dev_dbg(dev
, "Device resumed from suspend");
770 dev_err(dev
, "Resume failed (err: %d)", status
);
774 static SIMPLE_DEV_PM_OPS(secocec_pm_ops
, secocec_suspend
, secocec_resume
);
775 #define SECOCEC_PM_OPS (&secocec_pm_ops)
777 #define SECOCEC_PM_OPS NULL
781 static const struct acpi_device_id secocec_acpi_match
[] = {
786 MODULE_DEVICE_TABLE(acpi
, secocec_acpi_match
);
789 static struct platform_driver secocec_driver
= {
791 .name
= SECOCEC_DEV_NAME
,
792 .acpi_match_table
= ACPI_PTR(secocec_acpi_match
),
793 .pm
= SECOCEC_PM_OPS
,
795 .probe
= secocec_probe
,
796 .remove
= secocec_remove
,
799 module_platform_driver(secocec_driver
);
801 MODULE_DESCRIPTION("SECO CEC X86 Driver");
802 MODULE_AUTHOR("Ettore Chimenti <ek5.chimenti@gmail.com>");
803 MODULE_LICENSE("Dual BSD/GPL");