All of lore.kernel.org
 help / color / mirror / Atom feed
From: Michal Simek <michal.simek@xilinx.com>
To: Michael Tretter <m.tretter@pengutronix.de>,
	<linux-arm-kernel@lists.infradead.org>,
	<linux-clk@vger.kernel.org>, <devicetree@vger.kernel.org>
Cc: <rajanv@xilinx.com>, <tejasp@xilinx.com>, <dshah@xilinx.com>,
	<rvisaval@xilinx.com>, <kernel@pengutronix.de>,
	<robh+dt@kernel.org>, <mturquette@baylibre.com>,
	<sboyd@kernel.org>
Subject: Re: [PATCH 08/12] soc: xilinx: vcu: implement clock provider for output clocks
Date: Wed, 2 Dec 2020 15:49:54 +0100	[thread overview]
Message-ID: <71afe870-a10b-755d-37d3-1010abe17fe0@xilinx.com> (raw)
In-Reply-To: <20201116075532.4019252-9-m.tretter@pengutronix.de>



On 16. 11. 20 8:55, Michael Tretter wrote:
> The VCU System-Level Control uses an internal PLL to drive the core and
> MCU clock for the allegro encoder and decoder based on an external PL
> clock.
> 
> In order be able to ensure that the clocks are enabled and to get their
> rate from other drivers, the module must implement a clock provider and
> register the clocks at the common clock framework. Other drivers are
> then able to access the clock via devicetree bindings.
> 
> Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
> ---
>  drivers/soc/xilinx/xlnx_vcu.c | 191 +++++++++++++++++++++++++++-------
>  1 file changed, 154 insertions(+), 37 deletions(-)
> 
> diff --git a/drivers/soc/xilinx/xlnx_vcu.c b/drivers/soc/xilinx/xlnx_vcu.c
> index 725e646aa726..cedc8b7859f7 100644
> --- a/drivers/soc/xilinx/xlnx_vcu.c
> +++ b/drivers/soc/xilinx/xlnx_vcu.c
> @@ -18,6 +18,8 @@
>  #include <linux/platform_device.h>
>  #include <linux/regmap.h>
>  
> +#include <dt-bindings/clock/xlnx-vcu.h>
> +
>  /* vcu slcr registers, bitmask and shift */
>  #define VCU_PLL_CTRL			0x24
>  #define VCU_PLL_CTRL_RESET_MASK		0x01
> @@ -50,11 +52,6 @@
>  #define VCU_ENC_MCU_CTRL		0x34
>  #define VCU_DEC_CORE_CTRL		0x38
>  #define VCU_DEC_MCU_CTRL		0x3c
> -#define VCU_PLL_DIVISOR_MASK		0x3f
> -#define VCU_PLL_DIVISOR_SHIFT		4
> -#define VCU_SRCSEL_MASK			0x01
> -#define VCU_SRCSEL_SHIFT		0
> -#define VCU_SRCSEL_PLL			1
>  
>  #define VCU_PLL_STATUS			0x60
>  #define VCU_PLL_STATUS_LOCK_STATUS_MASK	0x01
> @@ -82,6 +79,7 @@ struct xvcu_device {
>  	struct regmap *logicore_reg_ba;
>  	void __iomem *vcu_slcr_ba;
>  	struct clk_hw *pll;
> +	struct clk_hw_onecell_data *clk_data;

The same here with clk_data - please update kernel-doc format.

>  };
>  
>  static struct regmap_config vcu_settings_regmap_config = {
> @@ -403,7 +401,7 @@ static int xvcu_set_vcu_pll_info(struct xvcu_device *xvcu)
>  	u32 refclk, coreclk, mcuclk, inte, deci;
>  	u32 divisor_mcu, divisor_core, fvco;
>  	u32 clkoutdiv, vcu_pll_ctrl, pll_clk;
> -	u32 mod, ctrl;
> +	u32 mod;
>  	int i;
>  	int ret;
>  	const struct xvcu_pll_cfg *found = NULL;
> @@ -478,37 +476,6 @@ static int xvcu_set_vcu_pll_info(struct xvcu_device *xvcu)
>  	dev_dbg(xvcu->dev, "Actual Core clock freq is %uHz\n", coreclk);
>  	dev_dbg(xvcu->dev, "Actual Mcu clock freq is %uHz\n", mcuclk);
>  
> -	/* Set divisor for the core and mcu clock */
> -	ctrl = xvcu_read(xvcu->vcu_slcr_ba, VCU_ENC_CORE_CTRL);
> -	ctrl &= ~(VCU_PLL_DIVISOR_MASK << VCU_PLL_DIVISOR_SHIFT);
> -	ctrl |= (divisor_core & VCU_PLL_DIVISOR_MASK) <<
> -		 VCU_PLL_DIVISOR_SHIFT;
> -	ctrl &= ~(VCU_SRCSEL_MASK << VCU_SRCSEL_SHIFT);
> -	ctrl |= (VCU_SRCSEL_PLL & VCU_SRCSEL_MASK) << VCU_SRCSEL_SHIFT;
> -	xvcu_write(xvcu->vcu_slcr_ba, VCU_ENC_CORE_CTRL, ctrl);
> -
> -	ctrl = xvcu_read(xvcu->vcu_slcr_ba, VCU_DEC_CORE_CTRL);
> -	ctrl &= ~(VCU_PLL_DIVISOR_MASK << VCU_PLL_DIVISOR_SHIFT);
> -	ctrl |= (divisor_core & VCU_PLL_DIVISOR_MASK) <<
> -		 VCU_PLL_DIVISOR_SHIFT;
> -	ctrl &= ~(VCU_SRCSEL_MASK << VCU_SRCSEL_SHIFT);
> -	ctrl |= (VCU_SRCSEL_PLL & VCU_SRCSEL_MASK) << VCU_SRCSEL_SHIFT;
> -	xvcu_write(xvcu->vcu_slcr_ba, VCU_DEC_CORE_CTRL, ctrl);
> -
> -	ctrl = xvcu_read(xvcu->vcu_slcr_ba, VCU_ENC_MCU_CTRL);
> -	ctrl &= ~(VCU_PLL_DIVISOR_MASK << VCU_PLL_DIVISOR_SHIFT);
> -	ctrl |= (divisor_mcu & VCU_PLL_DIVISOR_MASK) << VCU_PLL_DIVISOR_SHIFT;
> -	ctrl &= ~(VCU_SRCSEL_MASK << VCU_SRCSEL_SHIFT);
> -	ctrl |= (VCU_SRCSEL_PLL & VCU_SRCSEL_MASK) << VCU_SRCSEL_SHIFT;
> -	xvcu_write(xvcu->vcu_slcr_ba, VCU_ENC_MCU_CTRL, ctrl);
> -
> -	ctrl = xvcu_read(xvcu->vcu_slcr_ba, VCU_DEC_MCU_CTRL);
> -	ctrl &= ~(VCU_PLL_DIVISOR_MASK << VCU_PLL_DIVISOR_SHIFT);
> -	ctrl |= (divisor_mcu & VCU_PLL_DIVISOR_MASK) << VCU_PLL_DIVISOR_SHIFT;
> -	ctrl &= ~(VCU_SRCSEL_MASK << VCU_SRCSEL_SHIFT);
> -	ctrl |= (VCU_SRCSEL_PLL & VCU_SRCSEL_MASK) << VCU_SRCSEL_SHIFT;
> -	xvcu_write(xvcu->vcu_slcr_ba, VCU_DEC_MCU_CTRL, ctrl);
> -
>  	ret = xvcu_pll_set_rate(xvcu, fvco, refclk);
>  	if (ret)
>  		return ret;
> @@ -545,6 +512,146 @@ static int xvcu_set_pll(struct xvcu_device *xvcu)
>  	return xvcu_pll_enable(xvcu);
>  }
>  
> +static struct clk_hw *xvcu_clk_hw_register_leaf(struct device *dev,
> +						const char *name,
> +						const char * const *parent_names,
> +						u8 num_parents,
> +						struct clk_hw *parent_default,
> +						void __iomem *reg,
> +						spinlock_t *lock)
> +{
> +	unsigned long flags = CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT;
> +	u8 divider_flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO |
> +			   CLK_DIVIDER_ROUND_CLOSEST;
> +	struct clk_hw *mux = NULL;
> +	struct clk_hw *divider = NULL;
> +	struct clk_hw *gate = NULL;
> +	char *name_mux;
> +	char *name_div;
> +	int err;
> +
> +	name_mux = devm_kasprintf(dev, GFP_KERNEL, "%s%s", name, "_mux");
> +	if (!name_mux) {
> +		err = -ENOMEM;
> +		goto err;
> +	}
> +	mux = clk_hw_register_mux(dev, name_mux, parent_names, num_parents,
> +				  flags, reg, 0, 1, 0, lock);
> +	if (IS_ERR(mux)) {
> +		err = PTR_ERR(divider);

mux here?
And smatch is reporting also this issue. Please take a look.

drivers/soc/xilinx/xlnx_vcu.c:541 xvcu_clk_hw_register_leaf() warn:
passing zero to 'PTR_ERR'
drivers/soc/xilinx/xlnx_vcu.c:577 xvcu_clk_hw_register_leaf() warn:
passing zero to 'ERR_PTR'



> +		goto err;
> +	}
> +	clk_hw_set_parent(mux, parent_default);
> +
> +	name_div = devm_kasprintf(dev, GFP_KERNEL, "%s%s", name, "_div");
> +	if (!name_div) {
> +		err = -ENOMEM;
> +		goto err;
> +	}
> +	divider = clk_hw_register_divider_parent_hw(dev, name_div, mux, flags,
> +						    reg, 4, 6, divider_flags,
> +						    lock);
> +	if (IS_ERR(divider)) {
> +		err = PTR_ERR(divider);
> +		goto err;
> +	}
> +
> +	gate = clk_hw_register_gate_parent_hw(dev, name, divider,
> +					      CLK_SET_RATE_PARENT, reg, 12, 0,
> +					      lock);
> +	if (IS_ERR(gate)) {
> +		err = PTR_ERR(gate);
> +		goto err;
> +	}
> +
> +	return gate;
> +
> +err:
> +	if (!IS_ERR_OR_NULL(gate))
> +		clk_hw_unregister_gate(gate);
> +	if (!IS_ERR_OR_NULL(divider))
> +		clk_hw_unregister_divider(divider);
> +	if (!IS_ERR_OR_NULL(mux))
> +		clk_hw_unregister_divider(mux);
> +
> +	return ERR_PTR(err);
> +}
> +
> +static void xvcu_clk_hw_unregister_leaf(struct clk_hw *hw)
> +{
> +	struct clk_hw *gate = hw;
> +	struct clk_hw *divider;
> +	struct clk_hw *mux;
> +
> +	if (!gate)
> +		return;
> +
> +	divider = clk_hw_get_parent(gate);
> +	clk_hw_unregister_gate(gate);
> +	if (!divider)
> +		return;
> +
> +	mux = clk_hw_get_parent(divider);
> +	clk_hw_unregister_mux(mux);
> +	if (!divider)
> +		return;
> +
> +	clk_hw_unregister_divider(divider);
> +}
> +
> +static DEFINE_SPINLOCK(venc_core_lock);
> +static DEFINE_SPINLOCK(venc_mcu_lock);
> +
> +static int xvcu_register_clock_provider(struct xvcu_device *xvcu)
> +{
> +	struct device *dev = xvcu->dev;
> +	const char *parent_names[2];
> +	struct clk_hw *parent_default;
> +	struct clk_hw_onecell_data *data;
> +	struct clk_hw **hws;
> +	void __iomem *reg_base = xvcu->vcu_slcr_ba;
> +
> +	data = devm_kzalloc(dev, struct_size(data, hws, CLK_XVCU_NUM_CLOCKS), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +	data->num = CLK_XVCU_NUM_CLOCKS;
> +	hws = data->hws;
> +
> +	xvcu->clk_data = data;
> +
> +	parent_default = xvcu->pll;
> +	parent_names[0] = "dummy";
> +	parent_names[1] = clk_hw_get_name(parent_default);
> +
> +	hws[CLK_XVCU_ENC_CORE] =
> +		xvcu_clk_hw_register_leaf(dev, "venc_core_clk",
> +					  parent_names,
> +					  ARRAY_SIZE(parent_names),
> +					  parent_default,
> +					  reg_base + VCU_ENC_CORE_CTRL,
> +					  &venc_core_lock);
> +	hws[CLK_XVCU_ENC_MCU] =
> +		xvcu_clk_hw_register_leaf(dev, "venc_mcu_clk",
> +					  parent_names,
> +					  ARRAY_SIZE(parent_names),
> +					  parent_default,
> +					  reg_base + VCU_ENC_MCU_CTRL,
> +					  &venc_mcu_lock);
> +
> +	return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, data);
> +}
> +
> +static void xvcu_unregister_clock_provider(struct xvcu_device *xvcu)
> +{
> +	struct clk_hw_onecell_data *data = xvcu->clk_data;
> +	struct clk_hw **hws = data->hws;
> +
> +	if (!IS_ERR_OR_NULL(hws[CLK_XVCU_ENC_MCU]))
> +		xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_ENC_MCU]);
> +	if (!IS_ERR_OR_NULL(hws[CLK_XVCU_ENC_CORE]))
> +		xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_ENC_CORE]);
> +}
> +
>  /**
>   * xvcu_probe - Probe existence of the logicoreIP
>   *			and initialize PLL
> @@ -639,10 +746,18 @@ static int xvcu_probe(struct platform_device *pdev)
>  		goto error_pll_ref;
>  	}
>  
> +	ret = xvcu_register_clock_provider(xvcu);
> +	if (ret) {
> +		dev_err(&pdev->dev, "failed to register clock provider\n");
> +		goto error_clk_provider;
> +	}
> +
>  	dev_set_drvdata(&pdev->dev, xvcu);
>  
>  	return 0;
>  
> +error_clk_provider:
> +	xvcu_unregister_clock_provider(xvcu);
>  error_pll_ref:
>  	clk_disable_unprepare(xvcu->aclk);
>  	return ret;
> @@ -664,6 +779,8 @@ static int xvcu_remove(struct platform_device *pdev)
>  	if (!xvcu)
>  		return -ENODEV;
>  
> +	xvcu_unregister_clock_provider(xvcu);
> +
>  	/* Add the the Gasket isolation and put the VCU in reset. */
>  	regmap_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, 0);
>  
> 

M

WARNING: multiple messages have this Message-ID (diff)
From: Michal Simek <michal.simek@xilinx.com>
To: Michael Tretter <m.tretter@pengutronix.de>,
	<linux-arm-kernel@lists.infradead.org>,
	<linux-clk@vger.kernel.org>, <devicetree@vger.kernel.org>
Cc: dshah@xilinx.com, tejasp@xilinx.com, sboyd@kernel.org,
	mturquette@baylibre.com, rajanv@xilinx.com, robh+dt@kernel.org,
	kernel@pengutronix.de, rvisaval@xilinx.com
Subject: Re: [PATCH 08/12] soc: xilinx: vcu: implement clock provider for output clocks
Date: Wed, 2 Dec 2020 15:49:54 +0100	[thread overview]
Message-ID: <71afe870-a10b-755d-37d3-1010abe17fe0@xilinx.com> (raw)
In-Reply-To: <20201116075532.4019252-9-m.tretter@pengutronix.de>



On 16. 11. 20 8:55, Michael Tretter wrote:
> The VCU System-Level Control uses an internal PLL to drive the core and
> MCU clock for the allegro encoder and decoder based on an external PL
> clock.
> 
> In order be able to ensure that the clocks are enabled and to get their
> rate from other drivers, the module must implement a clock provider and
> register the clocks at the common clock framework. Other drivers are
> then able to access the clock via devicetree bindings.
> 
> Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
> ---
>  drivers/soc/xilinx/xlnx_vcu.c | 191 +++++++++++++++++++++++++++-------
>  1 file changed, 154 insertions(+), 37 deletions(-)
> 
> diff --git a/drivers/soc/xilinx/xlnx_vcu.c b/drivers/soc/xilinx/xlnx_vcu.c
> index 725e646aa726..cedc8b7859f7 100644
> --- a/drivers/soc/xilinx/xlnx_vcu.c
> +++ b/drivers/soc/xilinx/xlnx_vcu.c
> @@ -18,6 +18,8 @@
>  #include <linux/platform_device.h>
>  #include <linux/regmap.h>
>  
> +#include <dt-bindings/clock/xlnx-vcu.h>
> +
>  /* vcu slcr registers, bitmask and shift */
>  #define VCU_PLL_CTRL			0x24
>  #define VCU_PLL_CTRL_RESET_MASK		0x01
> @@ -50,11 +52,6 @@
>  #define VCU_ENC_MCU_CTRL		0x34
>  #define VCU_DEC_CORE_CTRL		0x38
>  #define VCU_DEC_MCU_CTRL		0x3c
> -#define VCU_PLL_DIVISOR_MASK		0x3f
> -#define VCU_PLL_DIVISOR_SHIFT		4
> -#define VCU_SRCSEL_MASK			0x01
> -#define VCU_SRCSEL_SHIFT		0
> -#define VCU_SRCSEL_PLL			1
>  
>  #define VCU_PLL_STATUS			0x60
>  #define VCU_PLL_STATUS_LOCK_STATUS_MASK	0x01
> @@ -82,6 +79,7 @@ struct xvcu_device {
>  	struct regmap *logicore_reg_ba;
>  	void __iomem *vcu_slcr_ba;
>  	struct clk_hw *pll;
> +	struct clk_hw_onecell_data *clk_data;

The same here with clk_data - please update kernel-doc format.

>  };
>  
>  static struct regmap_config vcu_settings_regmap_config = {
> @@ -403,7 +401,7 @@ static int xvcu_set_vcu_pll_info(struct xvcu_device *xvcu)
>  	u32 refclk, coreclk, mcuclk, inte, deci;
>  	u32 divisor_mcu, divisor_core, fvco;
>  	u32 clkoutdiv, vcu_pll_ctrl, pll_clk;
> -	u32 mod, ctrl;
> +	u32 mod;
>  	int i;
>  	int ret;
>  	const struct xvcu_pll_cfg *found = NULL;
> @@ -478,37 +476,6 @@ static int xvcu_set_vcu_pll_info(struct xvcu_device *xvcu)
>  	dev_dbg(xvcu->dev, "Actual Core clock freq is %uHz\n", coreclk);
>  	dev_dbg(xvcu->dev, "Actual Mcu clock freq is %uHz\n", mcuclk);
>  
> -	/* Set divisor for the core and mcu clock */
> -	ctrl = xvcu_read(xvcu->vcu_slcr_ba, VCU_ENC_CORE_CTRL);
> -	ctrl &= ~(VCU_PLL_DIVISOR_MASK << VCU_PLL_DIVISOR_SHIFT);
> -	ctrl |= (divisor_core & VCU_PLL_DIVISOR_MASK) <<
> -		 VCU_PLL_DIVISOR_SHIFT;
> -	ctrl &= ~(VCU_SRCSEL_MASK << VCU_SRCSEL_SHIFT);
> -	ctrl |= (VCU_SRCSEL_PLL & VCU_SRCSEL_MASK) << VCU_SRCSEL_SHIFT;
> -	xvcu_write(xvcu->vcu_slcr_ba, VCU_ENC_CORE_CTRL, ctrl);
> -
> -	ctrl = xvcu_read(xvcu->vcu_slcr_ba, VCU_DEC_CORE_CTRL);
> -	ctrl &= ~(VCU_PLL_DIVISOR_MASK << VCU_PLL_DIVISOR_SHIFT);
> -	ctrl |= (divisor_core & VCU_PLL_DIVISOR_MASK) <<
> -		 VCU_PLL_DIVISOR_SHIFT;
> -	ctrl &= ~(VCU_SRCSEL_MASK << VCU_SRCSEL_SHIFT);
> -	ctrl |= (VCU_SRCSEL_PLL & VCU_SRCSEL_MASK) << VCU_SRCSEL_SHIFT;
> -	xvcu_write(xvcu->vcu_slcr_ba, VCU_DEC_CORE_CTRL, ctrl);
> -
> -	ctrl = xvcu_read(xvcu->vcu_slcr_ba, VCU_ENC_MCU_CTRL);
> -	ctrl &= ~(VCU_PLL_DIVISOR_MASK << VCU_PLL_DIVISOR_SHIFT);
> -	ctrl |= (divisor_mcu & VCU_PLL_DIVISOR_MASK) << VCU_PLL_DIVISOR_SHIFT;
> -	ctrl &= ~(VCU_SRCSEL_MASK << VCU_SRCSEL_SHIFT);
> -	ctrl |= (VCU_SRCSEL_PLL & VCU_SRCSEL_MASK) << VCU_SRCSEL_SHIFT;
> -	xvcu_write(xvcu->vcu_slcr_ba, VCU_ENC_MCU_CTRL, ctrl);
> -
> -	ctrl = xvcu_read(xvcu->vcu_slcr_ba, VCU_DEC_MCU_CTRL);
> -	ctrl &= ~(VCU_PLL_DIVISOR_MASK << VCU_PLL_DIVISOR_SHIFT);
> -	ctrl |= (divisor_mcu & VCU_PLL_DIVISOR_MASK) << VCU_PLL_DIVISOR_SHIFT;
> -	ctrl &= ~(VCU_SRCSEL_MASK << VCU_SRCSEL_SHIFT);
> -	ctrl |= (VCU_SRCSEL_PLL & VCU_SRCSEL_MASK) << VCU_SRCSEL_SHIFT;
> -	xvcu_write(xvcu->vcu_slcr_ba, VCU_DEC_MCU_CTRL, ctrl);
> -
>  	ret = xvcu_pll_set_rate(xvcu, fvco, refclk);
>  	if (ret)
>  		return ret;
> @@ -545,6 +512,146 @@ static int xvcu_set_pll(struct xvcu_device *xvcu)
>  	return xvcu_pll_enable(xvcu);
>  }
>  
> +static struct clk_hw *xvcu_clk_hw_register_leaf(struct device *dev,
> +						const char *name,
> +						const char * const *parent_names,
> +						u8 num_parents,
> +						struct clk_hw *parent_default,
> +						void __iomem *reg,
> +						spinlock_t *lock)
> +{
> +	unsigned long flags = CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT;
> +	u8 divider_flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO |
> +			   CLK_DIVIDER_ROUND_CLOSEST;
> +	struct clk_hw *mux = NULL;
> +	struct clk_hw *divider = NULL;
> +	struct clk_hw *gate = NULL;
> +	char *name_mux;
> +	char *name_div;
> +	int err;
> +
> +	name_mux = devm_kasprintf(dev, GFP_KERNEL, "%s%s", name, "_mux");
> +	if (!name_mux) {
> +		err = -ENOMEM;
> +		goto err;
> +	}
> +	mux = clk_hw_register_mux(dev, name_mux, parent_names, num_parents,
> +				  flags, reg, 0, 1, 0, lock);
> +	if (IS_ERR(mux)) {
> +		err = PTR_ERR(divider);

mux here?
And smatch is reporting also this issue. Please take a look.

drivers/soc/xilinx/xlnx_vcu.c:541 xvcu_clk_hw_register_leaf() warn:
passing zero to 'PTR_ERR'
drivers/soc/xilinx/xlnx_vcu.c:577 xvcu_clk_hw_register_leaf() warn:
passing zero to 'ERR_PTR'



> +		goto err;
> +	}
> +	clk_hw_set_parent(mux, parent_default);
> +
> +	name_div = devm_kasprintf(dev, GFP_KERNEL, "%s%s", name, "_div");
> +	if (!name_div) {
> +		err = -ENOMEM;
> +		goto err;
> +	}
> +	divider = clk_hw_register_divider_parent_hw(dev, name_div, mux, flags,
> +						    reg, 4, 6, divider_flags,
> +						    lock);
> +	if (IS_ERR(divider)) {
> +		err = PTR_ERR(divider);
> +		goto err;
> +	}
> +
> +	gate = clk_hw_register_gate_parent_hw(dev, name, divider,
> +					      CLK_SET_RATE_PARENT, reg, 12, 0,
> +					      lock);
> +	if (IS_ERR(gate)) {
> +		err = PTR_ERR(gate);
> +		goto err;
> +	}
> +
> +	return gate;
> +
> +err:
> +	if (!IS_ERR_OR_NULL(gate))
> +		clk_hw_unregister_gate(gate);
> +	if (!IS_ERR_OR_NULL(divider))
> +		clk_hw_unregister_divider(divider);
> +	if (!IS_ERR_OR_NULL(mux))
> +		clk_hw_unregister_divider(mux);
> +
> +	return ERR_PTR(err);
> +}
> +
> +static void xvcu_clk_hw_unregister_leaf(struct clk_hw *hw)
> +{
> +	struct clk_hw *gate = hw;
> +	struct clk_hw *divider;
> +	struct clk_hw *mux;
> +
> +	if (!gate)
> +		return;
> +
> +	divider = clk_hw_get_parent(gate);
> +	clk_hw_unregister_gate(gate);
> +	if (!divider)
> +		return;
> +
> +	mux = clk_hw_get_parent(divider);
> +	clk_hw_unregister_mux(mux);
> +	if (!divider)
> +		return;
> +
> +	clk_hw_unregister_divider(divider);
> +}
> +
> +static DEFINE_SPINLOCK(venc_core_lock);
> +static DEFINE_SPINLOCK(venc_mcu_lock);
> +
> +static int xvcu_register_clock_provider(struct xvcu_device *xvcu)
> +{
> +	struct device *dev = xvcu->dev;
> +	const char *parent_names[2];
> +	struct clk_hw *parent_default;
> +	struct clk_hw_onecell_data *data;
> +	struct clk_hw **hws;
> +	void __iomem *reg_base = xvcu->vcu_slcr_ba;
> +
> +	data = devm_kzalloc(dev, struct_size(data, hws, CLK_XVCU_NUM_CLOCKS), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +	data->num = CLK_XVCU_NUM_CLOCKS;
> +	hws = data->hws;
> +
> +	xvcu->clk_data = data;
> +
> +	parent_default = xvcu->pll;
> +	parent_names[0] = "dummy";
> +	parent_names[1] = clk_hw_get_name(parent_default);
> +
> +	hws[CLK_XVCU_ENC_CORE] =
> +		xvcu_clk_hw_register_leaf(dev, "venc_core_clk",
> +					  parent_names,
> +					  ARRAY_SIZE(parent_names),
> +					  parent_default,
> +					  reg_base + VCU_ENC_CORE_CTRL,
> +					  &venc_core_lock);
> +	hws[CLK_XVCU_ENC_MCU] =
> +		xvcu_clk_hw_register_leaf(dev, "venc_mcu_clk",
> +					  parent_names,
> +					  ARRAY_SIZE(parent_names),
> +					  parent_default,
> +					  reg_base + VCU_ENC_MCU_CTRL,
> +					  &venc_mcu_lock);
> +
> +	return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, data);
> +}
> +
> +static void xvcu_unregister_clock_provider(struct xvcu_device *xvcu)
> +{
> +	struct clk_hw_onecell_data *data = xvcu->clk_data;
> +	struct clk_hw **hws = data->hws;
> +
> +	if (!IS_ERR_OR_NULL(hws[CLK_XVCU_ENC_MCU]))
> +		xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_ENC_MCU]);
> +	if (!IS_ERR_OR_NULL(hws[CLK_XVCU_ENC_CORE]))
> +		xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_ENC_CORE]);
> +}
> +
>  /**
>   * xvcu_probe - Probe existence of the logicoreIP
>   *			and initialize PLL
> @@ -639,10 +746,18 @@ static int xvcu_probe(struct platform_device *pdev)
>  		goto error_pll_ref;
>  	}
>  
> +	ret = xvcu_register_clock_provider(xvcu);
> +	if (ret) {
> +		dev_err(&pdev->dev, "failed to register clock provider\n");
> +		goto error_clk_provider;
> +	}
> +
>  	dev_set_drvdata(&pdev->dev, xvcu);
>  
>  	return 0;
>  
> +error_clk_provider:
> +	xvcu_unregister_clock_provider(xvcu);
>  error_pll_ref:
>  	clk_disable_unprepare(xvcu->aclk);
>  	return ret;
> @@ -664,6 +779,8 @@ static int xvcu_remove(struct platform_device *pdev)
>  	if (!xvcu)
>  		return -ENODEV;
>  
> +	xvcu_unregister_clock_provider(xvcu);
> +
>  	/* Add the the Gasket isolation and put the VCU in reset. */
>  	regmap_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, 0);
>  
> 

M

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  reply	other threads:[~2020-12-02 14:50 UTC|newest]

Thread overview: 68+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-11-16  7:55 [PATCH 00/12] soc: xilinx: vcu: Convert driver to clock provider Michael Tretter
2020-11-16  7:55 ` Michael Tretter
2020-11-16  7:55 ` [PATCH 01/12] ARM: dts: define indexes for output clocks Michael Tretter
2020-11-16  7:55   ` Michael Tretter
2020-12-02 14:33   ` Michal Simek
2020-12-02 14:33     ` Michal Simek
2020-12-07 19:21   ` Rob Herring
2020-12-07 19:21     ` Rob Herring
2020-12-13  5:44   ` Stephen Boyd
2020-12-13  5:44     ` Stephen Boyd
2020-11-16  7:55 ` [PATCH 02/12] clk: divider: fix initialization with parent_hw Michael Tretter
2020-11-16  7:55   ` Michael Tretter
2020-12-02 14:28   ` Michal Simek
2020-12-02 14:28     ` Michal Simek
2020-12-13  5:42   ` Stephen Boyd
2020-12-13  5:42     ` Stephen Boyd
2020-11-16  7:55 ` [PATCH 03/12] soc: xilinx: vcu: drop coreclk from struct xlnx_vcu Michael Tretter
2020-11-16  7:55   ` Michael Tretter
2020-11-16  7:55 ` [PATCH 04/12] soc: xilinx: vcu: add helper to wait for PLL locked Michael Tretter
2020-11-16  7:55   ` Michael Tretter
2020-11-16  7:55 ` [PATCH 05/12] soc: xilinx: vcu: add helpers for configuring PLL Michael Tretter
2020-11-16  7:55   ` Michael Tretter
2020-11-16  7:55 ` [PATCH 06/12] soc: xilinx: vcu: implement PLL disable Michael Tretter
2020-11-16  7:55   ` Michael Tretter
2020-11-16  7:55 ` [PATCH 07/12] soc: xilinx: vcu: register PLL as fixed rate clock Michael Tretter
2020-11-16  7:55   ` Michael Tretter
2020-12-02 14:41   ` Michal Simek
2020-12-02 14:41     ` Michal Simek
2020-11-16  7:55 ` [PATCH 08/12] soc: xilinx: vcu: implement clock provider for output clocks Michael Tretter
2020-11-16  7:55   ` Michael Tretter
2020-12-02 14:49   ` Michal Simek [this message]
2020-12-02 14:49     ` Michal Simek
2020-12-13  5:55   ` Stephen Boyd
2020-12-13  5:55     ` Stephen Boyd
2020-12-15 11:38     ` Michael Tretter
2020-12-15 11:38       ` Michael Tretter
2020-12-16  1:09       ` Stephen Boyd
2020-12-16  1:09         ` Stephen Boyd
2020-12-21  9:18         ` Michael Tretter
2020-12-21  9:18           ` Michael Tretter
2020-11-16  7:55 ` [PATCH 09/12] soc: xilinx: vcu: make pll post divider explicit Michael Tretter
2020-11-16  7:55   ` Michael Tretter
2020-12-02 14:51   ` Michal Simek
2020-12-02 14:51     ` Michal Simek
2020-11-16  7:55 ` [PATCH 10/12] soc: xilinx: vcu: make the PLL configurable Michael Tretter
2020-11-16  7:55   ` Michael Tretter
2020-12-02 14:54   ` Michal Simek
2020-12-02 14:54     ` Michal Simek
2020-11-16  7:55 ` [PATCH 11/12] soc: xilinx: vcu: remove calculation of PLL configuration Michael Tretter
2020-11-16  7:55   ` Michael Tretter
2020-11-16  7:55 ` [PATCH 12/12] soc: xilinx: vcu: use bitfields for register definition Michael Tretter
2020-11-16  7:55   ` Michael Tretter
2020-12-13  5:47   ` Stephen Boyd
2020-12-13  5:47     ` Stephen Boyd
2020-12-03  7:46 ` [PATCH 00/12] soc: xilinx: vcu: Convert driver to clock provider Michal Simek
2020-12-03  7:46   ` Michal Simek
2020-12-03  9:00   ` Michael Tretter
2020-12-03  9:00     ` Michael Tretter
2020-12-03  9:14     ` Michal Simek
2020-12-03  9:14       ` Michal Simek
2020-12-13  5:50 ` Stephen Boyd
2020-12-13  5:50   ` Stephen Boyd
2020-12-15 11:56   ` Michael Tretter
2020-12-15 11:56     ` Michael Tretter
2020-12-16  2:37     ` Stephen Boyd
2020-12-16  2:37       ` Stephen Boyd
2020-12-21  9:19       ` Michael Tretter
2020-12-21  9:19         ` Michael Tretter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=71afe870-a10b-755d-37d3-1010abe17fe0@xilinx.com \
    --to=michal.simek@xilinx.com \
    --cc=devicetree@vger.kernel.org \
    --cc=dshah@xilinx.com \
    --cc=kernel@pengutronix.de \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-clk@vger.kernel.org \
    --cc=m.tretter@pengutronix.de \
    --cc=mturquette@baylibre.com \
    --cc=rajanv@xilinx.com \
    --cc=robh+dt@kernel.org \
    --cc=rvisaval@xilinx.com \
    --cc=sboyd@kernel.org \
    --cc=tejasp@xilinx.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.