From: Yong Qin Date: Mon, 5 Aug 2019 08:16:14 +0000 (+0800) Subject: tvafe: Reg access protection [1/1] X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=8b95c783b4c444dc97c256f3d762b69846ffce49;p=GitHub%2FLineageOS%2FG12%2Fandroid_kernel_amlogic_linux-4.9.git tvafe: Reg access protection [1/1] PD#TV-8258 Problem: sometime tvafe reg is access after tvafe disabled, cause system panic Solution: 1.add reg access protection 2.hook function add protection condition Verify: x301 Change-Id: I331a3e9cd10ee2ba14d0f3c0768ce1df7e23c2f9 Signed-off-by: Yong Qin --- diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c index d1e14c9d6822..791c04a4b08d 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c @@ -99,7 +99,7 @@ bool tvafe_snow_function_flag; /*1: tvafe clk enabled;*/ /*0: tvafe clk disabled*/ /*read write cvd acd reg will crash when clk disabled*/ -bool tvafe_clk_status; +bool tvafe_clk_onoff; #ifdef CONFIG_AMLOGIC_MEDIA_TVIN_AVDETECT /*opened port,1:av1, 2:av2, 0:none av*/ @@ -121,6 +121,9 @@ unsigned int tvafe_dbg_print; #ifdef CONFIG_AMLOGIC_ATV_DEMOD static struct tvafe_info_s *g_tvafe_info; #endif +bool tvafe_probe_flag; +struct tvafe_dev_s *tvafe_devp; + static struct tvafe_user_param_s tvafe_user_param = { .cutwindow_val_h = {0, 10, 18, 20, 62}, @@ -240,6 +243,17 @@ static int tvafe_get_v_fmt(void) { int fmt = 0; + if (!tvafe_probe_flag || tvafe_devp == NULL) { + tvafe_pr_info("%s tvafe not proble\n", __func__); + return 0; + } + + if (!(tvafe_devp->flags & TVAFE_FLAG_DEV_OPENED) || + (tvafe_devp->flags & TVAFE_POWERDOWN_IN_IDLE)) { + tvafe_pr_info("%s tvafe is PW DOWN\n", __func__); + return 0; + } + if (tvin_get_sm_status(0) != TVIN_SM_STATUS_STABLE) { tvafe_pr_info("%s tvafe is not STABLE\n", __func__); return 0; @@ -334,7 +348,7 @@ static int tvafe_dec_open(struct tvin_frontend_s *fe, enum tvin_port_e port) /* set the flag to enabble ioctl access */ devp->flags |= TVAFE_FLAG_DEV_OPENED; - tvafe_clk_status = true; + tvafe_clk_onoff = true; #ifdef CONFIG_AMLOGIC_ATV_DEMOD g_tvafe_info = tvafe; /* register aml_fe hook for atv search */ @@ -499,7 +513,10 @@ static void tvafe_dec_close(struct tvin_frontend_s *fe) mutex_unlock(&devp->afe_mutex); return; } - tvafe_clk_status = false; + + devp->flags &= (~TVAFE_FLAG_DEV_STARTED); + devp->flags &= (~TVAFE_FLAG_DEV_OPENED); + tvafe_clk_onoff = false; /*del_timer_sync(&devp->timer);*/ #ifdef CONFIG_AMLOGIC_ATV_DEMOD g_tvafe_info = NULL; @@ -546,12 +563,7 @@ static void tvafe_dec_close(struct tvin_frontend_s *fe) #endif /* init variable */ memset(tvafe, 0, sizeof(struct tvafe_info_s)); - - devp->flags &= (~TVAFE_FLAG_DEV_STARTED); - devp->flags &= (~TVAFE_FLAG_DEV_OPENED); - tvafe_pr_info("%s close afe ok.\n", __func__); - mutex_unlock(&devp->afe_mutex); } @@ -726,7 +738,8 @@ bool tvafe_fmt_chg(struct tvin_frontend_s *fe) struct tvafe_info_s *tvafe = &devp->tvafe; enum tvin_port_e port = tvafe->parm.port; - if (!(devp->flags & TVAFE_FLAG_DEV_OPENED)) { + if (!(devp->flags & TVAFE_FLAG_DEV_OPENED) || + (devp->flags & TVAFE_POWERDOWN_IN_IDLE)) { tvafe_pr_err("tvafe havn't opened, get fmt chg error!!!\n"); return true; } @@ -760,7 +773,8 @@ enum tvin_sig_fmt_e tvafe_get_fmt(struct tvin_frontend_s *fe) struct tvafe_info_s *tvafe = &devp->tvafe; enum tvin_port_e port = tvafe->parm.port; - if (!(devp->flags & TVAFE_FLAG_DEV_OPENED)) { + if (!(devp->flags & TVAFE_FLAG_DEV_OPENED) || + (devp->flags & TVAFE_POWERDOWN_IN_IDLE)) { tvafe_pr_err("tvafe havn't opened, get sig fmt error!!!\n"); return fmt; } @@ -1124,7 +1138,7 @@ EXPORT_SYMBOL(tvafe_reg_write); int tvafe_vbi_reg_read(unsigned int reg, unsigned int *val) { - if (tvafe_clk_status) + if (tvafe_clk_onoff) *val = readl(tvafe_reg_base+reg); else return -1; @@ -1134,7 +1148,7 @@ EXPORT_SYMBOL(tvafe_vbi_reg_read); int tvafe_vbi_reg_write(unsigned int reg, unsigned int val) { - if (tvafe_clk_status) + if (tvafe_clk_onoff) writel(val, (tvafe_reg_base+reg)); else return -1; @@ -1301,6 +1315,7 @@ static int tvafe_drv_probe(struct platform_device *pdev) const struct of_device_id *match; /* struct tvin_frontend_s * frontend; */ + tvafe_devp = NULL; match = of_match_device(meson_tvafe_dt_match, &pdev->dev); if (match == NULL) { tvafe_pr_err("%s,no matched table\n", __func__); @@ -1317,6 +1332,7 @@ static int tvafe_drv_probe(struct platform_device *pdev) tdevp = kzalloc(sizeof(struct tvafe_dev_s), GFP_KERNEL); if (!tdevp) goto fail_kzalloc_tdev; + tvafe_devp = tdevp; if (pdev->dev.of_node) { ret = of_property_read_u32(pdev->dev.of_node, @@ -1465,7 +1481,7 @@ static int tvafe_drv_probe(struct platform_device *pdev) disableapi = false; force_stable = false; - + tvafe_probe_flag = true; tvafe_pr_info("driver probe ok\n"); return 0; @@ -1527,7 +1543,7 @@ static int tvafe_drv_suspend(struct platform_device *pdev, } /*disable and reset tvafe clock*/ tdevp->flags |= TVAFE_POWERDOWN_IN_IDLE; - tvafe_clk_status = false; + tvafe_clk_onoff = false; tvafe_enable_module(false); adc_set_pll_reset(); @@ -1545,7 +1561,7 @@ static int tvafe_drv_resume(struct platform_device *pdev) adc_set_pll_reset(); tvafe_enable_module(true); tdevp->flags &= (~TVAFE_POWERDOWN_IN_IDLE); - tvafe_clk_status = false; + tvafe_clk_onoff = true; tvafe_pr_info("resume module\n"); return 0; } @@ -1553,11 +1569,19 @@ static int tvafe_drv_resume(struct platform_device *pdev) static void tvafe_drv_shutdown(struct platform_device *pdev) { + struct tvafe_dev_s *tdevp; + struct tvafe_info_s *tvafe; + + tdevp = platform_get_drvdata(pdev); + tvafe = &tdevp->tvafe; + if (tvafe_cpu_type() == CPU_TYPE_TL1) { W_APB_BIT(TVFE_VAFE_CTRL0, 0, 19, 1); W_APB_BIT(TVFE_VAFE_CTRL1, 0, 8, 1); } adc_pll_down(); + tdevp->flags |= TVAFE_POWERDOWN_IN_IDLE; + tvafe_clk_onoff = false; tvafe_pr_info("tvafe_drv_shutdown ok.\n"); } diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.h b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.h index b64afd18d542..1a616636c0ae 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.h +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.h @@ -132,6 +132,7 @@ extern int tvafe_hiu_reg_write(unsigned int reg, unsigned int val); extern int tvafe_device_create_file(struct device *dev); extern void tvafe_remove_device_files(struct device *dev); +extern bool tvafe_clk_onoff; extern bool disableapi; extern bool force_stable; diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c index 87ba42a40cde..bf6ae789c4cb 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c @@ -352,6 +352,11 @@ static void tvafe_cvd2_write_mode_reg(struct tvafe_cvd2_s *cvd2, struct tvafe_user_param_s *user_param = tvafe_get_user_param(); unsigned int i = 0; + if (!tvafe_clk_onoff) { + tvafe_pr_err("%s: tvafe clk is disabled!\n", __func__); + return; + } + /*disable vbi*/ W_APB_REG(CVD2_VBI_FRAME_CODE_CTL, 0x10); W_APB_REG(ACD_REG_22, 0x07080000); @@ -1174,6 +1179,17 @@ int tvafe_cvd2_get_atv_format(void) { int format; + if (!tvafe_probe_flag || tvafe_devp == NULL) { + tvafe_pr_info("%s tvafe not proble\n", __func__); + return 0; + } + + if (!(tvafe_devp->flags & TVAFE_FLAG_DEV_OPENED) || + (tvafe_devp->flags & TVAFE_POWERDOWN_IN_IDLE)) { + tvafe_pr_info("%s tvafe is PW DOWN\n", __func__); + return 0; + } + format = R_APB_REG(CVD2_STATUS_REGISTER3)&0x7; return format; } @@ -1183,6 +1199,17 @@ int tvafe_cvd2_get_hv_lock(void) { int lock_status; + if (!tvafe_probe_flag || tvafe_devp == NULL) { + tvafe_pr_info("%s tvafe not proble\n", __func__); + return 0; + } + + if (!(tvafe_devp->flags & TVAFE_FLAG_DEV_OPENED) || + (tvafe_devp->flags & TVAFE_POWERDOWN_IN_IDLE)) { + tvafe_pr_info("%s tvafe is PW DOWN\n", __func__); + return 0; + } + lock_status = R_APB_REG(CVD2_STATUS_REGISTER1)&0x6; return lock_status; } @@ -2066,7 +2093,12 @@ inline bool tvafe_cvd2_no_sig(struct tvafe_cvd2_s *cvd2, struct tvafe_cvd2_mem_s *mem) { struct tvafe_user_param_s *user_param = tvafe_get_user_param(); - static bool ret; + bool ret = true; + + if (!tvafe_clk_onoff) { + tvafe_pr_err("%s: tvafe clk is disabled!\n", __func__); + return ret; + } tvafe_cvd2_get_signal_status(cvd2); /* get signal status from HW */ diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.h b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.h index d84dee21ca93..aba0ecfc2ff1 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.h +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.h @@ -225,6 +225,8 @@ extern bool tvafe_snow_function_flag; extern unsigned int try_fmt_max_atv; extern unsigned int try_fmt_max_av; +extern bool tvafe_probe_flag; +extern struct tvafe_dev_s *tvafe_devp; #endif /* _TVAFE_CVD_H */ diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c index a296131624fd..1e8d4e2ab0f6 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c @@ -609,7 +609,7 @@ void adc_pll_down(void) /*ADC_EN_TVAFE 0x2*/ /*ADC_EN_DTV_DEMOD 0x4*/ /*ADC_EN_DTV_DEMODPLL 0x8*/ -int adc_set_pll_cntl(bool on, unsigned int module_sel, void *pDtvPara) +int adc_set_pll_cntl(bool on, enum eADC_PLL_EN module_sel, void *pDtvPara) { unsigned int adc_pll_lock_cnt = 0; int ret = 0; /* 0: success; -x: failed*/ @@ -982,7 +982,7 @@ void tvafe_init_reg(struct tvafe_cvd2_s *cvd2, struct tvafe_cvd2_mem_s *mem, enum tvin_port_e port, struct tvafe_pin_mux_s *pinmux) { - unsigned int module_sel = ADC_EN_TVAFE; + enum eADC_PLL_EN module_sel = ADC_EN_TVAFE; if (port == TVIN_PORT_CVBS3) module_sel = ADC_EN_ATV_DEMOD; diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.h b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.h index f2067aa6e20f..c06552d463d5 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.h +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.h @@ -134,10 +134,12 @@ /* adc pll ctl, atv demod & tvafe use the same adc module*/ /* module index: atv demod:0x01; tvafe:0x2*/ -#define ADC_EN_ATV_DEMOD 0x1 -#define ADC_EN_TVAFE 0x2 -#define ADC_EN_DTV_DEMOD 0x4 -#define ADC_EN_DTV_DEMODPLL 0x8 +enum eADC_PLL_EN { + ADC_EN_ATV_DEMOD = 0x1, + ADC_EN_TVAFE = 0x2, + ADC_EN_DTV_DEMOD = 0x4, + ADC_EN_DTV_DEMODPLL = 0x8, +}; #define LOG_ADC_CAL /* #define LOG_VGA_EDID */ diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.c index 9cd74d886334..f6d49ff251ff 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.c @@ -935,7 +935,7 @@ static void vbi_slicer_work(struct work_struct *p_work) return; if (devp->vbi_start == false) return; - if (tvafe_clk_status == false) { + if (tvafe_clk_onoff == false) { vbi_ringbuffer_flush(&devp->slicer->buffer); return; } @@ -1026,7 +1026,7 @@ static void vbi_slicer_work(struct work_struct *p_work) local_rptr = devp->temp_addr_start; datalen = sizeof(struct vbi_data_s); while (chlen < len) { - if (!devp->vbi_start || !tvafe_clk_status) { + if (!devp->vbi_start || !tvafe_clk_onoff) { if (vbi_dbg_en & VBI_DBG_INFO) tvafe_pr_info("%s: vbi stopped\n", __func__); goto vbi_slicer_work_exit; @@ -1501,7 +1501,7 @@ static ssize_t vbi_buffer_read(struct vbi_ringbuffer_s *src, while (vbi_ringbuffer_empty(src)) { if ((non_blocking || vbi_nonblock_en) || - (tvafe_clk_status == false) || (timeout++ > 50)) { + (tvafe_clk_onoff == false) || (timeout++ > 50)) { ret = -EWOULDBLOCK; tvafe_pr_info("%s:nonblock|closed|timeout return.\n", __func__); @@ -1510,7 +1510,7 @@ static ssize_t vbi_buffer_read(struct vbi_ringbuffer_s *src, msleep(20); } - if (tvafe_clk_status == false) { + if (tvafe_clk_onoff == false) { ret = -EWOULDBLOCK; vbi_ringbuffer_flush(src); if (vbi_dbg_en & VBI_DBG_READ) @@ -1611,7 +1611,7 @@ static int vbi_release(struct inode *inode, struct file *file) free_irq(vbi_dev->vs_irq, (void *)vbi_dev); vbi_dev->irq_free_status = 0; vcnt = 1; - if (tvafe_clk_status) { + if (tvafe_clk_onoff) { /* vbi reset release, vbi agent enable */ /*W_VBI_APB_REG(ACD_REG_22, 0x06080000);*/ W_VBI_APB_REG(CVD2_VBI_FRAME_CODE_CTL, 0x10); @@ -1641,7 +1641,7 @@ static long vbi_ioctl(struct file *file, tvafe_pr_err("%s: slicer mutex error\n", __func__); return -ERESTARTSYS; } - if (tvafe_clk_status) + if (tvafe_clk_onoff) vbi_hw_init(vbi_dev); else { tvafe_pr_err("tvafe not opend.ioctl start err\n"); @@ -1682,7 +1682,7 @@ static long vbi_ioctl(struct file *file, vbi_dev->vbi_start = false; vbi_data_stable_flag = 0; ret = vbi_slicer_stop(vbi_slicer); - if (tvafe_clk_status) { + if (tvafe_clk_onoff) { /* manuel reset vbi */ /*W_VBI_APB_REG(ACD_REG_22, 0x82080000);*/ /* vbi reset release, vbi agent enable*/ @@ -1696,7 +1696,7 @@ static long vbi_ioctl(struct file *file, break; case VBI_IOC_SET_TYPE: - if (!tvafe_clk_status) { + if (!tvafe_clk_onoff) { mutex_unlock(&vbi_dev->mutex); tvafe_pr_info("[vbi..] %s: afe not open,SET_TYPE return\n", __func__); @@ -1714,7 +1714,7 @@ static long vbi_ioctl(struct file *file, mutex_unlock(&vbi_slicer->mutex); break; } - if (tvafe_clk_status) { + if (tvafe_clk_onoff) { ret = vbi_slicer_set(vbi_dev, vbi_slicer); } else { ret = -EFAULT; diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.h b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.h index 8310cabb70b3..867847264b29 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.h +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.h @@ -304,7 +304,7 @@ struct vbi_dev_s { /*1: tvafe clk enable;*/ /*0: tvafe clk disable*/ /*read write cvd acd reg will crash when clk disabled*/ -extern bool tvafe_clk_status; +extern bool tvafe_clk_onoff; extern unsigned int vbi_mem_start; #endif /* TVIN_VBI_H_ */