tvafe: Reg access protection [1/1]
authorYong Qin <yong.qin@amlogic.com>
Mon, 5 Aug 2019 08:16:14 +0000 (16:16 +0800)
committerTao Zeng <tao.zeng@amlogic.com>
Thu, 15 Aug 2019 02:39:42 +0000 (19:39 -0700)
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 <yong.qin@amlogic.com>
drivers/amlogic/media/vin/tvin/tvafe/tvafe.c
drivers/amlogic/media/vin/tvin/tvafe/tvafe.h
drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c
drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.h
drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c
drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.h
drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.c
drivers/amlogic/media/vin/tvin/tvafe/tvafe_vbi.h

index d1e14c9d6822d337f7ff28e9ca0f4a2c55756a66..791c04a4b08d957e7d2da03d629671dd3a00475b 100644 (file)
@@ -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");
 }
 
index b64afd18d5428ca486360fe6796ba1a23f7ab4b6..1a616636c0aec12841e1d30d9db3d0ffbf3e05b5 100644 (file)
@@ -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;
 
index 87ba42a40cdeefda238b04e0c297ce423cf41185..bf6ae789c4cb8c73b0f232a5664aa334ee668305 100644 (file)
@@ -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 */
index d84dee21ca930a2a0a338fbc0d64abfb71ea4f60..aba0ecfc2ff125250303cc128339c131ae03fb57 100644 (file)
@@ -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 */
 
index a296131624fd13295047707db7e713dd4814bc8b..1e8d4e2ab0f6194da54700bed41a05e1cba855a1 100644 (file)
@@ -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;
index f2067aa6e20f6e189c29519a50a7f2ba5bedf1e0..c06552d463d52e5afbf17176402c9938a1c19448 100644 (file)
 
 /* 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 */
index 9cd74d886334adecb1e36de9031a812c1820a8b9..f6d49ff251fffc0c762aa41e898dc7587d6766ae 100644 (file)
@@ -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;
index 8310cabb70b3a1749b69fe2501ace7be8140ee71..867847264b29f505ce6bba0df2eb29bc8c052ef4 100644 (file)
@@ -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_ */