media: mfc: add MMCache handling for MFC only
authorJeonghee Kim <jhhhh.kim@samsung.com>
Tue, 17 Apr 2018 07:54:49 +0000 (16:54 +0900)
committerSunyoung Kang <sy0816.kang@samsung.com>
Tue, 29 May 2018 06:59:18 +0000 (15:59 +0900)
Change-Id: I4c5368ad277013df30110774a4a445f25de89071
Signed-off-by: Jiho Chang <jiho04.chang@samsung.com>
Signed-off-by: Jeonghee Kim <jhhhh.kim@samsung.com>
13 files changed:
drivers/media/platform/exynos/mfc/Makefile
drivers/media/platform/exynos/mfc/s5p_mfc.c
drivers/media/platform/exynos/mfc/s5p_mfc_cmd.c
drivers/media/platform/exynos/mfc/s5p_mfc_common.h
drivers/media/platform/exynos/mfc/s5p_mfc_data_struct.h
drivers/media/platform/exynos/mfc/s5p_mfc_debug.h
drivers/media/platform/exynos/mfc/s5p_mfc_debugfs.c
drivers/media/platform/exynos/mfc/s5p_mfc_dec.c
drivers/media/platform/exynos/mfc/s5p_mfc_irq.c
drivers/media/platform/exynos/mfc/s5p_mfc_mmcache.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/s5p_mfc_mmcache.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/s5p_mfc_reg.c
drivers/media/platform/exynos/mfc/s5p_mfc_reg.h

index 36de58256e300d83409d06a7907d79d1797bbc5f..428674d17dd16f6cb743aa90a4a4643b280af48e 100644 (file)
@@ -5,3 +5,4 @@ s5p-mfc-y += s5p_mfc_pm.o s5p_mfc_inst.o s5p_mfc_cmd.o s5p_mfc_cal.o s5p_mfc_reg
 s5p-mfc-y += s5p_mfc_dec_ops.o s5p_mfc_enc_ops.o s5p_mfc_enc_param.o
 s5p-mfc-y += s5p_mfc_queue.o s5p_mfc_buf.o s5p_mfc_utils.o s5p_mfc_qos.o s5p_mfc_mem.o
 s5p-mfc-y += s5p_mfc_debugfs.o s5p_mfc_otf.o
+s5p-mfc-y += s5p_mfc_mmcache.o
index 942e4f126bd165f7c733c1de0346a731b545aa05..705ac511f272fb58a510734dcfd39a434822b5be 100644 (file)
@@ -40,6 +40,7 @@
 #include "s5p_mfc_cal.h"
 #include "s5p_mfc_perf_measure.h"
 #include "s5p_mfc_reg.h"
+#include "s5p_mfc_mmcache.h"
 
 #include "s5p_mfc_qos.h"
 #include "s5p_mfc_queue.h"
@@ -385,6 +386,10 @@ static int mfc_init_instance(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx)
                goto err_hw_init;
        }
 
+       if (dev->has_mmcache && (dev->mmcache.is_on_status == 0))
+               s5p_mfc_mmcache_enable(dev);
+
+
        s5p_mfc_release_hwlock_dev(dev);
 
 #ifdef NAL_Q_ENABLE
@@ -743,6 +748,13 @@ static int s5p_mfc_release(struct file *file)
 
        s5p_mfc_qos_off(ctx);
 
+       if (dev->has_mmcache && dev->mmcache.is_on_status) {
+               s5p_mfc_invalidate_mmcache(dev);
+
+               if (dev->num_inst == 0)
+                       s5p_mfc_mmcache_disable(dev);
+       }
+
        s5p_mfc_release_codec_buffers(ctx);
        s5p_mfc_release_instance_context(ctx);
 
@@ -992,6 +1004,7 @@ static int mfc_register_resource(struct platform_device *pdev, struct s5p_mfc_de
        struct device_node *np = dev->device->of_node;
        struct device_node *iommu;
        struct device_node *hwfc;
+       struct device_node *mmcache;
        struct resource *res;
        int ret;
 
@@ -1038,12 +1051,24 @@ static int mfc_register_resource(struct platform_device *pdev, struct s5p_mfc_de
                if (dev->hwfc_base == NULL) {
                        dev->has_hwfc = 0;
                        dev_err(&pdev->dev, "failed to iomap hwfc address region\n");
-                       goto err_res_hwfc;
+                       goto err_ioremap_hwfc;
                } else {
                        dev->has_hwfc = 1;
                }
        }
 
+       mmcache = of_get_child_by_name(np, "mmcache");
+       if (mmcache) {
+               dev->mmcache.base = of_iomap(mmcache, 0);
+               if (dev->mmcache.base == NULL) {
+                       dev->has_mmcache = 0;
+                       dev_err(&pdev->dev, "failed to iomap mmcache address region\n");
+                       goto err_ioremap_mmcache;
+               } else {
+                       dev->has_mmcache = 1;
+               }
+       }
+
        res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (res == NULL) {
                dev_err(&pdev->dev, "failed to get irq resource\n");
@@ -1060,9 +1085,12 @@ static int mfc_register_resource(struct platform_device *pdev, struct s5p_mfc_de
        return 0;
 
 err_res_irq:
+       if (dev->has_mmcache)
+               iounmap(dev->mmcache.base);
+err_ioremap_mmcache:
        if (dev->has_hwfc)
                iounmap(dev->hwfc_base);
-err_res_hwfc:
+err_ioremap_hwfc:
        if (dev->has_2sysmmu)
                iounmap(dev->sysmmu1_base);
        iounmap(dev->sysmmu0_base);
@@ -1278,6 +1306,8 @@ alloc_vdev_dec:
 err_v4l2_dev:
        mutex_destroy(&dev->mfc_mutex);
        free_irq(dev->irq, dev);
+       if (dev->has_mmcache)
+               iounmap(dev->mmcache.base);
        if (dev->has_hwfc)
                iounmap(dev->hwfc_base);
        if (dev->has_2sysmmu)
@@ -1319,6 +1349,8 @@ static int s5p_mfc_remove(struct platform_device *pdev)
        mfc_debug(2, "Will now deinit HW\n");
        s5p_mfc_deinit_hw(dev);
        free_irq(dev->irq, dev);
+       if (dev->has_mmcache)
+               iounmap(dev->mmcache.base);
        if (dev->has_hwfc)
                iounmap(dev->hwfc_base);
        if (dev->has_2sysmmu)
index 0d7e5c8a2a015bccfcbc62f07189b825a66a1b5d..3d2614c8c83a2f2f043f17220de3b4a8e93603e7 100644 (file)
@@ -16,6 +16,7 @@
 
 #include "s5p_mfc_cal.h"
 #include "s5p_mfc_reg.h"
+#include "s5p_mfc_mmcache.h"
 
 #include "s5p_mfc_utils.h"
 #include "s5p_mfc_buf.h"
@@ -225,6 +226,10 @@ int s5p_mfc_cmd_dec_init_buffers(struct s5p_mfc_ctx *ctx)
        ret = s5p_mfc_set_dec_codec_buffers(ctx);
        if (ret) {
                mfc_info_ctx("isn't enough codec buffer size, re-alloc!\n");
+
+               if (dev->has_mmcache && dev->mmcache.is_on_status)
+                       s5p_mfc_invalidate_mmcache(dev);
+
                s5p_mfc_release_codec_buffers(ctx);
                ret = s5p_mfc_alloc_codec_buffers(ctx);
                if (ret) {
@@ -275,6 +280,10 @@ int s5p_mfc_cmd_enc_init_buffers(struct s5p_mfc_ctx *ctx)
        ret = s5p_mfc_set_enc_codec_buffers(ctx);
        if (ret) {
                mfc_info_ctx("isn't enough codec buffer size, re-alloc!\n");
+
+               if (dev->has_mmcache && dev->mmcache.is_on_status)
+                       s5p_mfc_invalidate_mmcache(dev);
+
                s5p_mfc_release_codec_buffers(ctx);
                ret = s5p_mfc_alloc_codec_buffers(ctx);
                if (ret) {
index 5d9b5c24cbb1d2f7890bfe7eea118c584505df2e..2d6b28fde6fe3dd69dcf1443168f447fa23c1e5b 100644 (file)
@@ -44,6 +44,8 @@
 #define MFC_HWLOCK_TIMEOUT     5000
 /* Busy wait timeout */
 #define MFC_BW_TIMEOUT         500
+/* MMCache invalidation timeout */
+#define MMCACHE_INVAL_TIMEOUT  1000
 /* Interrupt timeout count*/
 #define MFC_INT_TIMEOUT_CNT    2
 
index dcc1ddd21931ead601e6fc31842e5319a77bfad7..2134b7fb1cf52f8a819d68484191b72e3c983d0c 100644 (file)
@@ -337,6 +337,8 @@ struct s5p_mfc_debugfs {
        struct dentry *otf_dump;
        struct dentry *perf_measure_option;
        struct dentry *sfr_dump;
+       struct dentry *mmcache_dump;
+       struct dentry *mmcache_disable;
        struct dentry *debug_mode;
 };
 
@@ -672,6 +674,11 @@ struct s5p_mfc_dump_ops {
        void (*dump_and_stop_debug_mode)(struct s5p_mfc_dev *dev);
 };
 
+struct s5p_mfc_mmcache {
+       void __iomem *base;
+       int is_on_status;
+};
+
 /**
  * struct s5p_mfc_dev - The struct containing driver internal parameters.
  */
@@ -710,8 +717,9 @@ struct s5p_mfc_dev {
        wait_queue_head_t cmd_wq;
        struct s5p_mfc_listable_wq hwlock_wq;
 
-       bool has_hwfc;
        bool has_2sysmmu;
+       bool has_hwfc;
+       bool has_mmcache;
 
        struct s5p_mfc_special_buf common_ctx_buf;
        struct s5p_mfc_special_buf drm_common_ctx_buf;
@@ -777,6 +785,8 @@ struct s5p_mfc_dev {
        struct s5p_mfc_dump_ops *dump_ops;
 
        struct s5p_mfc_perf perf;
+
+       struct s5p_mfc_mmcache mmcache;
 };
 
 /**
index 8d626590e93fc253665f9c7b4517b77fbec66d73..2b9f45a743882f9610bde772932935800f0b5167 100644 (file)
@@ -25,6 +25,8 @@ extern unsigned int nal_q_disable;
 extern unsigned int nal_q_parallel_disable;
 extern unsigned int otf_dump;
 extern unsigned int sfr_dump;
+extern unsigned int mmcache_dump;
+extern unsigned int mmcache_disable;
 extern unsigned int debug_mode;
 
 #define mfc_debug(level, fmt, args...)                         \
index 58a824fc08037d8eae5e9340f224d5ef449c0376..03a98b7759fd3432ac410694f4fbf23055d1efd6 100644 (file)
@@ -29,6 +29,8 @@ unsigned int nal_q_parallel_disable;
 unsigned int otf_dump;
 unsigned int perf_measure_option;
 unsigned int sfr_dump;
+unsigned int mmcache_dump;
+unsigned int mmcache_disable;
 /* It will be disable after driver is stabilized */
 unsigned int debug_mode = 1;
 
@@ -50,6 +52,9 @@ static int mfc_info_show(struct seq_file *s, void *unused)
        seq_printf(s, "[HWLOCK] bits: %#lx, dev: %#lx, owned_by_irq = %d, wl_count = %d\n",
                        dev->hwlock.bits, dev->hwlock.dev,
                        dev->hwlock.owned_by_irq, dev->hwlock.wl_count);
+       seq_printf(s, "[MMCACHE] %s(%s)\n",
+                       dev->has_mmcache ? "supported" : "not supported",
+                       dev->mmcache.is_on_status ? "enabled" : "disabled");
        if (dev->nal_q_handle)
                seq_printf(s, "[NAL-Q] state: %d\n", dev->nal_q_handle->nal_q_state);
 
@@ -151,6 +156,10 @@ void s5p_mfc_init_debugfs(struct s5p_mfc_dev *dev)
                        0644, debugfs->root, &perf_measure_option);
        debugfs->sfr_dump = debugfs_create_u32("sfr_dump",
                        0644, debugfs->root, &sfr_dump);
+       debugfs->mmcache_dump = debugfs_create_u32("mmcache_dump",
+                       0644, debugfs->root, &mmcache_dump);
+       debugfs->mmcache_disable = debugfs_create_u32("mmcache_disable",
+                       0644, debugfs->root, &mmcache_disable);
        debugfs->debug_mode = debugfs_create_u32("debug_mode",
                        0644, debugfs->root, &debug_mode);
 }
index bd0f354f372faf125b86c5741a17023614f31a76..001e3b3aedfe85c0504950424434d6304a0f028c 100644 (file)
@@ -16,6 +16,7 @@
 #include "s5p_mfc_hwlock.h"
 #include "s5p_mfc_opr.h"
 #include "s5p_mfc_sync.h"
+#include "s5p_mfc_mmcache.h"
 
 #include "s5p_mfc_qos.h"
 #include "s5p_mfc_queue.h"
@@ -626,6 +627,10 @@ static int vidioc_reqbufs(struct file *file, void *priv,
                if (reqbufs->count == 0) {
                        mfc_debug(2, "Freeing buffers.\n");
                        ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+
+                       if (dev->has_mmcache && dev->mmcache.is_on_status)
+                               s5p_mfc_invalidate_mmcache(dev);
+
                        s5p_mfc_release_codec_buffers(ctx);
                        ctx->capture_state = QUEUE_FREE;
                        return ret;
index 228679f9834988b6d32cbe2a79e2bb15c3376dfc..403fdba16e654f4ca873387f1f9adcba211c248a 100644 (file)
@@ -22,6 +22,7 @@
 #include "s5p_mfc_cal.h"
 #include "s5p_mfc_perf_measure.h"
 #include "s5p_mfc_reg.h"
+#include "s5p_mfc_mmcache.h"
 
 #include "s5p_mfc_qos.h"
 #include "s5p_mfc_queue.h"
@@ -746,6 +747,9 @@ static void mfc_enc_res_change(struct s5p_mfc_ctx *ctx)
                mfc_debug(2, "Encoding Resolution Status : %d\n", reg);
 
                if (reg == 2 || reg == 3) {
+                       if (dev->has_mmcache && dev->mmcache.is_on_status)
+                               s5p_mfc_invalidate_mmcache(dev);
+
                        s5p_mfc_release_codec_buffers(ctx);
                        /* for INIT_BUFFER cmd */
                        s5p_mfc_change_state(ctx, MFCINST_HEAD_PARSED);
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_mmcache.c b/drivers/media/platform/exynos/mfc/s5p_mfc_mmcache.c
new file mode 100644 (file)
index 0000000..a5a07b7
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_mmcache.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "s5p_mfc_mmcache.h"
+
+#include "s5p_mfc_reg.h"
+
+static const unsigned char mmcache_SFR_0x0010[] = {
+       0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+       0x2A, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const unsigned char mmcache_SFR_0x0040[] = {
+       0x0E, 0x00, 0x1E, 0x00, 0x0E, 0x00, 0x1E, 0x00, 0x0E, 0x00, 0x1E, 0x00, 0x0E, 0x00, 0x1E, 0x00,
+       0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+       0x10, 0x00, 0x1F, 0x00, 0x10, 0x00, 0x1F, 0x00, 0x10, 0x00, 0x1F, 0x00, 0x10, 0x00, 0x1F, 0x00,
+       0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+       0x0C, 0x00, 0x1F, 0x00, 0x0C, 0x00, 0x1F, 0x00, 0x0C, 0x00, 0x1F, 0x00, 0x0C, 0x00, 0x1F, 0x00,
+       0x12, 0x00, 0x3F, 0x00, 0x08, 0x00, 0x3F, 0x00, 0x0C, 0x00, 0x3D, 0x00, 0x0C, 0x00, 0x3D, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static void mmcache_print_config(struct s5p_mfc_dev *dev)
+{
+       void __iomem *addr;
+       unsigned int size;
+
+       mfc_debug_enter();
+
+       if (!mmcache_dump)
+               return;
+
+       size = sizeof(mmcache_SFR_0x0010);
+       addr = dev->mmcache.base + MMCACHE_WAY0_CTRL;
+
+       print_hex_dump(KERN_ERR, "[MMCACHE] Config:", DUMP_PREFIX_ADDRESS, 32, 4, addr, size, false);
+
+       size = sizeof(mmcache_SFR_0x0040);
+       addr = dev->mmcache.base + MMCACHE_MASTER_GRP0_RPATH0;
+
+       print_hex_dump(KERN_ERR, "[MMCACHE] Config:", DUMP_PREFIX_ADDRESS, 32, 4, addr, size, false);
+
+       mfc_debug_leave();
+}
+
+static void mmcache_set_config(struct s5p_mfc_dev *dev)
+{
+       unsigned int data, i, size;
+       const unsigned int *sfr_dump;
+
+       mfc_debug_enter();
+
+       size = sizeof(mmcache_SFR_0x0010);
+       sfr_dump = (const unsigned int *)mmcache_SFR_0x0010;
+
+       for (i = 0; i < size; i += 4) {
+               data = sfr_dump[i / 4];
+               MMCACHE_WRITEL(data, MMCACHE_WAY0_CTRL + i);
+       }
+
+       size = sizeof(mmcache_SFR_0x0040);
+       sfr_dump = (const unsigned int *)mmcache_SFR_0x0040;
+
+       for (i = 0; i < size; i += 4) {
+               data = sfr_dump[i / 4];
+               MMCACHE_WRITEL(data, MMCACHE_MASTER_GRP0_RPATH0 + i);
+       }
+
+       mfc_debug(2, "[MMCACHE] mmcache config setting is done\n");
+
+       mfc_debug_leave();
+}
+
+static void mmcache_reset_config(struct s5p_mfc_dev *dev)
+{
+       void __iomem *addr;
+       unsigned int data;
+
+       mfc_debug_enter();
+
+       addr = dev->mmcache.base + MMCACHE_MASTER_GRP_CTRL2;
+       data = 0;
+
+       mfc_debug(2, "[MMCACHE] before write 0x%X: (0x%08llX) 0x%X\n",
+                       data, (unsigned long long)(addr),
+                       MMCACHE_READL(MMCACHE_MASTER_GRP_CTRL2));
+
+       MMCACHE_WRITEL(data, MMCACHE_MASTER_GRP_CTRL2);
+
+       mfc_debug(2, "[MMCACHE] after write 0x%X: (0x%08llX) 0x%X\n",
+                       data, (unsigned long long)(addr),
+                       MMCACHE_READL(MMCACHE_MASTER_GRP_CTRL2));
+
+       mfc_debug_leave();
+}
+
+static void mmcache_update_master_grp(struct s5p_mfc_dev *dev)
+{
+       void __iomem *addr;
+       unsigned int data;
+
+       mfc_debug_enter();
+
+       addr = dev->mmcache.base + MMCACHE_GLOBAL_CTRL;
+       data = MMCACHE_GLOBAL_CTRL_VALUE;
+
+       mfc_debug(2, "[MMCACHE] before write 0x%X: (0x%08llX) 0x%X\n",
+                       data, (unsigned long long)(addr),
+                       MMCACHE_READL(MMCACHE_GLOBAL_CTRL));
+
+       MMCACHE_WRITEL(data, MMCACHE_GLOBAL_CTRL);
+
+       mfc_debug(2, "[MMCACHE] after write 0x%X: (0x%08llX) 0x%X\n",
+                       data, (unsigned long long)(addr),
+                       MMCACHE_READL(MMCACHE_GLOBAL_CTRL));
+
+       mfc_debug_leave();
+}
+
+static void mmcache_enable_clock_gating(struct s5p_mfc_dev *dev)
+{
+       void __iomem *addr;
+       unsigned int data;
+
+       mfc_debug_enter();
+
+       addr = dev->mmcache.base + MMCACHE_CG_CONTROL;
+       data = MMCACHE_CG_CONTROL_VALUE;
+
+       mfc_debug(2, "[MMCACHE] before write 0x%X: (0x%08llX) 0x%X\n",
+                       data, (unsigned long long)(addr),
+                       MMCACHE_READL(MMCACHE_CG_CONTROL));
+
+       MMCACHE_WRITEL(data, MMCACHE_CG_CONTROL);
+
+       mfc_debug(2, "[MMCACHE] after write 0x%X: (0x%08llX) 0x%X\n",
+                       data, (unsigned long long)(addr),
+                       MMCACHE_READL(MMCACHE_CG_CONTROL));
+
+       mfc_debug_leave();
+}
+
+void s5p_mfc_mmcache_enable(struct s5p_mfc_dev *dev)
+{
+       mfc_debug_enter();
+
+       if (mmcache_disable)
+               return;
+
+       mmcache_set_config(dev);
+       mmcache_print_config(dev);
+       mmcache_update_master_grp(dev);
+       mmcache_enable_clock_gating(dev);
+
+       dev->mmcache.is_on_status = 1;
+       mfc_info_dev("[MMCACHE] enabled\n");
+       MFC_TRACE_DEV("[MMCACHE] enabled\n");
+
+       mfc_debug_leave();
+}
+
+void s5p_mfc_mmcache_disable(struct s5p_mfc_dev *dev)
+{
+       mfc_debug_enter();
+
+       mmcache_reset_config(dev);
+       mmcache_update_master_grp(dev);
+
+       dev->mmcache.is_on_status = 0;
+       mfc_info_dev("[MMCACHE] disabled\n");
+       MFC_TRACE_DEV("[MMCACHE] disabled\n");
+
+       mfc_debug_leave();
+}
+
+void s5p_mfc_invalidate_mmcache(struct s5p_mfc_dev *dev)
+{
+       void __iomem *addr;
+       unsigned int data;
+       unsigned long timeout;
+
+       mfc_debug_enter();
+
+       addr = dev->mmcache.base + MMCACHE_INVALIDATE;
+       data = MMCACHE_INVALIDATE_VALUE;
+
+       mfc_debug(2, "[MMCACHE] before write 0x%X: (0x%08llX) 0x%X\n",
+                       data, (unsigned long long)(addr),
+                       MMCACHE_READL(MMCACHE_INVALIDATE));
+
+       MMCACHE_WRITEL(data, MMCACHE_INVALIDATE);
+
+       mfc_debug(2, "[MMCACHE] after write 0x%X: (0x%08llX) 0x%X\n",
+                       data, (unsigned long long)(addr),
+                       MMCACHE_READL(MMCACHE_INVALIDATE));
+
+       addr = dev->mmcache.base + MMCACHE_INVALIDATE_STATUS;
+
+       timeout = jiffies + msecs_to_jiffies(MMCACHE_INVAL_TIMEOUT);
+       while (1) {
+               if (MMCACHE_READL(MMCACHE_INVALIDATE_STATUS) == 0) {
+                       mfc_debug(2, "[MMCACHE] invalidate done: (0x%08llX) 0x%X\n",
+                                       (unsigned long long)(addr), __raw_readl(addr));
+                       break;
+               }
+               if (time_after(jiffies, timeout)) {
+                       mfc_err_dev("[MMCACHE] Timeout while invalidation.\n");
+                       call_dop(dev, dump_and_stop_debug_mode, dev);
+                       break;
+               }
+       }
+
+       mfc_debug(2, "[MMCACHE] invalidated\n");
+       MFC_TRACE_DEV("[MMCACHE] invalidated\n");
+
+       mfc_debug_leave();
+}
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_mmcache.h b/drivers/media/platform/exynos/mfc/s5p_mfc_mmcache.h
new file mode 100644 (file)
index 0000000..f4cfa4d
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_mmcache.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __S5P_MFC_MMCACHE_H
+#define __S5P_MFC_MMCACHE_H __FILE__
+
+#include "s5p_mfc_common.h"
+
+#define MMCACHE_GLOBAL_CTRL            0x0000
+#define MMCACHE_INVALIDATE_STATUS      0x0008
+#define MMCACHE_WAY0_CTRL              0x0010
+#define MMCACHE_MASTER_GRP_CTRL2       0x0028
+#define MMCACHE_MASTER_GRP0_RPATH0     0x0040
+#define MMCACHE_CG_CONTROL             0x0400
+#define MMCACHE_INVALIDATE             0x0114
+
+#define MMCACHE_GLOBAL_CTRL_VALUE      0x2
+#define MMCACHE_CG_CONTROL_VALUE       0x7FF
+#define MMCACHE_INVALIDATE_VALUE       0x41
+
+/* Need HW lock to call this function */
+
+void s5p_mfc_mmcache_enable(struct s5p_mfc_dev *dev);
+void s5p_mfc_mmcache_disable(struct s5p_mfc_dev *dev);
+
+
+/* Need HW lock to call this function */
+void s5p_mfc_invalidate_mmcache(struct s5p_mfc_dev *dev);
+
+#endif /* __S5P_MFC_MMCACHE_H */
index e8c77f03de7cd8ee61820e4cfb7f96043a79dbab..aee8f0ebad27253261f6e3bab4bad53212a3b8e0 100644 (file)
@@ -78,7 +78,7 @@ void s5p_mfc_otf_set_hwfc_index(struct s5p_mfc_ctx *ctx, int job_id)
        struct s5p_mfc_dev *dev = ctx->dev;
 
        mfc_debug(2, "OTF: set hwfc index, %d\n", job_id);
-       MFC_WRITEL_HWFC(job_id, HWFC_ENCODING_IDX);
+       HWFC_WRITEL(job_id, HWFC_ENCODING_IDX);
 }
 
 /* Set decoding frame buffer */
index d8700bb91a804a5527061796029f3731f80c83d1..bc4b1154427587d741167b83cf2a04ea268cc879 100644 (file)
 #define MFC_MMU0_READL(offset)         readl(dev->sysmmu0_base + (offset))
 #define MFC_MMU1_READL(offset)         readl(dev->sysmmu1_base + (offset))
 
-#define MFC_WRITEL_HWFC(data, offset)  writel((data), dev->hwfc_base + (offset))
+#define HWFC_WRITEL(data, offset)      writel((data), dev->hwfc_base + (offset))
+
+#define MMCACHE_READL(offset)          readl(dev->mmcache.base + (offset))
+#define MMCACHE_WRITEL(data, offset)   writel((data), dev->mmcache.base + (offset))
 
 /* version */
 #define s5p_mfc_get_fimv_info()                ((MFC_READL(S5P_FIMV_FW_VERSION)                \