From: Yong Qin Date: Tue, 24 Jul 2018 05:55:25 +0000 (+0800) Subject: cec: add debug cmd interface X-Git-Tag: khadas-vims-v0.9.6-release~1624 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7fa72600d909ae7169989953a707e5c601bde05b;p=platform%2Fkernel%2Flinux-amlogic.git 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 --- 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__ */