MLK-22109-2: media: replace dispmix reset flow for ISI and MIPI CSI
authorGuoniu.Zhou <guoniu.zhou@nxp.com>
Wed, 19 Jun 2019 07:27:26 +0000 (15:27 +0800)
committerGuoniu.Zhou <guoniu.zhou@nxp.com>
Wed, 7 Aug 2019 06:29:03 +0000 (14:29 +0800)
After the dispmix reset driver development, the reset flow
is better to be replaced by using this driver to hide the
reset details for all the dispmix submodules, and whose
driver code for reset can become platform independent.

Signed-off-by: Guoniu.Zhou <guoniu.zhou@nxp.com>
drivers/media/platform/imx8/mxc-isi-core.c
drivers/media/platform/imx8/mxc-isi-core.h
drivers/media/platform/imx8/mxc-mipi-csi2-sam.c
drivers/media/platform/imx8/mxc-mipi-csi2-sam.h

index 5cb6cae..de5d176 100644 (file)
@@ -52,42 +52,28 @@ static irqreturn_t mxc_isi_irq_handler(int irq, void *priv)
        return IRQ_HANDLED;
 }
 
-static void disp_mix_sft_rstn(struct regmap *gpr, bool enable)
+static int disp_mix_sft_rstn(struct reset_control *reset, bool enable)
 {
-       if (!gpr)
-               return;
+       int ret;
 
-       if (!enable)
-               /* release isi soft reset */
-               regmap_update_bits(gpr,
-                               DISP_MIX_SFT_RSTN_CSR,
-                               EN_ISI_APB_CLK_RSTN | EN_ISI_PROC_CLK_RSTN,
-                               EN_ISI_APB_CLK_RSTN | EN_ISI_PROC_CLK_RSTN);
-       else
-               regmap_update_bits(gpr,
-                               DISP_MIX_SFT_RSTN_CSR,
-                               EN_ISI_APB_CLK_RSTN | EN_ISI_APB_CLK_RSTN,
-                               0x0);
+       if (!reset)
+               return 0;
 
+       ret = enable ? reset_control_assert(reset) :
+                        reset_control_deassert(reset);
+       return ret;
 }
 
-static void disp_mix_clks_enable(struct regmap *gpr, bool enable)
+static int disp_mix_clks_enable(struct reset_control *reset, bool enable)
 {
-       if (!gpr)
-               return;
+       int ret;
 
-       if (enable)
-               /* enable isi clks */
-               regmap_update_bits(gpr,
-                               DISP_MIX_CLK_EN_CSR,
-                               EN_ISI_APB_CLK | EN_ISI_PROC_CLK,
-                               EN_ISI_APB_CLK | EN_ISI_PROC_CLK);
-       else
-               /* disable isi clks */
-               regmap_update_bits(gpr,
-                               DISP_MIX_CLK_EN_CSR,
-                               EN_ISI_APB_CLK | EN_ISI_PROC_CLK,
-                               0x0);
+       if (!reset)
+               return 0;
+
+       ret = enable ? reset_control_assert(reset) :
+                        reset_control_deassert(reset);
+       return ret;
 }
 
 /**
@@ -296,6 +282,53 @@ static void mxc_isi_clk_disable(struct mxc_isi_dev *mxc_isi)
        ops->clk_disable(mxc_isi);
 }
 
+static int mxc_isi_of_parse_resets(struct mxc_isi_dev *mxc_isi)
+{
+       int ret;
+       struct device *dev = &mxc_isi->pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct device_node *parent, *child;
+       struct of_phandle_args args;
+       struct reset_control *rstc;
+       const char *compat;
+       uint32_t len, rstc_num = 0;
+
+       ret = of_parse_phandle_with_args(np, "resets", "#reset-cells",
+                                        0, &args);
+       if (ret)
+               return ret;
+
+       parent = args.np;
+       for_each_child_of_node(parent, child) {
+               compat = of_get_property(child, "compatible", NULL);
+               if (!compat)
+                       continue;
+
+               rstc = of_reset_control_array_get(child, false, false);
+               if (IS_ERR(rstc))
+                       continue;
+
+               len = strlen(compat);
+               if (!of_compat_cmp("isi,soft-resetn", compat, len)) {
+                       mxc_isi->soft_resetn = rstc;
+                       rstc_num++;
+               } else if (!of_compat_cmp("isi,clk-enable", compat, len)) {
+                       mxc_isi->clk_enable = rstc;
+                       rstc_num++;
+               } else {
+                       dev_warn(dev, "invalid isi reset node: %s\n", compat);
+               }
+       }
+
+       if (!rstc_num) {
+               dev_err(dev, "no invalid reset control exists\n");
+               return -EINVAL;
+       }
+
+       of_node_put(parent);
+       return 0;
+}
+
 static int mxc_isi_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -335,10 +368,12 @@ static int mxc_isi_probe(struct platform_device *pdev)
        mutex_init(&mxc_isi->m2m_lock);
        atomic_set(&mxc_isi->open_count, 0);
 
-       mxc_isi->gpr = syscon_regmap_lookup_by_phandle(dev->of_node, "isi-gpr");
-       if (IS_ERR(mxc_isi->gpr)) {
-               mxc_isi->gpr = NULL;
-               dev_warn(dev, "can't find isi-gpr property\n");
+       if (of_device_is_compatible(dev->of_node, "fsl,imx8mn-isi")) {
+               ret = mxc_isi_of_parse_resets(mxc_isi);
+               if (ret) {
+                       dev_warn(dev, "Can not parse reset control\n");
+                       return ret;
+               }
        }
 
        ret = mxc_isi_clk_get(mxc_isi);
@@ -365,8 +400,8 @@ static int mxc_isi_probe(struct platform_device *pdev)
                dev_err(dev, "ISI_%d enable clocks fail\n", mxc_isi->id);
                return ret;
        }
-       disp_mix_sft_rstn(mxc_isi->gpr, false);
-       disp_mix_clks_enable(mxc_isi->gpr, true);
+       disp_mix_sft_rstn(mxc_isi->soft_resetn, false);
+       disp_mix_clks_enable(mxc_isi->clk_enable, true);
 
        mxc_isi_clean_registers(mxc_isi);
 
@@ -440,7 +475,7 @@ static int mxc_isi_runtime_suspend(struct device *dev)
 {
        struct mxc_isi_dev *mxc_isi = dev_get_drvdata(dev);
 
-       disp_mix_clks_enable(mxc_isi->gpr, false);
+       disp_mix_clks_enable(mxc_isi->clk_enable, false);
        mxc_isi_clk_disable(mxc_isi);
 
        return 0;
@@ -456,8 +491,8 @@ static int mxc_isi_runtime_resume(struct device *dev)
                dev_err(dev, "%s clk enable fail\n", __func__);
                return ret;
        }
-       disp_mix_sft_rstn(mxc_isi->gpr, false);
-       disp_mix_clks_enable(mxc_isi->gpr, true);
+       disp_mix_sft_rstn(mxc_isi->soft_resetn, false);
+       disp_mix_clks_enable(mxc_isi->clk_enable, true);
 
        return 0;
 }
index de4c253..56f9e1a 100644 (file)
 #include <media/v4l2-ctrls.h>
 #include <media/videobuf2-core.h>
 #include <media/videobuf2-dma-contig.h>
+#include <linux/reset.h>
 
 #define MXC_ISI_DRIVER_NAME    "mxc-isi"
 #define MXC_ISI_MAX_DEVS       8
 
 #define ISI_OF_NODE_NAME       "isi"
 
-/* display_mix_sft_rstn_csr */
-#define EN_BUS_BLK_CLK_RSTN    BIT(8)
-#define EN_ISI_APB_CLK_RSTN    BIT(7)
-#define EN_ISI_PROC_CLK_RSTN   BIT(6)
-
-/* display_mix_clk_en_csr */
-#define EN_BUS_BLK_CLK         BIT(8)
-#define EN_ISI_APB_CLK         BIT(7)
-#define EN_ISI_PROC_CLK                BIT(6)
-
 #define MXC_ISI_SD_PAD_SINK_MIPI0_VC0          0
 #define MXC_ISI_SD_PAD_SINK_MIPI0_VC1          1
 #define MXC_ISI_SD_PAD_SINK_MIPI0_VC2          2
@@ -310,9 +301,11 @@ struct mxc_isi_dev {
        struct clk      *clk_root_disp_axi;
        struct clk      *clk_root_disp_apb;
 
-       struct regmap *gpr;
        const struct mxc_isi_dev_ops *ops;
 
+       struct reset_control *soft_resetn;
+       struct reset_control *clk_enable;
+
        u32 interface[MAX_PORTS];
        u32 flags;
        u32 skip_m2m;
index a738c6a..a05b1b9 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/videodev2.h>
 #include <media/v4l2-subdev.h>
 #include <media/v4l2-device.h>
+#include <linux/reset.h>
 
 #include "mxc-mipi-csi2-sam.h"
 
@@ -220,13 +221,12 @@ static int mipi_csis_phy_init(struct csi_state *state)
 
 static void mipi_csis_phy_reset_mx8mn(struct csi_state *state)
 {
-       struct regmap *gpr = state->gpr;
+       struct reset_control *reset = state->mipi_reset;
 
-       regmap_update_bits(gpr, GPR_MIPI_RESET, GPR_MIPI_S_RESETN, 0x0);
+       reset_control_assert(reset);
        usleep_range(10, 20);
 
-       regmap_update_bits(gpr, GPR_MIPI_RESET, GPR_MIPI_S_RESETN,
-                                               GPR_MIPI_S_RESETN);
+       reset_control_deassert(reset);
        usleep_range(10, 20);
 }
 
@@ -412,35 +412,22 @@ static int mipi_csis_clk_get(struct csi_state *state)
        return 0;
 }
 
-static void disp_mix_sft_rstn(struct regmap *gpr, bool enable)
+static int disp_mix_sft_rstn(struct reset_control *reset, bool enable)
 {
-       if (!enable)
-               /* release isi soft reset */
-               regmap_update_bits(gpr,
-                               DISP_MIX_SFT_RSTN_CSR,
-                               EN_CSI_ACLK_RSTN | EN_CSI_PCLK_RSTN,
-                               EN_CSI_ACLK_RSTN | EN_CSI_PCLK_RSTN);
-       else
-               regmap_update_bits(gpr,
-                               DISP_MIX_SFT_RSTN_CSR,
-                               EN_CSI_ACLK_RSTN | EN_CSI_PCLK_RSTN,
-                               0x0);
-       usleep_range(20, 30);
+       int ret;
+
+       ret = enable ? reset_control_assert(reset) :
+                        reset_control_deassert(reset);
+       return ret;
 }
 
-static void disp_mix_clks_enable(struct regmap *gpr, bool enable)
+static int disp_mix_clks_enable(struct reset_control *reset, bool enable)
 {
-       if (enable)
-               regmap_update_bits(gpr,
-                               DISP_MIX_CLK_EN_CSR,
-                               EN_CSI_ACLK | EN_CSI_PCLK,
-                               EN_CSI_ACLK | EN_CSI_PCLK);
-       else
-               regmap_update_bits(gpr,
-                               DISP_MIX_CLK_EN_CSR,
-                               EN_CSI_ACLK | EN_CSI_PCLK,
-                               0x0);
-       usleep_range(20, 30);
+       int ret;
+
+       ret = enable ? reset_control_assert(reset) :
+                        reset_control_deassert(reset);
+       return ret;
 }
 
 static void disp_mix_gasket_config(struct csi_state *state)
@@ -934,6 +921,56 @@ static int mipi_csis_subdev_init(struct v4l2_subdev *mipi_sd,
        return ret;
 }
 
+static int mipi_csis_of_parse_resets(struct csi_state *state)
+{
+       int ret;
+       struct device *dev = state->dev;
+       struct device_node *np = dev->of_node;
+       struct device_node *parent, *child;
+       struct of_phandle_args args;
+       struct reset_control *rstc;
+       const char *compat;
+       uint32_t len, rstc_num = 0;
+
+       ret = of_parse_phandle_with_args(np, "resets", "#reset-cells",
+                                        0, &args);
+       if (ret)
+               return ret;
+
+       parent = args.np;
+       for_each_child_of_node(parent, child) {
+               compat = of_get_property(child, "compatible", NULL);
+               if (!compat)
+                       continue;
+
+               rstc = of_reset_control_array_get(child, false, false);
+               if (IS_ERR(rstc))
+                       continue;
+
+               len = strlen(compat);
+               if (!of_compat_cmp("csi,soft-resetn", compat, len)) {
+                       state->soft_resetn = rstc;
+                       rstc_num++;
+               } else if (!of_compat_cmp("csi,clk-enable", compat, len)) {
+                       state->clk_enable = rstc;
+                       rstc_num++;
+               } else if (!of_compat_cmp("csi,mipi-reset", compat, len)) {
+                       state->mipi_reset = rstc;
+                       rstc_num++;
+               } else {
+                       dev_warn(dev, "invalid csis reset node: %s\n", compat);
+               }
+       }
+
+       if (!rstc_num) {
+               dev_err(dev, "no invalid reset control exists\n");
+               return -EINVAL;
+       }
+       of_node_put(parent);
+
+       return 0;
+}
+
 static int mipi_csis_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -982,6 +1019,12 @@ static int mipi_csis_probe(struct platform_device *pdev)
                return PTR_ERR(state->gpr);
        }
 
+       ret = mipi_csis_of_parse_resets(state);
+       if (ret < 0) {
+               dev_err(dev, "Can not parse reset control\n");
+               return ret;
+       }
+
        mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        state->regs = devm_ioremap_resource(dev, mem_res);
        if (IS_ERR(state->regs))
@@ -1001,8 +1044,8 @@ static int mipi_csis_probe(struct platform_device *pdev)
        if (ret < 0)
                return ret;
 
-       disp_mix_clks_enable(state->gpr, true);
-       disp_mix_sft_rstn(state->gpr, false);
+       disp_mix_clks_enable(state->clk_enable, true);
+       disp_mix_sft_rstn(state->soft_resetn, false);
        phy_reset_fn(state);
 
        mipi_csis_clk_disable(state);
@@ -1073,7 +1116,7 @@ static int mipi_csis_runtime_suspend(struct device *dev)
        if (ret < 0)
                return ret;
 
-       disp_mix_clks_enable(state->gpr, false);
+       disp_mix_clks_enable(state->clk_enable, false);
        mipi_csis_clk_disable(state);
        return 0;
 }
@@ -1091,8 +1134,8 @@ static int mipi_csis_runtime_resume(struct device *dev)
        if (ret < 0)
                return ret;
 
-       disp_mix_clks_enable(state->gpr, true);
-       disp_mix_sft_rstn(state->gpr, false);
+       disp_mix_clks_enable(state->clk_enable, true);
+       disp_mix_sft_rstn(state->soft_resetn, false);
 
        return 0;
 }
index 5859230..67fc25d 100644 (file)
 #define MIPI_CSIS_PKTDATA_EVEN         0x3000
 #define MIPI_CSIS_PKTDATA_SIZE         SZ_4K
 
-#define GPR_MIPI_RESET                 0x08
-#define GPR_MIPI_S_RESETN              BIT(16)
-
 #define DEFAULT_SCLK_CSIS_FREQ         166000000UL
 
-/* display_mix_sft_rstn_csr */
-#define DISP_MIX_SFT_RSTN_CSR          0x00
-#define EN_CSI_ACLK_RSTN               BIT(3)
-#define EN_CSI_PCLK_RSTN               BIT(2)
-
-/* display_mix_clk_en_csr */
-#define DISP_MIX_CLK_EN_CSR            0x04
-#define EN_CSI_ACLK                    BIT(3)
-#define EN_CSI_PCLK                    BIT(2)
-
 /* display_mix_clk_en_csr */
 #define DISP_MIX_GASKET_0_CTRL                 0x60
 #define GASKET_0_CTRL_DATA_TYPE(x)             (((x) & (0x3F)) << 8)
@@ -334,6 +321,9 @@ struct csi_state {
        struct regulator     *mipi_phy_regulator;
 
        struct regmap *gpr;
+       struct reset_control *soft_resetn;
+       struct reset_control *clk_enable;
+       struct reset_control *mipi_reset;
 };
 
 /**