summaryrefslogtreecommitdiff
authorYong Qin <yong.qin@amlogic.com>2018-07-24 05:55:25 (GMT)
committer Jianxin Pan <jianxin.pan@amlogic.com>2018-08-01 06:50:23 (GMT)
commit7fa72600d909ae7169989953a707e5c601bde05b (patch)
tree0d2707c1b1c51d7c1b46a028ce84b2565dbf89bb
parent30329dbcbbd6f372610facfe826d2c1c2846ed66 (diff)
downloadcommon-7fa72600d909ae7169989953a707e5c601bde05b.zip
common-7fa72600d909ae7169989953a707e5c601bde05b.tar.gz
common-7fa72600d909ae7169989953a707e5c601bde05b.tar.bz2
cec: add debug cmd interface
PD#170470: cec: add debug cmd interface 1.enable cec error_initator interrupt 2.add debug cmd interfacec 1)dump info 2)register read write 3)bypass hal cmd 3.boot reson ioctrl add mutex unlock Change-Id: I340e4d363a46890001ff0494744cd9ec2fb28ea3 Signed-off-by: Yong Qin <yong.qin@amlogic.com>
Diffstat
-rw-r--r--drivers/amlogic/cec/hdmi_ao_cec.c200
-rw-r--r--drivers/amlogic/cec/hdmi_ao_cec.h29
2 files changed, 201 insertions, 28 deletions
diff --git a/drivers/amlogic/cec/hdmi_ao_cec.c b/drivers/amlogic/cec/hdmi_ao_cec.c
index be49708..373381d 100644
--- a/drivers/amlogic/cec/hdmi_ao_cec.c
+++ b/drivers/amlogic/cec/hdmi_ao_cec.c
@@ -141,6 +141,7 @@ struct cec_msg_last {
unsigned long last_jiffies;
};
static struct cec_msg_last *last_cec_msg;
+static struct dbgflg stdbgflg;
static int phy_addr_test;
@@ -165,7 +166,9 @@ static unsigned int new_msg;
static bool wake_ok = 1;
static bool ee_cec;
static bool pin_status;
-bool cec_msg_dbg_en;
+static unsigned int cec_msg_dbg_en;
+
+static void cec_hw_reset(void);
#define CEC_ERR(format, args...) \
{if (cec_dev->dbg_dev) \
@@ -177,9 +180,12 @@ bool cec_msg_dbg_en;
dev_info(cec_dev->dbg_dev, format, ##args); \
}
-static unsigned char msg_log_buf[128] = { 0 };
+#define CEC_INFO_L(level, format, args...) \
+ {if ((cec_msg_dbg_en >= level) && cec_dev->dbg_dev) \
+ dev_info(cec_dev->dbg_dev, format, ##args); \
+ }
-static void cec_hw_reset(void);
+static unsigned char msg_log_buf[128] = { 0 };
#define waiting_aocec_free(r) \
do {\
@@ -316,6 +322,11 @@ static inline void hdmirx_set_bits_dwc(uint32_t reg, uint32_t bits,
hdmirx_cec_write(reg, tmp);
}
+void cec_dbg_init(void)
+{
+ stdbgflg.hal_cmd_bypass = 0;
+}
+
void cecrx_hw_reset(void)
{
/* cec disable */
@@ -462,15 +473,18 @@ void cecrx_irq_handle(void)
if ((intr_cec & CEC_IRQ_TX_NACK) ||
(intr_cec & CEC_IRQ_TX_ARB_LOST) ||
(intr_cec & CEC_IRQ_TX_ERR_INITIATOR)) {
- if (!(intr_cec & CEC_IRQ_TX_NACK))
- CEC_ERR("tx msg failed, flag:%08x\n", intr_cec);
- if (intr_cec & CEC_IRQ_TX_NACK)
+ if (intr_cec & CEC_IRQ_TX_NACK) {
cec_tx_result = CEC_FAIL_NACK;
- else if (intr_cec & CEC_IRQ_TX_ARB_LOST) {
+ CEC_INFO_L(L_2, "warning:TX_NACK\n");
+ } else if (intr_cec & CEC_IRQ_TX_ARB_LOST) {
cec_tx_result = CEC_FAIL_BUSY;
/* clear start */
hdmirx_cec_write(DWC_CEC_TX_CNT, 0);
hdmirx_set_bits_dwc(DWC_CEC_CTRL, 0, 0, 3);
+ CEC_ERR("warning:ARB_LOST\n");
+ } else if (intr_cec & CEC_IRQ_TX_ERR_INITIATOR) {
+ CEC_ERR("warning:INITIATOR\n");
+ cec_tx_result = CEC_FAIL_OTHER;
} else
cec_tx_result = CEC_FAIL_OTHER;
complete(&cec_dev->tx_ok);
@@ -478,18 +492,20 @@ void cecrx_irq_handle(void)
/* RX error irq flag */
if (intr_cec & CEC_IRQ_RX_ERR_FOLLOWER) {
- CEC_ERR("rx msg failed\n");
+ CEC_ERR("warning:FOLLOWER\n");
+ hdmirx_cec_write(DWC_CEC_LOCK, 0);
/* TODO: need reset cec hw logic? */
}
+ /* wakeup op code will triger this int*/
if (intr_cec & CEC_IRQ_RX_WAKEUP) {
- CEC_INFO("rx wake up\n");
- hdmirx_cec_write(DWC_CEC_WKUPCTRL, 0);
+ CEC_ERR("warning:RX_WAKEUP\n");
+ hdmirx_cec_write(DWC_CEC_WKUPCTRL, WAKEUP_EN_MASK);
/* TODO: wake up system if needed */
}
}
-static irqreturn_t cecrx_isr(int irq, void *dev_instance)
+static irqreturn_t cecb_rx_isr(int irq, void *dev_instance)
{
cecrx_irq_handle();
return IRQ_HANDLED;
@@ -543,7 +559,7 @@ static void ao_cecb_init(void)
/* Enable all AO_CECB interrupt sources */
cec_irq_enable(true);
- hdmirx_cec_write(DWC_CEC_WKUPCTRL, 0);
+ hdmirx_cec_write(DWC_CEC_WKUPCTRL, WAKEUP_EN_MASK);
}
void eecec_irq_enable(bool enable)
@@ -873,7 +889,7 @@ int cec_ll_rx(unsigned char *msg, unsigned char *len)
ret = rx_stat;
/* ignore ping message */
- if (cec_msg_dbg_en == 1 && *len > 1) {
+ if (cec_msg_dbg_en && *len > 1) {
pos = 0;
pos += sprintf(msg_log_buf + pos,
"CEC: rx msg len: %d dat: ", *len);
@@ -930,7 +946,7 @@ static int cec_ll_trigle_tx(const unsigned char *msg, int len)
aocec_wr_reg(CEC_TX_MSG_LENGTH, len-1);
aocec_wr_reg(CEC_TX_MSG_CMD, TX_REQ_CURRENT);
- if (cec_msg_dbg_en == 1) {
+ if (cec_msg_dbg_en) {
pos = 0;
pos += sprintf(msg_log_buf + pos,
"CEC: tx msg len: %d dat: ", len);
@@ -968,7 +984,7 @@ void tx_irq_handle(void)
break;
case TX_ERROR:
- if (cec_msg_dbg_en == 1)
+ if (cec_msg_dbg_en)
CEC_ERR("TX ERROR!!!\n");
aocec_wr_reg(CEC_TX_MSG_CMD, TX_ABORT);
cec_hw_reset();
@@ -1709,7 +1725,7 @@ static void cec_task(struct work_struct *work)
queue_delayed_work(cec_dev->cec_thread, dwork, CEC_FRAME_DELAY);
}
-static irqreturn_t cec_isr_handler(int irq, void *dev_instance)
+static irqreturn_t ceca_isr_handler(int irq, void *dev_instance)
{
unsigned int intr_stat = 0;
struct delayed_work *dwork;
@@ -1736,6 +1752,27 @@ static void check_wake_up(void)
cec_request_active_source();
}
+static void cec_dump_info(void)
+{
+ CEC_ERR("dev_type:%d\n", (unsigned int)cec_dev->dev_type);
+ CEC_ERR("wk_logic_addr:0x%x\n", cec_dev->wakup_data.wk_logic_addr);
+ CEC_ERR("wk_phy_addr:0x%x\n", cec_dev->wakup_data.wk_phy_addr);
+ CEC_ERR("wk_port_id:0x%x\n", cec_dev->wakup_data.wk_port_id);
+ CEC_ERR("wakeup_reason:0x%x\n", cec_dev->wakeup_reason);
+ CEC_ERR("phy_addr:0x%x\n", cec_dev->phy_addr);
+ CEC_ERR("cec_version:0x%x\n", cec_dev->cec_info.cec_version);
+ CEC_ERR("hal_ctl:0x%x\n", cec_dev->cec_info.hal_ctl);
+ CEC_ERR("menu_lang:0x%x\n", cec_dev->cec_info.menu_lang);
+ CEC_ERR("menu_status:0x%x\n", cec_dev->cec_info.menu_status);
+ CEC_ERR("open_count:%d\n", cec_dev->cec_info.open_count.counter);
+ CEC_ERR("vendor_id:0x%x\n", cec_dev->v_data.vendor_id);
+ CEC_ERR("port_num:0x%x\n", cec_dev->port_num);
+ CEC_ERR("hal_flag:0x%x\n", cec_dev->hal_flag);
+ CEC_ERR("hpd_state:0x%x\n", cec_dev->tx_dev->hpd_state);
+ CEC_ERR("cec_config:0x%x\n", cec_config(0, 0));
+ dump_reg();
+}
+
/******************** cec class interface *************************/
static ssize_t device_type_show(struct class *cla,
struct class_attribute *attr, char *buf)
@@ -1972,7 +2009,7 @@ static ssize_t dbg_en_store(struct class *cla, struct class_attribute *attr,
if (kstrtouint(buf, 16, &en) != 0)
return -EINVAL;
- cec_msg_dbg_en = en ? 1 : 0;
+ cec_msg_dbg_en = en;
return count;
}
@@ -2052,6 +2089,114 @@ static ssize_t log_addr_show(struct class *cla,
return sprintf(buf, "0x%x\n", cec_dev->cec_info.log_addr);
}
+static ssize_t dbg_store(struct class *cla, struct class_attribute *attr,
+ const char *bu, size_t count)
+{
+ const char *delim = " ";
+ char *token;
+ char *cur = (char *)bu;
+ struct dbgflg *dbg = &stdbgflg;
+ unsigned int addr, val;
+
+ token = strsep(&cur, delim);
+ if (token && strncmp(token, "bypass", 6) == 0) {
+ /*get the second param*/
+ token = strsep(&cur, delim);
+ /*string to int*/
+ if (!token || kstrtouint(token, 16, &val) < 0)
+ return count;
+
+ dbg->hal_cmd_bypass = val ? 1 : 0;
+ CEC_ERR("cmdbypass:%d\n", val);
+ } else if (token && strncmp(token, "dbgen", 5) == 0) {
+ token = strsep(&cur, delim);
+ /*string to int*/
+ if (!token || kstrtouint(token, 16, &val) < 0)
+ return count;
+
+ cec_msg_dbg_en = val;
+ CEC_ERR("msg_dbg_en:%d\n", val);
+ } else if (token && strncmp(token, "ra", 2) == 0) {
+ token = strsep(&cur, delim);
+ /*string to int*/
+ if (!token || kstrtouint(token, 16, &addr) < 0)
+ return count;
+
+ CEC_ERR("rd ceca reg:0x%x val:0x%x\n", addr,
+ aocec_rd_reg(addr));
+ } else if (token && strncmp(token, "wa", 2) == 0) {
+ token = strsep(&cur, delim);
+ /*string to int*/
+ if (!token || kstrtouint(token, 16, &addr) < 0)
+ return count;
+
+ token = strsep(&cur, delim);
+ /*string to int*/
+ if (!token || kstrtouint(token, 16, &val) < 0)
+ return count;
+
+ CEC_ERR("wa ceca reg:0x%x val:0x%x\n", addr, val);
+ aocec_wr_reg(addr, val);
+ } else if (token && strncmp(token, "rb", 2) == 0) {
+ token = strsep(&cur, delim);
+ /*string to int*/
+ if (!token || kstrtouint(token, 16, &addr) < 0)
+ return count;
+
+ CEC_ERR("rd cecb reg:0x%x val:0x%x\n", addr,
+ hdmirx_cec_read(addr));
+ } else if (token && strncmp(token, "wb", 2) == 0) {
+ token = strsep(&cur, delim);
+ /*string to int*/
+ if (!token || kstrtouint(token, 16, &addr) < 0)
+ return count;
+
+ token = strsep(&cur, delim);
+ /*string to int*/
+ if (!token || kstrtouint(token, 16, &val) < 0)
+ return count;
+
+ CEC_ERR("wb cecb reg:0x%x val:0x%x\n", addr, val);
+ hdmirx_cec_write(addr, val);
+ } else if (token && strncmp(token, "dump", 4) == 0) {
+ cec_dump_info();
+ } else if (token && strncmp(token, "rao", 3) == 0) {
+ token = strsep(&cur, delim);
+ /*string to int*/
+ if (!token || kstrtouint(token, 16, &addr) < 0)
+ return count;
+
+ val = readl(cec_dev->cec_reg + addr);
+ CEC_ERR("rao addr:0x%x, val:0x%x", val, addr);
+ } else if (token && strncmp(token, "wao", 3) == 0) {
+ token = strsep(&cur, delim);
+ /*string to int*/
+ if (!token || kstrtouint(token, 16, &addr) < 0)
+ return count;
+
+ token = strsep(&cur, delim);
+ /*string to int*/
+ if (!token || kstrtouint(token, 16, &val) < 0)
+ return count;
+
+ writel(val, cec_dev->cec_reg + addr);
+ CEC_ERR("wao addr:0x%x, val:0x%x", val, addr);
+ } else {
+ if (token)
+ CEC_ERR("no cmd:%s\n", token);
+ }
+
+ return count;
+}
+
+static ssize_t dbg_show(struct class *cla,
+ struct class_attribute *attr, char *buf)
+{
+ CEC_INFO("dbg_show\n");
+ return 0;
+}
+
+
static struct class_attribute aocec_class_attr[] = {
__ATTR_WO(cmd),
__ATTR_RO(port_num),
@@ -2070,6 +2215,7 @@ static struct class_attribute aocec_class_attr[] = {
__ATTR(dbg_en, 0664, dbg_en_show, dbg_en_store),
__ATTR(log_addr, 0664, log_addr_show, log_addr_store),
__ATTR(fun_cfg, 0664, fun_cfg_show, fun_cfg_store),
+ __ATTR(dbg, 0664, dbg_show, dbg_store),
__ATTR_NULL
};
@@ -2116,6 +2262,9 @@ static ssize_t hdmitx_cec_write(struct file *f, const char __user *buf,
int ret = CEC_FAIL_OTHER;
unsigned int cec_cfg;
+ if (stdbgflg.hal_cmd_bypass)
+ return -EINVAL;
+
if (size > 16)
size = 16;
if (size <= 0)
@@ -2135,7 +2284,6 @@ static ssize_t hdmitx_cec_write(struct file *f, const char __user *buf,
return ret;
}
-
static void init_cec_port_info(struct hdmi_port_info *port,
struct ao_cec_dev *cec_dev)
{
@@ -2438,15 +2586,19 @@ static long hdmitx_cec_ioctl(struct file *f,
tmp = (cec_dev->wakup_data.wk_logic_addr << 16) |
cec_dev->wakup_data.wk_phy_addr;
CEC_ERR("Boot addr:%#x\n", (unsigned int)tmp);
- if (copy_to_user(argp, &tmp, _IOC_SIZE(cmd)))
+ if (copy_to_user(argp, &tmp, _IOC_SIZE(cmd))) {
+ mutex_unlock(&cec_dev->cec_ioctl_mutex);
return -EINVAL;
+ }
break;
case CEC_IOC_GET_BOOT_REASON:
tmp = cec_dev->wakeup_reason;
CEC_ERR("Boot reason:%#x\n", (unsigned int)tmp);
- if (copy_to_user(argp, &tmp, _IOC_SIZE(cmd)))
+ if (copy_to_user(argp, &tmp, _IOC_SIZE(cmd))) {
+ mutex_unlock(&cec_dev->cec_ioctl_mutex);
return -EINVAL;
+ }
break;
default:
@@ -2579,13 +2731,14 @@ static int aml_cec_probe(struct platform_device *pdev)
ret = -ENOMEM;
goto tag_cec_devm_err;
}
+ CEC_ERR("cec driver date:%s\n", CEC_DRIVER_VERSION);
cec_dev->dev_type = DEV_TYPE_PLAYBACK;
cec_dev->dbg_dev = &pdev->dev;
cec_dev->tx_dev = get_hdmitx_device();
cec_dev->cpu_type = get_cpu_type();
cec_dev->node = pdev->dev.of_node;
phy_addr_test = 0;
-
+ cec_dbg_init();
/* cdev registe */
r = class_register(&aocec_class);
if (r) {
@@ -2809,13 +2962,13 @@ static int aml_cec_probe(struct platform_device *pdev)
if (of_get_property(node, "interrupt-names", NULL)) {
r = of_property_read_string(node, "interrupt-names", &irq_name);
if (!r && !ee_cec) {
- r = request_irq(irq_idx, &cec_isr_handler, IRQF_SHARED,
+ r = request_irq(irq_idx, &ceca_isr_handler, IRQF_SHARED,
irq_name, (void *)cec_dev);
if (r < 0)
CEC_INFO("aocec irq request fail\n");
}
if (!r && ee_cec) {
- r = request_irq(irq_idx, &cecrx_isr, IRQF_SHARED,
+ r = request_irq(irq_idx, &cecb_rx_isr, IRQF_SHARED,
irq_name, (void *)cec_dev);
if (r < 0)
CEC_INFO("cecb irq request fail\n");
@@ -2845,7 +2998,6 @@ static int aml_cec_probe(struct platform_device *pdev)
/* for init */
cec_pre_init();
queue_delayed_work(cec_dev->cec_thread, &cec_dev->cec_work, 0);
- CEC_ERR("cec driver date:%s\n", CEC_DRIVER_VERSION);
CEC_ERR("boot:%#x;%#x\n", *((unsigned int *)&cec_dev->wakup_data),
cec_dev->wakeup_reason);
CEC_ERR("%s success end\n", __func__);
diff --git a/drivers/amlogic/cec/hdmi_ao_cec.h b/drivers/amlogic/cec/hdmi_ao_cec.h
index f5efeb4..fb171eb 100644
--- a/drivers/amlogic/cec/hdmi_ao_cec.h
+++ b/drivers/amlogic/cec/hdmi_ao_cec.h
@@ -18,7 +18,7 @@
#ifndef __AO_CEC_H__
#define __AO_CEC_H__
-#define CEC_DRIVER_VERSION "Ver**2018/07/31**\n"
+#define CEC_DRIVER_VERSION "Ver 2018/08/01\n"
#define CEC_FRAME_DELAY msecs_to_jiffies(400)
#define CEC_DEV_NAME "cec"
@@ -28,6 +28,10 @@
#define HR_DELAY(n) (ktime_set(0, n * 1000 * 1000))
+#define L_1 1
+#define L_2 2
+#define L_3 3
+
#define CEC_FUNC_MASK 0
#define ONE_TOUCH_PLAY_MASK 1
#define ONE_TOUCH_STANDBY_MASK 2
@@ -350,7 +354,7 @@
#define EECEC_IRQ_TX_ERR_INITIATOR (1 << 20)
#define EECEC_IRQ_RX_ERR_FOLLOWER (1 << 21)
#define EECEC_IRQ_RX_WAKEUP (1 << 22)
-#define EE_CEC_IRQ_EN_MASK (0x1f << 16)
+#define EE_CEC_IRQ_EN_MASK (0x3f << 16)
/* cec irq bit flags for AO_CEC_B */
#define CECB_IRQ_TX_DONE (1 << 0)
@@ -360,7 +364,7 @@
#define CECB_IRQ_TX_ERR_INITIATOR (1 << 4)
#define CECB_IRQ_RX_ERR_FOLLOWER (1 << 5)
#define CECB_IRQ_RX_WAKEUP (1 << 6)
-#define CECB_IRQ_EN_MASK (0x1f << 0)
+#define CECB_IRQ_EN_MASK (0x3f << 0)
/* common mask */
#define CEC_IRQ_TX_DONE (1 << (16 - shift))
@@ -371,13 +375,29 @@
#define CEC_IRQ_RX_ERR_FOLLOWER (1 << (21 - shift))
#define CEC_IRQ_RX_WAKEUP (1 << (22 - shift))
+/* wakeup mask */
+#define WAKEUP_OP_86_EN (1 << 7)
+#define WAKEUP_OP_82_EN (1 << 6)
+#define WAKEUP_OP_70_EN (1 << 5)
+#define WAKEUP_OP_44_EN (1 << 4)
+#define WAKEUP_OP_42_EN (1 << 3)
+#define WAKEUP_OP_41_EN (1 << 2)
+#define WAKEUP_OP_0D_EN (1 << 1)
+#define WAKEUP_OP_04_EN (1 << 0)
+#define WAKEUP_DIS_MASK 0
+#define WAKEUP_EN_MASK (WAKEUP_OP_86_EN | \
+ WAKEUP_OP_0D_EN | \
+ WAKEUP_OP_04_EN)
+
#define EDID_CEC_ID_ADDR 0x00a100a0
#define EDID_AUTO_CEC_EN 0
#define HHI_32K_CLK_CNTL (0x89 << 2)
+struct dbgflg {
+ unsigned int hal_cmd_bypass:1;
-
+};
#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI
extern unsigned long hdmirx_rd_top(unsigned long addr);
@@ -418,6 +438,7 @@ void cec_arbit_bit_time_set(unsigned int bit_set,
unsigned int time_set, unsigned int flag);
void cec_irq_enable(bool enable);
void aocec_irq_enable(bool enable);
+extern void dump_reg(void);
#endif
#endif /* __AO_CEC_H__ */