clk:starfive: Add isp clock tree driver
authorxingyu.wu <xingyu.wu@starfivetech.com>
Wed, 27 Apr 2022 07:49:49 +0000 (15:49 +0800)
committerxingyu.wu <xingyu.wu@starfivetech.com>
Thu, 28 Apr 2022 09:44:16 +0000 (17:44 +0800)
Clock references refer to include/dt-bindings/clock/starfive-jh7110-isp.h

Enable the isp clock tree driver in dts file if use it.
If the fpga is not connetted with isp board, the isp clock tree must be disabled.

Signed-off-by: Xingyu Wu <xingyu.wu@starfivetech.com>
arch/riscv/boot/dts/starfive/jh7110.dtsi
drivers/clk/starfive/Kconfig
drivers/clk/starfive/Makefile
drivers/clk/starfive/clk-starfive-jh7110-isp.c [new file with mode: 0755]
drivers/clk/starfive/clk-starfive-jh7110.h
include/dt-bindings/clock/starfive-jh7110-isp.h [new file with mode: 0755]

index 8720646..b3caf65 100644 (file)
@@ -9,6 +9,7 @@
 #include <dt-bindings/reset/starfive-jh7110.h>
 #include <dt-bindings/clock/starfive-jh7110-clkgen.h>
 #include <dt-bindings/clock/starfive-jh7110-vout.h>
+#include <dt-bindings/clock/starfive-jh7110-isp.h>
 
 / {
        compatible = "starfive,jh7110";
                        reg = <0x0 0x19810000 0x0 0x10000>;
                        reg-names = "isp";
                        #clock-cells = <1>;
+                       clocks = <&clkgen JH7110_ISP_TOP_CLK_DVP>,
+                                <&clkgen JH7110_ISP_TOP_CLK_ISPCORE_2X>,
+                                <&clkgen JH7110_ISP_TOP_CLK_ISP_AXI>;
+                       clock-names = "u0_dom_isp_top_clk_dom_isp_top_clk_dvp",
+                                     "u0_dom_isp_top_clk_dom_isp_top_clk_ispcore_2x",
+                                     "u0_dom_isp_top_clk_dom_isp_top_clk_isp_axi";
+                       resets = <&rstgen RSTN_U0_DOM_ISP_TOP_N>,
+                                <&rstgen RSTN_U0_DOM_ISP_TOP_AXI>;
+                       reset-names = "rst_isp_top_n", "rst_isp_top_axi";
                        status = "disabled";
                };
 
index 60aac0d..2310261 100755 (executable)
@@ -15,3 +15,11 @@ config CLK_STARFIVE_JH7110_VOUT
        help
                Say yes here to support the vout clocks on the StarFive
                JH7100 SoC.
+
+config CLK_STARFIVE_JH7110_ISP
+       bool "StarFive JH7110 isp clock support"
+       depends on CLK_STARFIVE_JH7110
+       default y if SOC_STARFIVE_JH7110
+       help
+               Say yes here to support the isp clocks on the StarFive
+               JH7110 SoC.
index bdaaea7..a6746e1 100755 (executable)
@@ -5,3 +5,4 @@ obj-$(CONFIG_CLK_STARFIVE_JH7110)       += clk-starfive-jh7110-gen.o \
                                                clk-starfive-jh7110-stg.o \
                                                clk-starfive-jh7110-aon.o
 obj-$(CONFIG_CLK_STARFIVE_JH7110_VOUT) += clk-starfive-jh7110-vout.o
+obj-$(CONFIG_CLK_STARFIVE_JH7110_ISP)  += clk-starfive-jh7110-isp.o
\ No newline at end of file
diff --git a/drivers/clk/starfive/clk-starfive-jh7110-isp.c b/drivers/clk/starfive/clk-starfive-jh7110-isp.c
new file mode 100755 (executable)
index 0000000..a8b4b5e
--- /dev/null
@@ -0,0 +1,284 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * StarFive JH7110 Isp Clock Driver
+ *
+ * Copyright (C) 2022 Xingyu Wu <xingyu.wu@starfivetech.com>
+ */
+
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/reset.h>
+#include <linux/reset-controller.h>
+#include <dt-bindings/clock/starfive-jh7110-isp.h>
+#include <soc/starfive/jh7110_pmu.h>
+
+#include "clk-starfive-jh7110.h"
+
+static const struct jh7110_clk_data jh7110_clk_isp_data[] __initconst = {
+       //syscon
+       JH7110__DIV(JH7110_DOM4_APB_FUNC, "dom4_apb_func",
+                       15, JH7110_ISP_TOP_CLK_ISP_AXI_CLKGEN),
+       //crg
+       JH7110__DIV(JH7110_MIPI_RX0_PXL, "mipi_rx0_pxl",
+                       8, JH7110_ISP_TOP_CLK_ISPCORE_2X_CLKGEN),
+       JH7110__INV(JH7110_DVP_INV, "dvp_inv", JH7110_ISP_TOP_CLK_DVP_CLKGEN),
+       //vin
+       JH7110__DIV(JH7110_U0_M31DPHY_CFGCLK_IN, "u0_m31dphy_cfgclk_in",
+                       16, JH7110_ISP_TOP_CLK_ISPCORE_2X_CLKGEN),
+       JH7110__DIV(JH7110_U0_M31DPHY_REFCLK_IN, "u0_m31dphy_refclk_in",
+                       16, JH7110_ISP_TOP_CLK_ISPCORE_2X_CLKGEN),
+       JH7110__DIV(JH7110_U0_M31DPHY_TXCLKESC_LAN0, "u0_m31dphy_txclkesc_lan0",
+                       60, JH7110_ISP_TOP_CLK_ISPCORE_2X_CLKGEN),
+       JH7110_GATE(JH7110_U0_VIN_PCLK, "u0_vin_pclk", 0, JH7110_DOM4_APB),
+       JH7110__DIV(JH7110_U0_VIN_SYS_CLK, "u0_vin_sys_clk",
+                       8, JH7110_ISP_TOP_CLK_ISPCORE_2X_CLKGEN),
+       JH7110_GATE(JH7110_U0_VIN_PIXEL_CLK_IF0, "u0_vin_pixel_clk_if0",
+                       0, JH7110_MIPI_RX0_PXL),
+       JH7110_GATE(JH7110_U0_VIN_PIXEL_CLK_IF1, "u0_vin_pixel_clk_if1",
+                       0, JH7110_MIPI_RX0_PXL),
+       JH7110_GATE(JH7110_U0_VIN_PIXEL_CLK_IF2, "u0_vin_pixel_clk_if2",
+                       0, JH7110_MIPI_RX0_PXL),
+       JH7110_GATE(JH7110_U0_VIN_PIXEL_CLK_IF3, "u0_vin_pixel_clk_if3",
+                       0, JH7110_MIPI_RX0_PXL),
+       JH7110__MUX(JH7110_U0_VIN_CLK_P_AXIWR, "u0_vin_clk_p_axiwr", 2,
+                       JH7110_MIPI_RX0_PXL,
+                       JH7110_DVP_INV),
+       //ispv2_top_wrapper
+       JH7110_GMUX(JH7110_U0_ISPV2_TOP_WRAPPER_CLK_C,
+                       "u0_ispv2_top_wrapper_clk_c", 0, 2,
+                       JH7110_MIPI_RX0_PXL,
+                       JH7110_DVP_INV),
+};
+
+static struct clk_hw *jh7110_isp_clk_get(struct of_phandle_args *clkspec,
+                                       void *data)
+{
+       struct jh7110_clk_priv *priv = data;
+       unsigned int idx = clkspec->args[0];
+
+       if (idx < JH7110_CLK_ISP_REG_END)
+               return &priv->reg[idx].hw;
+
+       if (idx < JH7110_CLK_ISP_END)
+               return priv->pll[PLL_OFI(idx)];
+
+       return ERR_PTR(-EINVAL);
+}
+
+static int __init clk_starfive_jh7110_isp_probe(struct platform_device *pdev)
+{
+       struct jh7110_clk_priv *priv;
+       unsigned int idx;
+       struct clk *clk_isp_2x;
+       struct clk *clk_isp_axi;
+       struct reset_control *rst_isp_n;
+       struct reset_control *rst_isp_axi;
+       int ret = 0;
+
+       priv = devm_kzalloc(&pdev->dev, struct_size(priv, reg,
+                               JH7110_CLK_ISP_END), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       spin_lock_init(&priv->rmw_lock);
+       priv->dev = &pdev->dev;
+       priv->isp_base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(priv->isp_base))
+               return PTR_ERR(priv->isp_base);
+
+       starfive_power_domain_set(POWER_DOMAIN_ISP, 1);
+
+       clk_isp_2x = devm_clk_get(priv->dev,
+                       "u0_dom_isp_top_clk_dom_isp_top_clk_ispcore_2x");
+       if (!IS_ERR(clk_isp_2x)){
+               ret = clk_prepare_enable(clk_isp_2x);
+               if(ret){
+                       dev_err(priv->dev, "clk_isp_2x enable failed\n");
+                       return ret;
+               }
+       }else{
+               dev_err(priv->dev, "clk_isp_2x get failed\n");
+               return PTR_ERR(clk_isp_2x);
+       }
+
+       clk_isp_axi = devm_clk_get(priv->dev,
+                       "u0_dom_isp_top_clk_dom_isp_top_clk_isp_axi");
+       if (!IS_ERR(clk_isp_axi)){
+               ret = clk_prepare_enable(clk_isp_axi);
+               if(ret){
+                       dev_err(priv->dev, "clk_isp_axi enable failed\n");
+                       return ret;
+               }
+       }else{
+               dev_err(priv->dev, "clk_isp_axi get failed\n");
+               return PTR_ERR(clk_isp_axi);
+       }
+
+       rst_isp_n = devm_reset_control_get_exclusive(
+                       priv->dev, "rst_isp_top_n");
+       if (!IS_ERR(rst_isp_n)) {
+               ret = reset_control_deassert(rst_isp_n);
+               if(ret){
+                       dev_err(priv->dev, "rst_isp_n deassert failed.\n");
+                       return ret;
+               }
+       }else{
+               dev_err(priv->dev, "rst_isp_n get failed.\n");
+               return PTR_ERR(rst_isp_n);
+       }
+
+       rst_isp_axi = devm_reset_control_get_exclusive(
+                       priv->dev, "rst_isp_top_axi");
+       if (!IS_ERR(rst_isp_axi)) {
+               ret = reset_control_deassert(rst_isp_axi);
+               if(ret){
+                       dev_err(priv->dev, "rst_isp_axi deassert failed.\n");
+                       return ret;
+               }
+       }else{
+               dev_err(priv->dev, "rst_isp_axi get failed.\n");
+               return PTR_ERR(rst_isp_axi);
+       }
+
+       priv->pll[PLL_OFI(JH7110_U3_PCLK_MUX_FUNC_PCLK)] =
+                       devm_clk_hw_register_fixed_factor(
+                       priv->dev, "u3_pclk_mux_func_pclk",
+                       "dom4_apb_func", 0, 1, 1);
+       priv->pll[PLL_OFI(JH7110_U3_PCLK_MUX_BIST_PCLK)] =
+                       devm_clk_hw_register_fixed_factor(
+                       priv->dev, "u3_pclk_mux_bist_pclk",
+                       "u0_dom_isp_top_clk_dom_isp_top_clk_bist_apb", 0, 1, 1);
+       priv->pll[PLL_OFI(JH7110_DOM4_APB)] =
+                       devm_clk_hw_register_fixed_factor(priv->dev, "dom4_apb",
+                       "u3_pclk_mux_pclk", 0, 1, 1);
+       //vin
+       priv->pll[PLL_OFI(JH7110_U0_VIN_PCLK_FREE)] =
+                       devm_clk_hw_register_fixed_factor(
+                       priv->dev, "u0_vin_pclk_free",
+                       "dom4_apb", 0, 1, 1);
+       priv->pll[PLL_OFI(JH7110_U0_VIN_CLK_P_AXIRD)] =
+                       devm_clk_hw_register_fixed_factor(
+                       priv->dev, "u0_vin_clk_p_axird",
+                       "mipi_rx0_pxl", 0, 1, 1);
+       priv->pll[PLL_OFI(JH7110_U0_VIN_ACLK)] =
+                       devm_clk_hw_register_fixed_factor(
+                       priv->dev, "u0_vin_ACLK",
+                       "u0_dom_isp_top_clk_dom_isp_top_clk_isp_axi", 0, 1, 1);
+       priv->pll[PLL_OFI(JH7110_U0_ISPV2_TOP_WRAPPER_CLK_ISP_AXI_IN)] =
+                       devm_clk_hw_register_fixed_factor(priv->dev,
+                       "u0_ispv2_top_wrapper_clk_isp_axi_in",
+                       "u0_dom_isp_top_clk_dom_isp_top_clk_isp_axi", 0, 1, 1);
+       priv->pll[PLL_OFI(JH7110_U0_ISPV2_TOP_WRAPPER_CLK_ISP_X2)] =
+                       devm_clk_hw_register_fixed_factor(priv->dev,
+                       "u0_ispv2_top_wrapper_clk_isp_x2",
+                       "u0_dom_isp_top_clk_dom_isp_top_clk_ispcore_2x",
+                       0, 1, 1);
+       //wrapper
+       priv->pll[PLL_OFI(JH7110_U0_ISPV2_TOP_WRAPPER_CLK_ISP)] =
+                       devm_clk_hw_register_fixed_factor(priv->dev,
+                       "u0_ispv2_top_wrapper_clk_isp",
+                       "u0_dom_isp_top_clk_dom_isp_top_clk_isp_axi", 0, 1, 1);
+       priv->pll[PLL_OFI(JH7110_U0_ISPV2_TOP_WRAPPER_CLK_P)] =
+                       devm_clk_hw_register_fixed_factor(priv->dev,
+                       "u0_ispv2_top_wrapper_clk_p",
+                       "mipi_rx0_pxl", 0, 1, 1);
+       priv->pll[PLL_OFI(JH7110_U0_CRG_PCLK)] =
+                       devm_clk_hw_register_fixed_factor(priv->dev,
+                       "u0_crg_pclk", "dom4_apb", 0, 1, 1);
+       priv->pll[PLL_OFI(JH7110_U0_SYSCON_PCLK)] =
+                       devm_clk_hw_register_fixed_factor(priv->dev,
+                       "u0_syscon_pclk", "dom4_apb", 0, 1, 1);
+       priv->pll[PLL_OFI(JH7110_U0_M31DPHY_APBCFG_PCLK)] =
+                       devm_clk_hw_register_fixed_factor(priv->dev,
+                       "u0_m31dphy_apbcfg_pclk", "dom4_apb", 0, 1, 1);
+       priv->pll[PLL_OFI(JH7110_U0_AXI2APB_BRIDGE_CLK_DOM4_APB)] =
+                       devm_clk_hw_register_fixed_factor(priv->dev,
+                       "u0_axi2apb_bridge_clk_dom4_apb", "dom4_apb", 0, 1, 1);
+       priv->pll[PLL_OFI(JH7110_U0_AXI2APB_BRIDGE_ISP_AXI4SLV_CLK)] =
+                       devm_clk_hw_register_fixed_factor(priv->dev,
+                       "u0_axi2apb_bridge_isp_axi4slv_clk",
+                       "u0_dom_isp_top_clk_dom_isp_top_clk_isp_axi", 0, 1, 1);
+       priv->pll[PLL_OFI(JH7110_U3_PCLK_MUX_PCLK)] =
+                       devm_clk_hw_register_fixed_factor(priv->dev,
+                       "u3_pclk_mux_pclk", "u3_pclk_mux_func_pclk", 0, 1, 1);
+
+       for (idx = 0; idx < JH7110_CLK_ISP_REG_END; idx++) {
+               u32 max = jh7110_clk_isp_data[idx].max;
+               struct clk_parent_data parents[2] = {};
+               struct clk_init_data init = {
+                       .name = jh7110_clk_isp_data[idx].name,
+                       .ops = starfive_jh7110_clk_ops(max),
+                       .parent_data = parents,
+                       .num_parents = ((max & JH7110_CLK_MUX_MASK) \
+                                       >> JH7110_CLK_MUX_SHIFT) + 1,
+                       .flags = jh7110_clk_isp_data[idx].flags,
+               };
+               struct jh7110_clk *clk = &priv->reg[idx];
+               unsigned int i;
+
+               for (i = 0; i < init.num_parents; i++) {
+                       unsigned int pidx = jh7110_clk_isp_data[idx].parents[i];
+
+                       if (pidx < JH7110_CLK_ISP_REG_END)
+                               parents[i].hw = &priv->reg[pidx].hw;
+                       else if (pidx < JH7110_CLK_ISP_END)
+                               parents[i].hw = priv->pll[PLL_OFI(pidx)];
+                       else if (pidx == JH7110_ISP_TOP_CLK_ISPCORE_2X_CLKGEN)
+                               parents[i].fw_name = \
+                               "u0_dom_isp_top_clk_dom_isp_top_clk_ispcore_2x";
+                       else if (pidx == JH7110_ISP_TOP_CLK_ISP_AXI_CLKGEN)
+                               parents[i].fw_name = \
+                               "u0_dom_isp_top_clk_dom_isp_top_clk_isp_axi";
+                       else if (pidx == JH7110_ISP_TOP_CLK_BIST_APB_CLKGEN)
+                               parents[i].fw_name = \
+                               "u0_dom_isp_top_clk_dom_isp_top_clk_bist_apb";
+                       else if (pidx == JH7110_ISP_TOP_CLK_DVP_CLKGEN)
+                               parents[i].fw_name = \
+                               "u0_dom_isp_top_clk_dom_isp_top_clk_dvp";
+               }
+
+               clk->hw.init = &init;
+               clk->idx = idx;
+               clk->max_div = max & JH7110_CLK_DIV_MASK;
+               clk->reg_flags = JH7110_CLK_ISP_FLAG;
+
+               ret = devm_clk_hw_register(priv->dev, &clk->hw);
+               if (ret)
+                       return ret;
+       }
+
+       ret = devm_of_clk_add_hw_provider(priv->dev, jh7110_isp_clk_get, priv);
+       if (ret)
+               return ret;
+
+       dev_info(&pdev->dev,"starfive JH7110 clk_isp init successfully.");
+       return 0;
+}
+
+static const struct of_device_id clk_starfive_jh7110_isp_match[] = {
+               {.compatible = "starfive,jh7110-clk-isp" },
+               { /* sentinel */ }
+};
+
+static struct platform_driver clk_starfive_jh7110_isp_driver = {
+       .probe = clk_starfive_jh7110_isp_probe,
+               .driver = {
+               .name = "clk-starfive-jh7110-isp",
+               .of_match_table = clk_starfive_jh7110_isp_match,
+       },
+};
+module_platform_driver(clk_starfive_jh7110_isp_driver);
+
+MODULE_AUTHOR("Xingyu Wu <xingyu.wu@starfivetech.com>");
+MODULE_DESCRIPTION("StarFive JH7110 isp clock driver");
+MODULE_LICENSE("GPL");
index b27ba4c..41225a0 100755 (executable)
@@ -13,6 +13,7 @@
 #include <linux/debugfs.h>
 #include <dt-bindings/clock/starfive-jh7110-clkgen.h>
 #include <dt-bindings/clock/starfive-jh7110-vout.h>
+#include <dt-bindings/clock/starfive-jh7110-isp.h>
 
 /* register flags */
 #define JH7110_CLK_SYS_FLAG    1
@@ -32,6 +33,8 @@
 #define PLL_OF(x)      (x - JH7110_CLK_REG_END)
 /* vout PLL CLOCK offset */
 #define PLL_OFV(x)     (x - JH7110_CLK_VOUT_REG_END)
+/* isp PLL CLOCK offset */
+#define PLL_OFI(x)     (x - JH7110_CLK_ISP_REG_END)
 
 /* clock data */
 struct jh7110_clk_data {
diff --git a/include/dt-bindings/clock/starfive-jh7110-isp.h b/include/dt-bindings/clock/starfive-jh7110-isp.h
new file mode 100755 (executable)
index 0000000..b4f2873
--- /dev/null
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/*
+ * Copyright 2022 StarFive, Inc <xingyu.wu@starfivetech.com>
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_STARFIVE_JH7110_ISP_H__
+#define __DT_BINDINGS_CLOCK_STARFIVE_JH7110_ISP_H__
+
+/* regisger */
+#define JH7110_DOM4_APB_FUNC                                   0
+#define JH7110_MIPI_RX0_PXL                                    1
+#define JH7110_DVP_INV                                         2
+#define JH7110_U0_M31DPHY_CFGCLK_IN                            3
+#define JH7110_U0_M31DPHY_REFCLK_IN                            4
+#define JH7110_U0_M31DPHY_TXCLKESC_LAN0                                5
+#define JH7110_U0_VIN_PCLK                                     6
+#define JH7110_U0_VIN_SYS_CLK                                  7
+#define JH7110_U0_VIN_PIXEL_CLK_IF0                            8
+#define JH7110_U0_VIN_PIXEL_CLK_IF1                            9
+#define JH7110_U0_VIN_PIXEL_CLK_IF2                            10
+#define JH7110_U0_VIN_PIXEL_CLK_IF3                            11
+#define JH7110_U0_VIN_CLK_P_AXIWR                              12
+#define JH7110_U0_ISPV2_TOP_WRAPPER_CLK_C                      13
+
+#define JH7110_CLK_ISP_REG_END                                 14
+
+/* other */
+#define JH7110_U3_PCLK_MUX_FUNC_PCLK                           14
+#define JH7110_U3_PCLK_MUX_BIST_PCLK                           15
+#define JH7110_DOM4_APB                                                16
+#define JH7110_U0_VIN_PCLK_FREE                                        17
+#define JH7110_U0_VIN_CLK_P_AXIRD                              18
+#define JH7110_U0_VIN_ACLK                                     19
+#define JH7110_U0_ISPV2_TOP_WRAPPER_CLK_ISP_AXI_IN             20
+#define JH7110_U0_ISPV2_TOP_WRAPPER_CLK_ISP_X2                 21
+#define JH7110_U0_ISPV2_TOP_WRAPPER_CLK_ISP                    22
+#define JH7110_U0_ISPV2_TOP_WRAPPER_CLK_P                      23
+#define JH7110_U0_CRG_PCLK                                     24
+#define JH7110_U0_SYSCON_PCLK                                  25
+#define JH7110_U0_M31DPHY_APBCFG_PCLK                          26
+#define JH7110_U0_AXI2APB_BRIDGE_CLK_DOM4_APB                  27
+#define JH7110_U0_AXI2APB_BRIDGE_ISP_AXI4SLV_CLK               28
+#define JH7110_U3_PCLK_MUX_PCLK                                        29
+
+#define JH7110_CLK_ISP_END                                     30
+
+/* external clocks */
+#define JH7110_ISP_TOP_CLK_ISPCORE_2X_CLKGEN   (JH7110_CLK_ISP_END + 0)
+#define JH7110_ISP_TOP_CLK_ISP_AXI_CLKGEN      (JH7110_CLK_ISP_END + 1)
+#define JH7110_ISP_TOP_CLK_BIST_APB_CLKGEN     (JH7110_CLK_ISP_END + 2)
+#define JH7110_ISP_TOP_CLK_DVP_CLKGEN          (JH7110_CLK_ISP_END + 3)
+
+#endif /* __DT_BINDINGS_CLOCK_STARFIVE_JH7110_H__ */