From cf3a533906fea21f7fb2f6db5c2232f7c57a2a02 Mon Sep 17 00:00:00 2001 From: Chun Xu Date: Fri, 19 Jan 2018 11:08:51 +0800 Subject: [PATCH] tegra_cec: suppport dump registers and snoop mode Provide dump registers and changingRX snoop mode interface. Bug 200382184 Change-Id: Idb55d22112bc6be9de89b8ff8e060e73de469507 Signed-off-by: Chun Xu Reviewed-on: https://git-master.nvidia.com/r/1765068 (cherry picked from commit 3310df0f117d792d3d0bfab6326592851faaeed7) Reviewed-on: https://git-master.nvidia.com/r/1641846 Reviewed-by: svc-mobile-coverity GVS: Gerrit_Virtual_Submit Reviewed-by: Prafull Suryawanshi Reviewed-by: Sachin Nikam Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/misc/tegra-cec/tegra_cec.c | 61 ++++++++++++++++++++++++++++++ drivers/misc/tegra-cec/tegra_cec.h | 4 ++ 2 files changed, 65 insertions(+) diff --git a/drivers/misc/tegra-cec/tegra_cec.c b/drivers/misc/tegra-cec/tegra_cec.c index eaf68014..affe3cde 100644 --- a/drivers/misc/tegra-cec/tegra_cec.c +++ b/drivers/misc/tegra-cec/tegra_cec.c @@ -325,9 +325,49 @@ out: return IRQ_HANDLED; } +static int tegra_cec_dump_registers(struct tegra_cec *cec) +{ + int value, i; + + dev_info(cec->dev, "base address = %llx\n", (u64)cec->cec_base); + for(i = 0; i <= TEGRA_CEC_HW_SPARE; i+=4) + { + value = readl(cec->cec_base + i); + dev_info(cec->dev, "offset %08x: %08x\n", i, value); + } + return i; + +} + +static int tegra_cec_set_rx_snoop(struct tegra_cec *cec, u32 enable) +{ + u32 state; + + if (!atomic_read(&cec->init_done)) + return -EAGAIN; + state = readl(cec->cec_base + TEGRA_CEC_HW_CONTROL); + if (((state & TEGRA_CEC_HWCTRL_RX_SNOOP) != 0) ^ (enable != 0)) { + state ^= TEGRA_CEC_HWCTRL_RX_SNOOP; + writel(state, cec->cec_base + TEGRA_CEC_HW_CONTROL); + } + return 0; +} + +static int tegra_cec_get_rx_snoop(struct tegra_cec *cec, u32 *state) +{ + if (!atomic_read(&cec->init_done)) + return -EAGAIN; + *state = (readl(cec->cec_base + TEGRA_CEC_HW_CONTROL) & TEGRA_CEC_HWCTRL_RX_SNOOP) >> 15; + return 0; +} + + static long tegra_cec_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { + int err; + u32 state; + struct tegra_cec *cec = file->private_data; if (_IOC_TYPE(cmd) != TEGRA_CEC_IOC_MAGIC) @@ -339,6 +379,27 @@ static long tegra_cec_ioctl(struct file *file, unsigned int cmd, tegra_cec_error_recovery(cec); mutex_unlock(&cec->recovery_lock); break; + case TEGRA_CEC_IOCTL_DUMP_REGISTERS: + tegra_cec_dump_registers(cec); + break; + case TEGRA_CEC_IOCTL_SET_RX_SNOOP: + err = !access_ok(VERIFY_READ, arg, sizeof(u32)); + if (err) + return -EFAULT; + if (copy_from_user((u32 *) &state, (u32 *) arg, sizeof(u32))) + return -EFAULT; + tegra_cec_set_rx_snoop(cec, state); + break; + case TEGRA_CEC_IOCTL_GET_RX_SNOOP: + err = !access_ok(VERIFY_WRITE, arg, sizeof(u32)); + if (err) + return -EFAULT; + err = tegra_cec_get_rx_snoop(cec, &state); + if (!err) { + if (copy_to_user((u32 *) arg, &state, sizeof(u32))) + return -EFAULT; + } + break; default: dev_err(cec->dev, "unsupported ioctl\n"); return -EINVAL; diff --git a/drivers/misc/tegra-cec/tegra_cec.h b/drivers/misc/tegra-cec/tegra_cec.h index 34300d0f..70881a3d 100644 --- a/drivers/misc/tegra-cec/tegra_cec.h +++ b/drivers/misc/tegra-cec/tegra_cec.h @@ -77,6 +77,7 @@ static int tegra_cec_remove(struct platform_device *pdev); #define TEGRA_CEC_INT_MASK 0X034 #define TEGRA_CEC_HW_DEBUG_RX 0X038 #define TEGRA_CEC_HW_DEBUG_TX 0X03C +#define TEGRA_CEC_HW_SPARE 0X03C #define TEGRA_CEC_MAX_LOGICAL_ADDR 15 #define TEGRA_CEC_HWCTRL_RX_LADDR_UNREG 0x0 @@ -167,5 +168,8 @@ static int tegra_cec_remove(struct platform_device *pdev); #define TEGRA_CEC_IOC_MAGIC 'C' #define TEGRA_CEC_IOCTL_ERROR_RECOVERY _IO(TEGRA_CEC_IOC_MAGIC, 1) +#define TEGRA_CEC_IOCTL_DUMP_REGISTERS _IO(TEGRA_CEC_IOC_MAGIC, 2) +#define TEGRA_CEC_IOCTL_SET_RX_SNOOP _IO(TEGRA_CEC_IOC_MAGIC, 3) +#define TEGRA_CEC_IOCTL_GET_RX_SNOOP _IO(TEGRA_CEC_IOC_MAGIC, 4) #endif /* TEGRA_CEC_H */