[COMMON] media: mfc: check the MFC pending
authorAyoung Sim <a.sim@samsung.com>
Tue, 22 Jan 2019 07:04:53 +0000 (16:04 +0900)
committerKim Gunho <gunho.kim@samsung.com>
Fri, 28 Jun 2019 14:45:37 +0000 (23:45 +0900)
MFC transaction should never occur in the section
where the MFC attribute is changed. (Normal <-> Secure)
But transaction can be send by HWACG although clock was disabled.
So, we check the pending both F/W and H/W.

Change-Id: I9f5b9eafa5c94cd159142be0e906638544467072
Signed-off-by: Ayoung Sim <a.sim@samsung.com>
drivers/media/platform/exynos/mfc/mfc_hw_reg_api.h
drivers/media/platform/exynos/mfc/mfc_pm.c
drivers/media/platform/exynos/mfc/mfc_regs.h

index a3d15bb149841e719aaaa308f9355915c027b731..383e86cce91a74290bf0ab64fef7cfd81ae7e916 100644 (file)
                        MFC_WRITEL(0, MFC_REG_RISC2HOST_INT);   \
                } while (0)
 
+static inline int mfc_wait_pending(struct mfc_dev *dev)
+{
+       unsigned int status;
+       unsigned long timeout;
+
+       /* Check F/W wait status */
+       timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
+       do {
+               if (time_after(jiffies, timeout)) {
+                       mfc_err_dev("Timeout while waiting MFC F/W done\n");
+                       return -EIO;
+               }
+               status = MFC_READL(MFC_REG_FIRMWARE_STATUS_INFO);
+       } while ((status & 0x1) == 0);
+
+       /* Check H/W pending status */
+       timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
+       do {
+               if (time_after(jiffies, timeout)) {
+                       mfc_err_dev("Timeout while pendng clear\n");
+                       mfc_err_dev("MFC access pending R: %#x, BUS: %#x\n",
+                                       MFC_READL(MFC_REG_MFC_RPEND),
+                                       MFC_READL(MFC_REG_MFC_BUS_STATUS));
+                       return -EIO;
+               }
+               status = MFC_READL(MFC_REG_MFC_RPEND);
+       } while (status != 0);
+
+       MFC_TRACE_DEV("** pending wait done\n");
+
+       return 0;
+}
+
 static inline int mfc_stop_bus(struct mfc_dev *dev)
 {
        unsigned int status;
index 0172fe72148fd4e45806e284f8fb6bfa530cd96b..8c5fb3670e094792f28ad50861dae93fc09784cd 100644 (file)
@@ -55,10 +55,19 @@ int mfc_pm_clock_on(struct mfc_dev *dev)
         * -> IP Protection enable -> clock on
         */
        dev->pm.clock_on_steps |= 0x1 << 1;
-       if (dev->pm.base_type != MFCBUF_INVALID)
+       if (dev->pm.base_type != MFCBUF_INVALID) {
+               dev->pm.clock_on_steps |= 0x1 << 2;
+               ret = mfc_wait_pending(dev);
+               if (ret != 0) {
+                       mfc_err_dev("pending wait failed (%d)\n", ret);
+                       call_dop(dev, dump_and_stop_debug_mode, dev);
+                       return ret;
+               }
+               dev->pm.clock_on_steps |= 0x1 << 3;
                mfc_set_risc_base_addr(dev, dev->pm.base_type);
+       }
 
-       dev->pm.clock_on_steps |= 0x1 << 2;
+       dev->pm.clock_on_steps |= 0x1 << 4;
 #ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
        if (dev->curr_ctx_is_drm) {
                unsigned long flags;
@@ -67,7 +76,7 @@ int mfc_pm_clock_on(struct mfc_dev *dev)
                mfc_debug(3, "Begin: enable protection\n");
                ret = exynos_smc(SMC_PROTECTION_SET, 0,
                                        dev->id, SMC_PROTECTION_ENABLE);
-               dev->pm.clock_on_steps |= 0x1 << 3;
+               dev->pm.clock_on_steps |= 0x1 << 5;
                if (ret != DRMDRV_OK) {
                        mfc_err_dev("Protection Enable failed! ret(%u)\n", ret);
                        call_dop(dev, dump_and_stop_debug_mode, dev);
@@ -79,7 +88,7 @@ int mfc_pm_clock_on(struct mfc_dev *dev)
        }
 #endif
 
-       dev->pm.clock_on_steps |= 0x1 << 4;
+       dev->pm.clock_on_steps |= 0x1 << 6;
        ret = clk_enable(dev->pm.clock);
        if (ret < 0) {
                mfc_err_dev("clk_enable failed (%d)\n", ret);
@@ -87,13 +96,13 @@ int mfc_pm_clock_on(struct mfc_dev *dev)
                return ret;
        }
 
-       dev->pm.clock_on_steps |= 0x1 << 5;
+       dev->pm.clock_on_steps |= 0x1 << 7;
        atomic_inc_return(&dev->clk_ref);
 
-       dev->pm.clock_on_steps |= 0x1 << 6;
+       dev->pm.clock_on_steps |= 0x1 << 8;
        state = atomic_read(&dev->clk_ref);
        mfc_debug(2, "+ %d\n", state);
-       MFC_TRACE_DEV("** clock_on end: ref state(%d)\n", state);
+       MFC_TRACE_DEV("** clock_on end: ref(%d) step(%#x)\n", state, dev->pm.clock_on_steps);
        MFC_TRACE_LOG_DEV("c+%d", state);
 
        return 0;
@@ -160,7 +169,7 @@ void mfc_pm_clock_off(struct mfc_dev *dev)
        dev->pm.clock_off_steps |= 0x1 << 7;
        state = atomic_read(&dev->clk_ref);
        mfc_debug(2, "- %d\n", state);
-       MFC_TRACE_DEV("** clock_off end: ref state(%d)\n", state);
+       MFC_TRACE_DEV("** clock_off end: ref(%d) step(%#x)\n", state, dev->pm.clock_off_steps);
        MFC_TRACE_LOG_DEV("c-%d", state);
 }
 
index f5e0368c81c1ea57c58ceb6eadf614154c6071a2..8f22c408c4a91126d0fcf16d0074abf42daed9c0 100644 (file)
@@ -76,6 +76,8 @@
 #define MFC_REG_NAL_QUEUE_INPUT_EXE_COUNT                      0xF090
 #define MFC_REG_NAL_QUEUE_INFO                                 0xF094
 
+#define MFC_REG_FIRMWARE_STATUS_INFO                           0xF0A4
+
 /* Decoder Registers */
 #define MFC_REG_D_CRC_CTRL                                     0xF0B0
 #define MFC_REG_D_DEC_OPTIONS                                  0xF0B4