From: xingyu.wu Date: Wed, 27 Apr 2022 07:49:49 +0000 (+0800) Subject: clk:starfive: Add isp clock tree driver X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5b76e45f595d3c226ab2f863edd6dfa2b3271f8b;p=platform%2Fkernel%2Flinux-starfive.git clk:starfive: Add isp clock tree driver 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 --- diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi b/arch/riscv/boot/dts/starfive/jh7110.dtsi index 8720646..b3caf65 100644 --- a/arch/riscv/boot/dts/starfive/jh7110.dtsi +++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi @@ -9,6 +9,7 @@ #include #include #include +#include / { compatible = "starfive,jh7110"; @@ -262,6 +263,15 @@ 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"; }; diff --git a/drivers/clk/starfive/Kconfig b/drivers/clk/starfive/Kconfig index 60aac0d..2310261 100755 --- a/drivers/clk/starfive/Kconfig +++ b/drivers/clk/starfive/Kconfig @@ -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. diff --git a/drivers/clk/starfive/Makefile b/drivers/clk/starfive/Makefile index bdaaea7..a6746e1 100755 --- a/drivers/clk/starfive/Makefile +++ b/drivers/clk/starfive/Makefile @@ -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 index 0000000..a8b4b5e --- /dev/null +++ b/drivers/clk/starfive/clk-starfive-jh7110-isp.c @@ -0,0 +1,284 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * StarFive JH7110 Isp Clock Driver + * + * Copyright (C) 2022 Xingyu Wu + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 "); +MODULE_DESCRIPTION("StarFive JH7110 isp clock driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/starfive/clk-starfive-jh7110.h b/drivers/clk/starfive/clk-starfive-jh7110.h index b27ba4c..41225a0 100755 --- a/drivers/clk/starfive/clk-starfive-jh7110.h +++ b/drivers/clk/starfive/clk-starfive-jh7110.h @@ -13,6 +13,7 @@ #include #include #include +#include /* 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 index 0000000..b4f2873 --- /dev/null +++ b/include/dt-bindings/clock/starfive-jh7110-isp.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0 OR MIT */ +/* + * Copyright 2022 StarFive, Inc + */ + +#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__ */