All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jerome Brunet <jbrunet@baylibre.com>
To: Neil Armstrong <neil.armstrong@linaro.org>,
	Michael Turquette <mturquette@baylibre.com>,
	Stephen Boyd <sboyd@kernel.org>,
	Kevin Hilman <khilman@baylibre.com>,
	Martin Blumenstingl <martin.blumenstingl@googlemail.com>,
	Rob Herring <robh+dt@kernel.org>,
	Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
	Conor Dooley <conor+dt@kernel.org>,
	David Airlie <airlied@gmail.com>, Daniel Vetter <daniel@ffwll.ch>,
	Philipp Zabel <p.zabel@pengutronix.de>,
	Kishon Vijay Abraham I <kishon@kernel.org>,
	Sam Ravnborg <sam@ravnborg.org>
Cc: "Lukas F. Hartmann" <lukas@mntre.com>,
	Nicolas Belin <nbelin@baylibre.com>,
	linux-amlogic@lists.infradead.org, linux-clk@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
	dri-devel@lists.freedesktop.org, linux-phy@lists.infradead.org
Subject: Re: [PATCH v5 05/17] clk: meson: g12a: make VCLK2 and ENCL clock path configurable by CCF
Date: Tue, 30 May 2023 10:14:51 +0200	[thread overview]
Message-ID: <1jv8ga445j.fsf@starbuckisacylon.baylibre.com> (raw)
In-Reply-To: <20230512-amlogic-v6-4-upstream-dsi-ccf-vim3-v5-5-56eb7a4d5b8e@linaro.org>


On Tue 30 May 2023 at 09:38, Neil Armstrong <neil.armstrong@linaro.org> wrote:

> In order to setup the DSI clock, let's make the unused VCLK2 clock path
> configuration via CCF.
>
> The nocache option is removed from following clocks:
> - vclk2_sel
> - vclk2_input
> - vclk2_div
> - vclk2
> - vclk_div1
> - vclk2_div2_en
> - vclk2_div4_en
> - vclk2_div6_en
> - vclk2_div12_en
> - vclk2_div2
> - vclk2_div4
> - vclk2_div6
> - vclk2_div12
> - cts_encl_sel
>
> The missing vclk2 reset sequence is handled via new clkc notifiers
> in order to reset the vclk2 after each rate change as done by Amlogic
> in the vendor implementation.
>
> In order to set a rate on cts_encl via the vclk2 clock path,
> the NO_REPARENT flag is set on cts_encl_sel & vclk2_sel in order
> to keep CCF from selection a parent.
> The parents of cts_encl_sel & vclk2_sel are expected to be defined
> in DT.
>
> The following clock scheme is to be used for DSI:
>
> xtal
> \_ gp0_pll_dco
>    \_ gp0_pll
>       |- vclk2_sel
>       |  \_ vclk2_input
>       |     \_ vclk2_div
>       |        \_ vclk2
>       |           \_ vclk2_div1
>       |              \_ cts_encl_sel
>       |                 \_ cts_encl	-> to VPU LCD Encoder
>       |- mipi_dsi_pxclk_sel
>       \_ mipi_dsi_pxclk_div
>          \_ mipi_dsi_pxclk		-> to DSI controller
>
> The mipi_dsi_pxclk_div is set as RO in order to use the same GP0
> for mipi_dsi_pxclk and vclk2_input.

I don't think notifiers is the appropriate approach here.
Whenever there is clock change the motifiers would trigger an off/on of
the clock, regardless of the clock usage or state.
If you have several consummers on this vclk2, this would
cause glitches and maybe this is not desirable.

I think it would be better to handle the enable and reset with a
specific gate driver, in prepare() or enable(), and the give the clock
CLK_SET_RATE_GATE flag.

This would require the clock to be properly turn off before changing the
rate.

>
> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
>  drivers/clk/meson/g12a.c | 131 +++++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 120 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c
> index 461ebd79497c..e4053f4957d5 100644
> --- a/drivers/clk/meson/g12a.c
> +++ b/drivers/clk/meson/g12a.c
> @@ -3163,7 +3163,7 @@ static struct clk_regmap g12a_vclk2_sel = {
>  		.ops = &clk_regmap_mux_ops,
>  		.parent_hws = g12a_vclk_parent_hws,
>  		.num_parents = ARRAY_SIZE(g12a_vclk_parent_hws),
> -		.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
> +		.flags = CLK_SET_RATE_NO_REPARENT,
>  	},
>  };
>  
> @@ -3191,7 +3191,6 @@ static struct clk_regmap g12a_vclk2_input = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2_sel.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
>  	},
>  };
>  
> @@ -3212,6 +3211,40 @@ static struct clk_regmap g12a_vclk_div = {
>  	},
>  };
>  
> +struct g12a_vclk_div_notifier {
> +	struct clk_regmap *clk;
> +	unsigned int offset;
> +	u8 en_bit_idx;
> +	u8 reset_bit_idx;
> +	struct notifier_block nb;
> +};
> +
> +static int g12a_vclk_div_notifier_cb(struct notifier_block *nb,
> +				  unsigned long event, void *data)
> +{
> +	struct g12a_vclk_div_notifier *nb_data =
> +		container_of(nb, struct g12a_vclk_div_notifier, nb);
> +
> +	switch (event) {
> +	case PRE_RATE_CHANGE:
> +		/* disable and reset vclk2 divider */
> +		regmap_update_bits(nb_data->clk->map, nb_data->offset,
> +				   BIT(nb_data->en_bit_idx) |
> +				   BIT(nb_data->reset_bit_idx),
> +				   BIT(nb_data->reset_bit_idx));
> +		return NOTIFY_OK;
> +	case POST_RATE_CHANGE:
> +		/* enabled and release reset */
> +		regmap_update_bits(nb_data->clk->map, nb_data->offset,
> +				   BIT(nb_data->en_bit_idx) |
> +				   BIT(nb_data->reset_bit_idx),
> +				   BIT(nb_data->en_bit_idx));
> +		return NOTIFY_OK;
> +	default:
> +		return NOTIFY_DONE;
> +	};
> +};
> +
>  static struct clk_regmap g12a_vclk2_div = {
>  	.data = &(struct clk_regmap_div_data){
>  		.offset = HHI_VIID_CLK_DIV,
> @@ -3225,10 +3258,18 @@ static struct clk_regmap g12a_vclk2_div = {
>  			&g12a_vclk2_input.hw
>  		},
>  		.num_parents = 1,
> -		.flags = CLK_GET_RATE_NOCACHE,
> +		.flags = CLK_DIVIDER_ROUND_CLOSEST,
>  	},
>  };
>  
> +static struct g12a_vclk_div_notifier g12a_vclk2_div_data = {
> +	.clk = &g12a_vclk2_div,
> +	.offset = HHI_VIID_CLK_DIV,
> +	.en_bit_idx = 16,
> +	.reset_bit_idx = 17,
> +	.nb.notifier_call = g12a_vclk_div_notifier_cb,
> +};
> +
>  static struct clk_regmap g12a_vclk = {
>  	.data = &(struct clk_regmap_gate_data){
>  		.offset = HHI_VID_CLK_CNTL,
> @@ -3243,6 +3284,33 @@ static struct clk_regmap g12a_vclk = {
>  	},
>  };
>  
> +struct g12a_vclk_reset_notifier {
> +	struct clk_regmap *clk;
> +	unsigned int offset;
> +	u8 bit_idx;
> +	struct notifier_block nb;
> +};
> +
> +static int g12a_vclk_notifier_cb(struct notifier_block *nb,
> +				  unsigned long event, void *data)
> +{
> +	struct g12a_vclk_reset_notifier *nb_data =
> +		container_of(nb, struct g12a_vclk_reset_notifier, nb);
> +
> +	switch (event) {
> +	case POST_RATE_CHANGE:
> +		/* reset vclk2 */
> +		regmap_update_bits(nb_data->clk->map, nb_data->offset,
> +				   BIT(nb_data->bit_idx), BIT(nb_data->bit_idx));
> +		regmap_update_bits(nb_data->clk->map, nb_data->offset,
> +				   BIT(nb_data->bit_idx), 0);
> +
> +		return NOTIFY_OK;
> +	default:
> +		return NOTIFY_DONE;
> +	};
> +}
> +
>  static struct clk_regmap g12a_vclk2 = {
>  	.data = &(struct clk_regmap_gate_data){
>  		.offset = HHI_VIID_CLK_CNTL,
> @@ -3253,10 +3321,17 @@ static struct clk_regmap g12a_vclk2 = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2_div.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> +static struct g12a_vclk_reset_notifier g12a_vclk2_data = {
> +	.clk = &g12a_vclk2,
> +	.offset = HHI_VIID_CLK_CNTL,
> +	.bit_idx = 15,
> +	.nb.notifier_call = g12a_vclk_notifier_cb,
> +};
> +
>  static struct clk_regmap g12a_vclk_div1 = {
>  	.data = &(struct clk_regmap_gate_data){
>  		.offset = HHI_VID_CLK_CNTL,
> @@ -3337,7 +3412,7 @@ static struct clk_regmap g12a_vclk2_div1 = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3351,7 +3426,7 @@ static struct clk_regmap g12a_vclk2_div2_en = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3365,7 +3440,7 @@ static struct clk_regmap g12a_vclk2_div4_en = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3379,7 +3454,7 @@ static struct clk_regmap g12a_vclk2_div6_en = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3393,7 +3468,7 @@ static struct clk_regmap g12a_vclk2_div12_en = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3459,6 +3534,7 @@ static struct clk_fixed_factor g12a_vclk2_div2 = {
>  			&g12a_vclk2_div2_en.hw
>  		},
>  		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3472,6 +3548,7 @@ static struct clk_fixed_factor g12a_vclk2_div4 = {
>  			&g12a_vclk2_div4_en.hw
>  		},
>  		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3485,6 +3562,7 @@ static struct clk_fixed_factor g12a_vclk2_div6 = {
>  			&g12a_vclk2_div6_en.hw
>  		},
>  		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3498,6 +3576,7 @@ static struct clk_fixed_factor g12a_vclk2_div12 = {
>  			&g12a_vclk2_div12_en.hw
>  		},
>  		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3559,7 +3638,7 @@ static struct clk_regmap g12a_cts_encl_sel = {
>  		.ops = &clk_regmap_mux_ops,
>  		.parent_hws = g12a_cts_parent_hws,
>  		.num_parents = ARRAY_SIZE(g12a_cts_parent_hws),
> -		.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
> +		.flags = CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3727,7 +3806,7 @@ static struct clk_regmap g12a_mipi_dsi_pxclk_div = {
>  	},
>  	.hw.init = &(struct clk_init_data){
>  		.name = "mipi_dsi_pxclk_div",
> -		.ops = &clk_regmap_divider_ops,
> +		.ops = &clk_regmap_divider_ro_ops,
>  		.parent_hws = (const struct clk_hw *[]) {
>  			&g12a_mipi_dsi_pxclk_sel.hw
>  		},
> @@ -5421,6 +5500,32 @@ static int meson_g12a_dvfs_setup(struct platform_device *pdev)
>  	return 0;
>  }
>  
> +static int meson_g12a_vclk_setup(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct clk *notifier_clk;
> +	int ret;
> +
> +	/* Setup clock notifier for vclk2 */
> +	notifier_clk = devm_clk_hw_get_clk(dev, &g12a_vclk2.hw, DVFS_CON_ID);
> +	ret = devm_clk_notifier_register(dev, notifier_clk, &g12a_vclk2_data.nb);
> +	if (ret) {
> +		dev_err(dev, "failed to register the vlkc2 notifier\n");
> +		return ret;
> +	}
> +
> +	/* Setup clock notifier for vclk2_div */
> +	notifier_clk = devm_clk_hw_get_clk(dev, &g12a_vclk2_div.hw, DVFS_CON_ID);
> +	ret = devm_clk_notifier_register(dev, notifier_clk,
> +					 &g12a_vclk2_div_data.nb);
> +	if (ret) {
> +		dev_err(dev, "failed to register the vclk2_div notifier\n");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
>  struct meson_g12a_data {
>  	const struct meson_eeclkc_data eeclkc_data;
>  	int (*dvfs_setup)(struct platform_device *pdev);
> @@ -5443,6 +5548,10 @@ static int meson_g12a_probe(struct platform_device *pdev)
>  	g12a_data = container_of(eeclkc_data, struct meson_g12a_data,
>  				 eeclkc_data);
>  
> +	ret = meson_g12a_vclk_setup(pdev);
> +	if (ret)
> +		return ret;
> +
>  	if (g12a_data->dvfs_setup)
>  		return g12a_data->dvfs_setup(pdev);


WARNING: multiple messages have this Message-ID (diff)
From: Jerome Brunet <jbrunet@baylibre.com>
To: Neil Armstrong <neil.armstrong@linaro.org>,
	Michael Turquette <mturquette@baylibre.com>,
	Stephen Boyd <sboyd@kernel.org>,
	Kevin Hilman <khilman@baylibre.com>,
	Martin Blumenstingl <martin.blumenstingl@googlemail.com>,
	Rob Herring <robh+dt@kernel.org>,
	Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
	Conor Dooley <conor+dt@kernel.org>,
	David Airlie <airlied@gmail.com>, Daniel Vetter <daniel@ffwll.ch>,
	Philipp Zabel <p.zabel@pengutronix.de>,
	Kishon Vijay Abraham I <kishon@kernel.org>,
	Sam Ravnborg <sam@ravnborg.org>
Cc: "Lukas F. Hartmann" <lukas@mntre.com>,
	Nicolas Belin <nbelin@baylibre.com>,
	linux-amlogic@lists.infradead.org, linux-clk@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
	dri-devel@lists.freedesktop.org, linux-phy@lists.infradead.org
Subject: Re: [PATCH v5 05/17] clk: meson: g12a: make VCLK2 and ENCL clock path configurable by CCF
Date: Tue, 30 May 2023 10:14:51 +0200	[thread overview]
Message-ID: <1jv8ga445j.fsf@starbuckisacylon.baylibre.com> (raw)
In-Reply-To: <20230512-amlogic-v6-4-upstream-dsi-ccf-vim3-v5-5-56eb7a4d5b8e@linaro.org>


On Tue 30 May 2023 at 09:38, Neil Armstrong <neil.armstrong@linaro.org> wrote:

> In order to setup the DSI clock, let's make the unused VCLK2 clock path
> configuration via CCF.
>
> The nocache option is removed from following clocks:
> - vclk2_sel
> - vclk2_input
> - vclk2_div
> - vclk2
> - vclk_div1
> - vclk2_div2_en
> - vclk2_div4_en
> - vclk2_div6_en
> - vclk2_div12_en
> - vclk2_div2
> - vclk2_div4
> - vclk2_div6
> - vclk2_div12
> - cts_encl_sel
>
> The missing vclk2 reset sequence is handled via new clkc notifiers
> in order to reset the vclk2 after each rate change as done by Amlogic
> in the vendor implementation.
>
> In order to set a rate on cts_encl via the vclk2 clock path,
> the NO_REPARENT flag is set on cts_encl_sel & vclk2_sel in order
> to keep CCF from selection a parent.
> The parents of cts_encl_sel & vclk2_sel are expected to be defined
> in DT.
>
> The following clock scheme is to be used for DSI:
>
> xtal
> \_ gp0_pll_dco
>    \_ gp0_pll
>       |- vclk2_sel
>       |  \_ vclk2_input
>       |     \_ vclk2_div
>       |        \_ vclk2
>       |           \_ vclk2_div1
>       |              \_ cts_encl_sel
>       |                 \_ cts_encl	-> to VPU LCD Encoder
>       |- mipi_dsi_pxclk_sel
>       \_ mipi_dsi_pxclk_div
>          \_ mipi_dsi_pxclk		-> to DSI controller
>
> The mipi_dsi_pxclk_div is set as RO in order to use the same GP0
> for mipi_dsi_pxclk and vclk2_input.

I don't think notifiers is the appropriate approach here.
Whenever there is clock change the motifiers would trigger an off/on of
the clock, regardless of the clock usage or state.
If you have several consummers on this vclk2, this would
cause glitches and maybe this is not desirable.

I think it would be better to handle the enable and reset with a
specific gate driver, in prepare() or enable(), and the give the clock
CLK_SET_RATE_GATE flag.

This would require the clock to be properly turn off before changing the
rate.

>
> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
>  drivers/clk/meson/g12a.c | 131 +++++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 120 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c
> index 461ebd79497c..e4053f4957d5 100644
> --- a/drivers/clk/meson/g12a.c
> +++ b/drivers/clk/meson/g12a.c
> @@ -3163,7 +3163,7 @@ static struct clk_regmap g12a_vclk2_sel = {
>  		.ops = &clk_regmap_mux_ops,
>  		.parent_hws = g12a_vclk_parent_hws,
>  		.num_parents = ARRAY_SIZE(g12a_vclk_parent_hws),
> -		.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
> +		.flags = CLK_SET_RATE_NO_REPARENT,
>  	},
>  };
>  
> @@ -3191,7 +3191,6 @@ static struct clk_regmap g12a_vclk2_input = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2_sel.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
>  	},
>  };
>  
> @@ -3212,6 +3211,40 @@ static struct clk_regmap g12a_vclk_div = {
>  	},
>  };
>  
> +struct g12a_vclk_div_notifier {
> +	struct clk_regmap *clk;
> +	unsigned int offset;
> +	u8 en_bit_idx;
> +	u8 reset_bit_idx;
> +	struct notifier_block nb;
> +};
> +
> +static int g12a_vclk_div_notifier_cb(struct notifier_block *nb,
> +				  unsigned long event, void *data)
> +{
> +	struct g12a_vclk_div_notifier *nb_data =
> +		container_of(nb, struct g12a_vclk_div_notifier, nb);
> +
> +	switch (event) {
> +	case PRE_RATE_CHANGE:
> +		/* disable and reset vclk2 divider */
> +		regmap_update_bits(nb_data->clk->map, nb_data->offset,
> +				   BIT(nb_data->en_bit_idx) |
> +				   BIT(nb_data->reset_bit_idx),
> +				   BIT(nb_data->reset_bit_idx));
> +		return NOTIFY_OK;
> +	case POST_RATE_CHANGE:
> +		/* enabled and release reset */
> +		regmap_update_bits(nb_data->clk->map, nb_data->offset,
> +				   BIT(nb_data->en_bit_idx) |
> +				   BIT(nb_data->reset_bit_idx),
> +				   BIT(nb_data->en_bit_idx));
> +		return NOTIFY_OK;
> +	default:
> +		return NOTIFY_DONE;
> +	};
> +};
> +
>  static struct clk_regmap g12a_vclk2_div = {
>  	.data = &(struct clk_regmap_div_data){
>  		.offset = HHI_VIID_CLK_DIV,
> @@ -3225,10 +3258,18 @@ static struct clk_regmap g12a_vclk2_div = {
>  			&g12a_vclk2_input.hw
>  		},
>  		.num_parents = 1,
> -		.flags = CLK_GET_RATE_NOCACHE,
> +		.flags = CLK_DIVIDER_ROUND_CLOSEST,
>  	},
>  };
>  
> +static struct g12a_vclk_div_notifier g12a_vclk2_div_data = {
> +	.clk = &g12a_vclk2_div,
> +	.offset = HHI_VIID_CLK_DIV,
> +	.en_bit_idx = 16,
> +	.reset_bit_idx = 17,
> +	.nb.notifier_call = g12a_vclk_div_notifier_cb,
> +};
> +
>  static struct clk_regmap g12a_vclk = {
>  	.data = &(struct clk_regmap_gate_data){
>  		.offset = HHI_VID_CLK_CNTL,
> @@ -3243,6 +3284,33 @@ static struct clk_regmap g12a_vclk = {
>  	},
>  };
>  
> +struct g12a_vclk_reset_notifier {
> +	struct clk_regmap *clk;
> +	unsigned int offset;
> +	u8 bit_idx;
> +	struct notifier_block nb;
> +};
> +
> +static int g12a_vclk_notifier_cb(struct notifier_block *nb,
> +				  unsigned long event, void *data)
> +{
> +	struct g12a_vclk_reset_notifier *nb_data =
> +		container_of(nb, struct g12a_vclk_reset_notifier, nb);
> +
> +	switch (event) {
> +	case POST_RATE_CHANGE:
> +		/* reset vclk2 */
> +		regmap_update_bits(nb_data->clk->map, nb_data->offset,
> +				   BIT(nb_data->bit_idx), BIT(nb_data->bit_idx));
> +		regmap_update_bits(nb_data->clk->map, nb_data->offset,
> +				   BIT(nb_data->bit_idx), 0);
> +
> +		return NOTIFY_OK;
> +	default:
> +		return NOTIFY_DONE;
> +	};
> +}
> +
>  static struct clk_regmap g12a_vclk2 = {
>  	.data = &(struct clk_regmap_gate_data){
>  		.offset = HHI_VIID_CLK_CNTL,
> @@ -3253,10 +3321,17 @@ static struct clk_regmap g12a_vclk2 = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2_div.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> +static struct g12a_vclk_reset_notifier g12a_vclk2_data = {
> +	.clk = &g12a_vclk2,
> +	.offset = HHI_VIID_CLK_CNTL,
> +	.bit_idx = 15,
> +	.nb.notifier_call = g12a_vclk_notifier_cb,
> +};
> +
>  static struct clk_regmap g12a_vclk_div1 = {
>  	.data = &(struct clk_regmap_gate_data){
>  		.offset = HHI_VID_CLK_CNTL,
> @@ -3337,7 +3412,7 @@ static struct clk_regmap g12a_vclk2_div1 = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3351,7 +3426,7 @@ static struct clk_regmap g12a_vclk2_div2_en = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3365,7 +3440,7 @@ static struct clk_regmap g12a_vclk2_div4_en = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3379,7 +3454,7 @@ static struct clk_regmap g12a_vclk2_div6_en = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3393,7 +3468,7 @@ static struct clk_regmap g12a_vclk2_div12_en = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3459,6 +3534,7 @@ static struct clk_fixed_factor g12a_vclk2_div2 = {
>  			&g12a_vclk2_div2_en.hw
>  		},
>  		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3472,6 +3548,7 @@ static struct clk_fixed_factor g12a_vclk2_div4 = {
>  			&g12a_vclk2_div4_en.hw
>  		},
>  		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3485,6 +3562,7 @@ static struct clk_fixed_factor g12a_vclk2_div6 = {
>  			&g12a_vclk2_div6_en.hw
>  		},
>  		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3498,6 +3576,7 @@ static struct clk_fixed_factor g12a_vclk2_div12 = {
>  			&g12a_vclk2_div12_en.hw
>  		},
>  		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3559,7 +3638,7 @@ static struct clk_regmap g12a_cts_encl_sel = {
>  		.ops = &clk_regmap_mux_ops,
>  		.parent_hws = g12a_cts_parent_hws,
>  		.num_parents = ARRAY_SIZE(g12a_cts_parent_hws),
> -		.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
> +		.flags = CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3727,7 +3806,7 @@ static struct clk_regmap g12a_mipi_dsi_pxclk_div = {
>  	},
>  	.hw.init = &(struct clk_init_data){
>  		.name = "mipi_dsi_pxclk_div",
> -		.ops = &clk_regmap_divider_ops,
> +		.ops = &clk_regmap_divider_ro_ops,
>  		.parent_hws = (const struct clk_hw *[]) {
>  			&g12a_mipi_dsi_pxclk_sel.hw
>  		},
> @@ -5421,6 +5500,32 @@ static int meson_g12a_dvfs_setup(struct platform_device *pdev)
>  	return 0;
>  }
>  
> +static int meson_g12a_vclk_setup(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct clk *notifier_clk;
> +	int ret;
> +
> +	/* Setup clock notifier for vclk2 */
> +	notifier_clk = devm_clk_hw_get_clk(dev, &g12a_vclk2.hw, DVFS_CON_ID);
> +	ret = devm_clk_notifier_register(dev, notifier_clk, &g12a_vclk2_data.nb);
> +	if (ret) {
> +		dev_err(dev, "failed to register the vlkc2 notifier\n");
> +		return ret;
> +	}
> +
> +	/* Setup clock notifier for vclk2_div */
> +	notifier_clk = devm_clk_hw_get_clk(dev, &g12a_vclk2_div.hw, DVFS_CON_ID);
> +	ret = devm_clk_notifier_register(dev, notifier_clk,
> +					 &g12a_vclk2_div_data.nb);
> +	if (ret) {
> +		dev_err(dev, "failed to register the vclk2_div notifier\n");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
>  struct meson_g12a_data {
>  	const struct meson_eeclkc_data eeclkc_data;
>  	int (*dvfs_setup)(struct platform_device *pdev);
> @@ -5443,6 +5548,10 @@ static int meson_g12a_probe(struct platform_device *pdev)
>  	g12a_data = container_of(eeclkc_data, struct meson_g12a_data,
>  				 eeclkc_data);
>  
> +	ret = meson_g12a_vclk_setup(pdev);
> +	if (ret)
> +		return ret;
> +
>  	if (g12a_data->dvfs_setup)
>  		return g12a_data->dvfs_setup(pdev);


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

WARNING: multiple messages have this Message-ID (diff)
From: Jerome Brunet <jbrunet@baylibre.com>
To: Neil Armstrong <neil.armstrong@linaro.org>,
	Michael Turquette <mturquette@baylibre.com>,
	Stephen Boyd <sboyd@kernel.org>,
	Kevin Hilman <khilman@baylibre.com>,
	Martin Blumenstingl <martin.blumenstingl@googlemail.com>,
	Rob Herring <robh+dt@kernel.org>,
	Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
	Conor Dooley <conor+dt@kernel.org>,
	David Airlie <airlied@gmail.com>, Daniel Vetter <daniel@ffwll.ch>,
	Philipp Zabel <p.zabel@pengutronix.de>,
	Kishon Vijay Abraham I <kishon@kernel.org>,
	Sam Ravnborg <sam@ravnborg.org>
Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	dri-devel@lists.freedesktop.org,
	Nicolas Belin <nbelin@baylibre.com>,
	linux-phy@lists.infradead.org, linux-amlogic@lists.infradead.org,
	"Lukas F. Hartmann" <lukas@mntre.com>,
	linux-clk@vger.kernel.org, linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH v5 05/17] clk: meson: g12a: make VCLK2 and ENCL clock path configurable by CCF
Date: Tue, 30 May 2023 10:14:51 +0200	[thread overview]
Message-ID: <1jv8ga445j.fsf@starbuckisacylon.baylibre.com> (raw)
In-Reply-To: <20230512-amlogic-v6-4-upstream-dsi-ccf-vim3-v5-5-56eb7a4d5b8e@linaro.org>


On Tue 30 May 2023 at 09:38, Neil Armstrong <neil.armstrong@linaro.org> wrote:

> In order to setup the DSI clock, let's make the unused VCLK2 clock path
> configuration via CCF.
>
> The nocache option is removed from following clocks:
> - vclk2_sel
> - vclk2_input
> - vclk2_div
> - vclk2
> - vclk_div1
> - vclk2_div2_en
> - vclk2_div4_en
> - vclk2_div6_en
> - vclk2_div12_en
> - vclk2_div2
> - vclk2_div4
> - vclk2_div6
> - vclk2_div12
> - cts_encl_sel
>
> The missing vclk2 reset sequence is handled via new clkc notifiers
> in order to reset the vclk2 after each rate change as done by Amlogic
> in the vendor implementation.
>
> In order to set a rate on cts_encl via the vclk2 clock path,
> the NO_REPARENT flag is set on cts_encl_sel & vclk2_sel in order
> to keep CCF from selection a parent.
> The parents of cts_encl_sel & vclk2_sel are expected to be defined
> in DT.
>
> The following clock scheme is to be used for DSI:
>
> xtal
> \_ gp0_pll_dco
>    \_ gp0_pll
>       |- vclk2_sel
>       |  \_ vclk2_input
>       |     \_ vclk2_div
>       |        \_ vclk2
>       |           \_ vclk2_div1
>       |              \_ cts_encl_sel
>       |                 \_ cts_encl	-> to VPU LCD Encoder
>       |- mipi_dsi_pxclk_sel
>       \_ mipi_dsi_pxclk_div
>          \_ mipi_dsi_pxclk		-> to DSI controller
>
> The mipi_dsi_pxclk_div is set as RO in order to use the same GP0
> for mipi_dsi_pxclk and vclk2_input.

I don't think notifiers is the appropriate approach here.
Whenever there is clock change the motifiers would trigger an off/on of
the clock, regardless of the clock usage or state.
If you have several consummers on this vclk2, this would
cause glitches and maybe this is not desirable.

I think it would be better to handle the enable and reset with a
specific gate driver, in prepare() or enable(), and the give the clock
CLK_SET_RATE_GATE flag.

This would require the clock to be properly turn off before changing the
rate.

>
> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
>  drivers/clk/meson/g12a.c | 131 +++++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 120 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c
> index 461ebd79497c..e4053f4957d5 100644
> --- a/drivers/clk/meson/g12a.c
> +++ b/drivers/clk/meson/g12a.c
> @@ -3163,7 +3163,7 @@ static struct clk_regmap g12a_vclk2_sel = {
>  		.ops = &clk_regmap_mux_ops,
>  		.parent_hws = g12a_vclk_parent_hws,
>  		.num_parents = ARRAY_SIZE(g12a_vclk_parent_hws),
> -		.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
> +		.flags = CLK_SET_RATE_NO_REPARENT,
>  	},
>  };
>  
> @@ -3191,7 +3191,6 @@ static struct clk_regmap g12a_vclk2_input = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2_sel.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
>  	},
>  };
>  
> @@ -3212,6 +3211,40 @@ static struct clk_regmap g12a_vclk_div = {
>  	},
>  };
>  
> +struct g12a_vclk_div_notifier {
> +	struct clk_regmap *clk;
> +	unsigned int offset;
> +	u8 en_bit_idx;
> +	u8 reset_bit_idx;
> +	struct notifier_block nb;
> +};
> +
> +static int g12a_vclk_div_notifier_cb(struct notifier_block *nb,
> +				  unsigned long event, void *data)
> +{
> +	struct g12a_vclk_div_notifier *nb_data =
> +		container_of(nb, struct g12a_vclk_div_notifier, nb);
> +
> +	switch (event) {
> +	case PRE_RATE_CHANGE:
> +		/* disable and reset vclk2 divider */
> +		regmap_update_bits(nb_data->clk->map, nb_data->offset,
> +				   BIT(nb_data->en_bit_idx) |
> +				   BIT(nb_data->reset_bit_idx),
> +				   BIT(nb_data->reset_bit_idx));
> +		return NOTIFY_OK;
> +	case POST_RATE_CHANGE:
> +		/* enabled and release reset */
> +		regmap_update_bits(nb_data->clk->map, nb_data->offset,
> +				   BIT(nb_data->en_bit_idx) |
> +				   BIT(nb_data->reset_bit_idx),
> +				   BIT(nb_data->en_bit_idx));
> +		return NOTIFY_OK;
> +	default:
> +		return NOTIFY_DONE;
> +	};
> +};
> +
>  static struct clk_regmap g12a_vclk2_div = {
>  	.data = &(struct clk_regmap_div_data){
>  		.offset = HHI_VIID_CLK_DIV,
> @@ -3225,10 +3258,18 @@ static struct clk_regmap g12a_vclk2_div = {
>  			&g12a_vclk2_input.hw
>  		},
>  		.num_parents = 1,
> -		.flags = CLK_GET_RATE_NOCACHE,
> +		.flags = CLK_DIVIDER_ROUND_CLOSEST,
>  	},
>  };
>  
> +static struct g12a_vclk_div_notifier g12a_vclk2_div_data = {
> +	.clk = &g12a_vclk2_div,
> +	.offset = HHI_VIID_CLK_DIV,
> +	.en_bit_idx = 16,
> +	.reset_bit_idx = 17,
> +	.nb.notifier_call = g12a_vclk_div_notifier_cb,
> +};
> +
>  static struct clk_regmap g12a_vclk = {
>  	.data = &(struct clk_regmap_gate_data){
>  		.offset = HHI_VID_CLK_CNTL,
> @@ -3243,6 +3284,33 @@ static struct clk_regmap g12a_vclk = {
>  	},
>  };
>  
> +struct g12a_vclk_reset_notifier {
> +	struct clk_regmap *clk;
> +	unsigned int offset;
> +	u8 bit_idx;
> +	struct notifier_block nb;
> +};
> +
> +static int g12a_vclk_notifier_cb(struct notifier_block *nb,
> +				  unsigned long event, void *data)
> +{
> +	struct g12a_vclk_reset_notifier *nb_data =
> +		container_of(nb, struct g12a_vclk_reset_notifier, nb);
> +
> +	switch (event) {
> +	case POST_RATE_CHANGE:
> +		/* reset vclk2 */
> +		regmap_update_bits(nb_data->clk->map, nb_data->offset,
> +				   BIT(nb_data->bit_idx), BIT(nb_data->bit_idx));
> +		regmap_update_bits(nb_data->clk->map, nb_data->offset,
> +				   BIT(nb_data->bit_idx), 0);
> +
> +		return NOTIFY_OK;
> +	default:
> +		return NOTIFY_DONE;
> +	};
> +}
> +
>  static struct clk_regmap g12a_vclk2 = {
>  	.data = &(struct clk_regmap_gate_data){
>  		.offset = HHI_VIID_CLK_CNTL,
> @@ -3253,10 +3321,17 @@ static struct clk_regmap g12a_vclk2 = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2_div.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> +static struct g12a_vclk_reset_notifier g12a_vclk2_data = {
> +	.clk = &g12a_vclk2,
> +	.offset = HHI_VIID_CLK_CNTL,
> +	.bit_idx = 15,
> +	.nb.notifier_call = g12a_vclk_notifier_cb,
> +};
> +
>  static struct clk_regmap g12a_vclk_div1 = {
>  	.data = &(struct clk_regmap_gate_data){
>  		.offset = HHI_VID_CLK_CNTL,
> @@ -3337,7 +3412,7 @@ static struct clk_regmap g12a_vclk2_div1 = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3351,7 +3426,7 @@ static struct clk_regmap g12a_vclk2_div2_en = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3365,7 +3440,7 @@ static struct clk_regmap g12a_vclk2_div4_en = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3379,7 +3454,7 @@ static struct clk_regmap g12a_vclk2_div6_en = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3393,7 +3468,7 @@ static struct clk_regmap g12a_vclk2_div12_en = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3459,6 +3534,7 @@ static struct clk_fixed_factor g12a_vclk2_div2 = {
>  			&g12a_vclk2_div2_en.hw
>  		},
>  		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3472,6 +3548,7 @@ static struct clk_fixed_factor g12a_vclk2_div4 = {
>  			&g12a_vclk2_div4_en.hw
>  		},
>  		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3485,6 +3562,7 @@ static struct clk_fixed_factor g12a_vclk2_div6 = {
>  			&g12a_vclk2_div6_en.hw
>  		},
>  		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3498,6 +3576,7 @@ static struct clk_fixed_factor g12a_vclk2_div12 = {
>  			&g12a_vclk2_div12_en.hw
>  		},
>  		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3559,7 +3638,7 @@ static struct clk_regmap g12a_cts_encl_sel = {
>  		.ops = &clk_regmap_mux_ops,
>  		.parent_hws = g12a_cts_parent_hws,
>  		.num_parents = ARRAY_SIZE(g12a_cts_parent_hws),
> -		.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
> +		.flags = CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3727,7 +3806,7 @@ static struct clk_regmap g12a_mipi_dsi_pxclk_div = {
>  	},
>  	.hw.init = &(struct clk_init_data){
>  		.name = "mipi_dsi_pxclk_div",
> -		.ops = &clk_regmap_divider_ops,
> +		.ops = &clk_regmap_divider_ro_ops,
>  		.parent_hws = (const struct clk_hw *[]) {
>  			&g12a_mipi_dsi_pxclk_sel.hw
>  		},
> @@ -5421,6 +5500,32 @@ static int meson_g12a_dvfs_setup(struct platform_device *pdev)
>  	return 0;
>  }
>  
> +static int meson_g12a_vclk_setup(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct clk *notifier_clk;
> +	int ret;
> +
> +	/* Setup clock notifier for vclk2 */
> +	notifier_clk = devm_clk_hw_get_clk(dev, &g12a_vclk2.hw, DVFS_CON_ID);
> +	ret = devm_clk_notifier_register(dev, notifier_clk, &g12a_vclk2_data.nb);
> +	if (ret) {
> +		dev_err(dev, "failed to register the vlkc2 notifier\n");
> +		return ret;
> +	}
> +
> +	/* Setup clock notifier for vclk2_div */
> +	notifier_clk = devm_clk_hw_get_clk(dev, &g12a_vclk2_div.hw, DVFS_CON_ID);
> +	ret = devm_clk_notifier_register(dev, notifier_clk,
> +					 &g12a_vclk2_div_data.nb);
> +	if (ret) {
> +		dev_err(dev, "failed to register the vclk2_div notifier\n");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
>  struct meson_g12a_data {
>  	const struct meson_eeclkc_data eeclkc_data;
>  	int (*dvfs_setup)(struct platform_device *pdev);
> @@ -5443,6 +5548,10 @@ static int meson_g12a_probe(struct platform_device *pdev)
>  	g12a_data = container_of(eeclkc_data, struct meson_g12a_data,
>  				 eeclkc_data);
>  
> +	ret = meson_g12a_vclk_setup(pdev);
> +	if (ret)
> +		return ret;
> +
>  	if (g12a_data->dvfs_setup)
>  		return g12a_data->dvfs_setup(pdev);


WARNING: multiple messages have this Message-ID (diff)
From: Jerome Brunet <jbrunet@baylibre.com>
To: Neil Armstrong <neil.armstrong@linaro.org>,
	Michael Turquette <mturquette@baylibre.com>,
	Stephen Boyd <sboyd@kernel.org>,
	Kevin Hilman <khilman@baylibre.com>,
	Martin Blumenstingl <martin.blumenstingl@googlemail.com>,
	Rob Herring <robh+dt@kernel.org>,
	Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
	Conor Dooley <conor+dt@kernel.org>,
	David Airlie <airlied@gmail.com>, Daniel Vetter <daniel@ffwll.ch>,
	Philipp Zabel <p.zabel@pengutronix.de>,
	Kishon Vijay Abraham I <kishon@kernel.org>,
	Sam Ravnborg <sam@ravnborg.org>
Cc: "Lukas F. Hartmann" <lukas@mntre.com>,
	Nicolas Belin <nbelin@baylibre.com>,
	linux-amlogic@lists.infradead.org, linux-clk@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
	dri-devel@lists.freedesktop.org, linux-phy@lists.infradead.org
Subject: Re: [PATCH v5 05/17] clk: meson: g12a: make VCLK2 and ENCL clock path configurable by CCF
Date: Tue, 30 May 2023 10:14:51 +0200	[thread overview]
Message-ID: <1jv8ga445j.fsf@starbuckisacylon.baylibre.com> (raw)
In-Reply-To: <20230512-amlogic-v6-4-upstream-dsi-ccf-vim3-v5-5-56eb7a4d5b8e@linaro.org>


On Tue 30 May 2023 at 09:38, Neil Armstrong <neil.armstrong@linaro.org> wrote:

> In order to setup the DSI clock, let's make the unused VCLK2 clock path
> configuration via CCF.
>
> The nocache option is removed from following clocks:
> - vclk2_sel
> - vclk2_input
> - vclk2_div
> - vclk2
> - vclk_div1
> - vclk2_div2_en
> - vclk2_div4_en
> - vclk2_div6_en
> - vclk2_div12_en
> - vclk2_div2
> - vclk2_div4
> - vclk2_div6
> - vclk2_div12
> - cts_encl_sel
>
> The missing vclk2 reset sequence is handled via new clkc notifiers
> in order to reset the vclk2 after each rate change as done by Amlogic
> in the vendor implementation.
>
> In order to set a rate on cts_encl via the vclk2 clock path,
> the NO_REPARENT flag is set on cts_encl_sel & vclk2_sel in order
> to keep CCF from selection a parent.
> The parents of cts_encl_sel & vclk2_sel are expected to be defined
> in DT.
>
> The following clock scheme is to be used for DSI:
>
> xtal
> \_ gp0_pll_dco
>    \_ gp0_pll
>       |- vclk2_sel
>       |  \_ vclk2_input
>       |     \_ vclk2_div
>       |        \_ vclk2
>       |           \_ vclk2_div1
>       |              \_ cts_encl_sel
>       |                 \_ cts_encl	-> to VPU LCD Encoder
>       |- mipi_dsi_pxclk_sel
>       \_ mipi_dsi_pxclk_div
>          \_ mipi_dsi_pxclk		-> to DSI controller
>
> The mipi_dsi_pxclk_div is set as RO in order to use the same GP0
> for mipi_dsi_pxclk and vclk2_input.

I don't think notifiers is the appropriate approach here.
Whenever there is clock change the motifiers would trigger an off/on of
the clock, regardless of the clock usage or state.
If you have several consummers on this vclk2, this would
cause glitches and maybe this is not desirable.

I think it would be better to handle the enable and reset with a
specific gate driver, in prepare() or enable(), and the give the clock
CLK_SET_RATE_GATE flag.

This would require the clock to be properly turn off before changing the
rate.

>
> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
>  drivers/clk/meson/g12a.c | 131 +++++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 120 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c
> index 461ebd79497c..e4053f4957d5 100644
> --- a/drivers/clk/meson/g12a.c
> +++ b/drivers/clk/meson/g12a.c
> @@ -3163,7 +3163,7 @@ static struct clk_regmap g12a_vclk2_sel = {
>  		.ops = &clk_regmap_mux_ops,
>  		.parent_hws = g12a_vclk_parent_hws,
>  		.num_parents = ARRAY_SIZE(g12a_vclk_parent_hws),
> -		.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
> +		.flags = CLK_SET_RATE_NO_REPARENT,
>  	},
>  };
>  
> @@ -3191,7 +3191,6 @@ static struct clk_regmap g12a_vclk2_input = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2_sel.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
>  	},
>  };
>  
> @@ -3212,6 +3211,40 @@ static struct clk_regmap g12a_vclk_div = {
>  	},
>  };
>  
> +struct g12a_vclk_div_notifier {
> +	struct clk_regmap *clk;
> +	unsigned int offset;
> +	u8 en_bit_idx;
> +	u8 reset_bit_idx;
> +	struct notifier_block nb;
> +};
> +
> +static int g12a_vclk_div_notifier_cb(struct notifier_block *nb,
> +				  unsigned long event, void *data)
> +{
> +	struct g12a_vclk_div_notifier *nb_data =
> +		container_of(nb, struct g12a_vclk_div_notifier, nb);
> +
> +	switch (event) {
> +	case PRE_RATE_CHANGE:
> +		/* disable and reset vclk2 divider */
> +		regmap_update_bits(nb_data->clk->map, nb_data->offset,
> +				   BIT(nb_data->en_bit_idx) |
> +				   BIT(nb_data->reset_bit_idx),
> +				   BIT(nb_data->reset_bit_idx));
> +		return NOTIFY_OK;
> +	case POST_RATE_CHANGE:
> +		/* enabled and release reset */
> +		regmap_update_bits(nb_data->clk->map, nb_data->offset,
> +				   BIT(nb_data->en_bit_idx) |
> +				   BIT(nb_data->reset_bit_idx),
> +				   BIT(nb_data->en_bit_idx));
> +		return NOTIFY_OK;
> +	default:
> +		return NOTIFY_DONE;
> +	};
> +};
> +
>  static struct clk_regmap g12a_vclk2_div = {
>  	.data = &(struct clk_regmap_div_data){
>  		.offset = HHI_VIID_CLK_DIV,
> @@ -3225,10 +3258,18 @@ static struct clk_regmap g12a_vclk2_div = {
>  			&g12a_vclk2_input.hw
>  		},
>  		.num_parents = 1,
> -		.flags = CLK_GET_RATE_NOCACHE,
> +		.flags = CLK_DIVIDER_ROUND_CLOSEST,
>  	},
>  };
>  
> +static struct g12a_vclk_div_notifier g12a_vclk2_div_data = {
> +	.clk = &g12a_vclk2_div,
> +	.offset = HHI_VIID_CLK_DIV,
> +	.en_bit_idx = 16,
> +	.reset_bit_idx = 17,
> +	.nb.notifier_call = g12a_vclk_div_notifier_cb,
> +};
> +
>  static struct clk_regmap g12a_vclk = {
>  	.data = &(struct clk_regmap_gate_data){
>  		.offset = HHI_VID_CLK_CNTL,
> @@ -3243,6 +3284,33 @@ static struct clk_regmap g12a_vclk = {
>  	},
>  };
>  
> +struct g12a_vclk_reset_notifier {
> +	struct clk_regmap *clk;
> +	unsigned int offset;
> +	u8 bit_idx;
> +	struct notifier_block nb;
> +};
> +
> +static int g12a_vclk_notifier_cb(struct notifier_block *nb,
> +				  unsigned long event, void *data)
> +{
> +	struct g12a_vclk_reset_notifier *nb_data =
> +		container_of(nb, struct g12a_vclk_reset_notifier, nb);
> +
> +	switch (event) {
> +	case POST_RATE_CHANGE:
> +		/* reset vclk2 */
> +		regmap_update_bits(nb_data->clk->map, nb_data->offset,
> +				   BIT(nb_data->bit_idx), BIT(nb_data->bit_idx));
> +		regmap_update_bits(nb_data->clk->map, nb_data->offset,
> +				   BIT(nb_data->bit_idx), 0);
> +
> +		return NOTIFY_OK;
> +	default:
> +		return NOTIFY_DONE;
> +	};
> +}
> +
>  static struct clk_regmap g12a_vclk2 = {
>  	.data = &(struct clk_regmap_gate_data){
>  		.offset = HHI_VIID_CLK_CNTL,
> @@ -3253,10 +3321,17 @@ static struct clk_regmap g12a_vclk2 = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2_div.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> +static struct g12a_vclk_reset_notifier g12a_vclk2_data = {
> +	.clk = &g12a_vclk2,
> +	.offset = HHI_VIID_CLK_CNTL,
> +	.bit_idx = 15,
> +	.nb.notifier_call = g12a_vclk_notifier_cb,
> +};
> +
>  static struct clk_regmap g12a_vclk_div1 = {
>  	.data = &(struct clk_regmap_gate_data){
>  		.offset = HHI_VID_CLK_CNTL,
> @@ -3337,7 +3412,7 @@ static struct clk_regmap g12a_vclk2_div1 = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3351,7 +3426,7 @@ static struct clk_regmap g12a_vclk2_div2_en = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3365,7 +3440,7 @@ static struct clk_regmap g12a_vclk2_div4_en = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3379,7 +3454,7 @@ static struct clk_regmap g12a_vclk2_div6_en = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3393,7 +3468,7 @@ static struct clk_regmap g12a_vclk2_div12_en = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3459,6 +3534,7 @@ static struct clk_fixed_factor g12a_vclk2_div2 = {
>  			&g12a_vclk2_div2_en.hw
>  		},
>  		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3472,6 +3548,7 @@ static struct clk_fixed_factor g12a_vclk2_div4 = {
>  			&g12a_vclk2_div4_en.hw
>  		},
>  		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3485,6 +3562,7 @@ static struct clk_fixed_factor g12a_vclk2_div6 = {
>  			&g12a_vclk2_div6_en.hw
>  		},
>  		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3498,6 +3576,7 @@ static struct clk_fixed_factor g12a_vclk2_div12 = {
>  			&g12a_vclk2_div12_en.hw
>  		},
>  		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3559,7 +3638,7 @@ static struct clk_regmap g12a_cts_encl_sel = {
>  		.ops = &clk_regmap_mux_ops,
>  		.parent_hws = g12a_cts_parent_hws,
>  		.num_parents = ARRAY_SIZE(g12a_cts_parent_hws),
> -		.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
> +		.flags = CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3727,7 +3806,7 @@ static struct clk_regmap g12a_mipi_dsi_pxclk_div = {
>  	},
>  	.hw.init = &(struct clk_init_data){
>  		.name = "mipi_dsi_pxclk_div",
> -		.ops = &clk_regmap_divider_ops,
> +		.ops = &clk_regmap_divider_ro_ops,
>  		.parent_hws = (const struct clk_hw *[]) {
>  			&g12a_mipi_dsi_pxclk_sel.hw
>  		},
> @@ -5421,6 +5500,32 @@ static int meson_g12a_dvfs_setup(struct platform_device *pdev)
>  	return 0;
>  }
>  
> +static int meson_g12a_vclk_setup(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct clk *notifier_clk;
> +	int ret;
> +
> +	/* Setup clock notifier for vclk2 */
> +	notifier_clk = devm_clk_hw_get_clk(dev, &g12a_vclk2.hw, DVFS_CON_ID);
> +	ret = devm_clk_notifier_register(dev, notifier_clk, &g12a_vclk2_data.nb);
> +	if (ret) {
> +		dev_err(dev, "failed to register the vlkc2 notifier\n");
> +		return ret;
> +	}
> +
> +	/* Setup clock notifier for vclk2_div */
> +	notifier_clk = devm_clk_hw_get_clk(dev, &g12a_vclk2_div.hw, DVFS_CON_ID);
> +	ret = devm_clk_notifier_register(dev, notifier_clk,
> +					 &g12a_vclk2_div_data.nb);
> +	if (ret) {
> +		dev_err(dev, "failed to register the vclk2_div notifier\n");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
>  struct meson_g12a_data {
>  	const struct meson_eeclkc_data eeclkc_data;
>  	int (*dvfs_setup)(struct platform_device *pdev);
> @@ -5443,6 +5548,10 @@ static int meson_g12a_probe(struct platform_device *pdev)
>  	g12a_data = container_of(eeclkc_data, struct meson_g12a_data,
>  				 eeclkc_data);
>  
> +	ret = meson_g12a_vclk_setup(pdev);
> +	if (ret)
> +		return ret;
> +
>  	if (g12a_data->dvfs_setup)
>  		return g12a_data->dvfs_setup(pdev);


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

WARNING: multiple messages have this Message-ID (diff)
From: Jerome Brunet <jbrunet@baylibre.com>
To: Neil Armstrong <neil.armstrong@linaro.org>,
	Michael Turquette <mturquette@baylibre.com>,
	Stephen Boyd <sboyd@kernel.org>,
	Kevin Hilman <khilman@baylibre.com>,
	Martin Blumenstingl <martin.blumenstingl@googlemail.com>,
	Rob Herring <robh+dt@kernel.org>,
	Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
	Conor Dooley <conor+dt@kernel.org>,
	David Airlie <airlied@gmail.com>, Daniel Vetter <daniel@ffwll.ch>,
	Philipp Zabel <p.zabel@pengutronix.de>,
	Kishon Vijay Abraham I <kishon@kernel.org>,
	Sam Ravnborg <sam@ravnborg.org>
Cc: "Lukas F. Hartmann" <lukas@mntre.com>,
	Nicolas Belin <nbelin@baylibre.com>,
	linux-amlogic@lists.infradead.org, linux-clk@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
	dri-devel@lists.freedesktop.org, linux-phy@lists.infradead.org
Subject: Re: [PATCH v5 05/17] clk: meson: g12a: make VCLK2 and ENCL clock path configurable by CCF
Date: Tue, 30 May 2023 10:14:51 +0200	[thread overview]
Message-ID: <1jv8ga445j.fsf@starbuckisacylon.baylibre.com> (raw)
In-Reply-To: <20230512-amlogic-v6-4-upstream-dsi-ccf-vim3-v5-5-56eb7a4d5b8e@linaro.org>


On Tue 30 May 2023 at 09:38, Neil Armstrong <neil.armstrong@linaro.org> wrote:

> In order to setup the DSI clock, let's make the unused VCLK2 clock path
> configuration via CCF.
>
> The nocache option is removed from following clocks:
> - vclk2_sel
> - vclk2_input
> - vclk2_div
> - vclk2
> - vclk_div1
> - vclk2_div2_en
> - vclk2_div4_en
> - vclk2_div6_en
> - vclk2_div12_en
> - vclk2_div2
> - vclk2_div4
> - vclk2_div6
> - vclk2_div12
> - cts_encl_sel
>
> The missing vclk2 reset sequence is handled via new clkc notifiers
> in order to reset the vclk2 after each rate change as done by Amlogic
> in the vendor implementation.
>
> In order to set a rate on cts_encl via the vclk2 clock path,
> the NO_REPARENT flag is set on cts_encl_sel & vclk2_sel in order
> to keep CCF from selection a parent.
> The parents of cts_encl_sel & vclk2_sel are expected to be defined
> in DT.
>
> The following clock scheme is to be used for DSI:
>
> xtal
> \_ gp0_pll_dco
>    \_ gp0_pll
>       |- vclk2_sel
>       |  \_ vclk2_input
>       |     \_ vclk2_div
>       |        \_ vclk2
>       |           \_ vclk2_div1
>       |              \_ cts_encl_sel
>       |                 \_ cts_encl	-> to VPU LCD Encoder
>       |- mipi_dsi_pxclk_sel
>       \_ mipi_dsi_pxclk_div
>          \_ mipi_dsi_pxclk		-> to DSI controller
>
> The mipi_dsi_pxclk_div is set as RO in order to use the same GP0
> for mipi_dsi_pxclk and vclk2_input.

I don't think notifiers is the appropriate approach here.
Whenever there is clock change the motifiers would trigger an off/on of
the clock, regardless of the clock usage or state.
If you have several consummers on this vclk2, this would
cause glitches and maybe this is not desirable.

I think it would be better to handle the enable and reset with a
specific gate driver, in prepare() or enable(), and the give the clock
CLK_SET_RATE_GATE flag.

This would require the clock to be properly turn off before changing the
rate.

>
> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
>  drivers/clk/meson/g12a.c | 131 +++++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 120 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c
> index 461ebd79497c..e4053f4957d5 100644
> --- a/drivers/clk/meson/g12a.c
> +++ b/drivers/clk/meson/g12a.c
> @@ -3163,7 +3163,7 @@ static struct clk_regmap g12a_vclk2_sel = {
>  		.ops = &clk_regmap_mux_ops,
>  		.parent_hws = g12a_vclk_parent_hws,
>  		.num_parents = ARRAY_SIZE(g12a_vclk_parent_hws),
> -		.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
> +		.flags = CLK_SET_RATE_NO_REPARENT,
>  	},
>  };
>  
> @@ -3191,7 +3191,6 @@ static struct clk_regmap g12a_vclk2_input = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2_sel.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
>  	},
>  };
>  
> @@ -3212,6 +3211,40 @@ static struct clk_regmap g12a_vclk_div = {
>  	},
>  };
>  
> +struct g12a_vclk_div_notifier {
> +	struct clk_regmap *clk;
> +	unsigned int offset;
> +	u8 en_bit_idx;
> +	u8 reset_bit_idx;
> +	struct notifier_block nb;
> +};
> +
> +static int g12a_vclk_div_notifier_cb(struct notifier_block *nb,
> +				  unsigned long event, void *data)
> +{
> +	struct g12a_vclk_div_notifier *nb_data =
> +		container_of(nb, struct g12a_vclk_div_notifier, nb);
> +
> +	switch (event) {
> +	case PRE_RATE_CHANGE:
> +		/* disable and reset vclk2 divider */
> +		regmap_update_bits(nb_data->clk->map, nb_data->offset,
> +				   BIT(nb_data->en_bit_idx) |
> +				   BIT(nb_data->reset_bit_idx),
> +				   BIT(nb_data->reset_bit_idx));
> +		return NOTIFY_OK;
> +	case POST_RATE_CHANGE:
> +		/* enabled and release reset */
> +		regmap_update_bits(nb_data->clk->map, nb_data->offset,
> +				   BIT(nb_data->en_bit_idx) |
> +				   BIT(nb_data->reset_bit_idx),
> +				   BIT(nb_data->en_bit_idx));
> +		return NOTIFY_OK;
> +	default:
> +		return NOTIFY_DONE;
> +	};
> +};
> +
>  static struct clk_regmap g12a_vclk2_div = {
>  	.data = &(struct clk_regmap_div_data){
>  		.offset = HHI_VIID_CLK_DIV,
> @@ -3225,10 +3258,18 @@ static struct clk_regmap g12a_vclk2_div = {
>  			&g12a_vclk2_input.hw
>  		},
>  		.num_parents = 1,
> -		.flags = CLK_GET_RATE_NOCACHE,
> +		.flags = CLK_DIVIDER_ROUND_CLOSEST,
>  	},
>  };
>  
> +static struct g12a_vclk_div_notifier g12a_vclk2_div_data = {
> +	.clk = &g12a_vclk2_div,
> +	.offset = HHI_VIID_CLK_DIV,
> +	.en_bit_idx = 16,
> +	.reset_bit_idx = 17,
> +	.nb.notifier_call = g12a_vclk_div_notifier_cb,
> +};
> +
>  static struct clk_regmap g12a_vclk = {
>  	.data = &(struct clk_regmap_gate_data){
>  		.offset = HHI_VID_CLK_CNTL,
> @@ -3243,6 +3284,33 @@ static struct clk_regmap g12a_vclk = {
>  	},
>  };
>  
> +struct g12a_vclk_reset_notifier {
> +	struct clk_regmap *clk;
> +	unsigned int offset;
> +	u8 bit_idx;
> +	struct notifier_block nb;
> +};
> +
> +static int g12a_vclk_notifier_cb(struct notifier_block *nb,
> +				  unsigned long event, void *data)
> +{
> +	struct g12a_vclk_reset_notifier *nb_data =
> +		container_of(nb, struct g12a_vclk_reset_notifier, nb);
> +
> +	switch (event) {
> +	case POST_RATE_CHANGE:
> +		/* reset vclk2 */
> +		regmap_update_bits(nb_data->clk->map, nb_data->offset,
> +				   BIT(nb_data->bit_idx), BIT(nb_data->bit_idx));
> +		regmap_update_bits(nb_data->clk->map, nb_data->offset,
> +				   BIT(nb_data->bit_idx), 0);
> +
> +		return NOTIFY_OK;
> +	default:
> +		return NOTIFY_DONE;
> +	};
> +}
> +
>  static struct clk_regmap g12a_vclk2 = {
>  	.data = &(struct clk_regmap_gate_data){
>  		.offset = HHI_VIID_CLK_CNTL,
> @@ -3253,10 +3321,17 @@ static struct clk_regmap g12a_vclk2 = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2_div.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> +static struct g12a_vclk_reset_notifier g12a_vclk2_data = {
> +	.clk = &g12a_vclk2,
> +	.offset = HHI_VIID_CLK_CNTL,
> +	.bit_idx = 15,
> +	.nb.notifier_call = g12a_vclk_notifier_cb,
> +};
> +
>  static struct clk_regmap g12a_vclk_div1 = {
>  	.data = &(struct clk_regmap_gate_data){
>  		.offset = HHI_VID_CLK_CNTL,
> @@ -3337,7 +3412,7 @@ static struct clk_regmap g12a_vclk2_div1 = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3351,7 +3426,7 @@ static struct clk_regmap g12a_vclk2_div2_en = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3365,7 +3440,7 @@ static struct clk_regmap g12a_vclk2_div4_en = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3379,7 +3454,7 @@ static struct clk_regmap g12a_vclk2_div6_en = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3393,7 +3468,7 @@ static struct clk_regmap g12a_vclk2_div12_en = {
>  		.ops = &clk_regmap_gate_ops,
>  		.parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw },
>  		.num_parents = 1,
> -		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3459,6 +3534,7 @@ static struct clk_fixed_factor g12a_vclk2_div2 = {
>  			&g12a_vclk2_div2_en.hw
>  		},
>  		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3472,6 +3548,7 @@ static struct clk_fixed_factor g12a_vclk2_div4 = {
>  			&g12a_vclk2_div4_en.hw
>  		},
>  		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3485,6 +3562,7 @@ static struct clk_fixed_factor g12a_vclk2_div6 = {
>  			&g12a_vclk2_div6_en.hw
>  		},
>  		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3498,6 +3576,7 @@ static struct clk_fixed_factor g12a_vclk2_div12 = {
>  			&g12a_vclk2_div12_en.hw
>  		},
>  		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3559,7 +3638,7 @@ static struct clk_regmap g12a_cts_encl_sel = {
>  		.ops = &clk_regmap_mux_ops,
>  		.parent_hws = g12a_cts_parent_hws,
>  		.num_parents = ARRAY_SIZE(g12a_cts_parent_hws),
> -		.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
> +		.flags = CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT,
>  	},
>  };
>  
> @@ -3727,7 +3806,7 @@ static struct clk_regmap g12a_mipi_dsi_pxclk_div = {
>  	},
>  	.hw.init = &(struct clk_init_data){
>  		.name = "mipi_dsi_pxclk_div",
> -		.ops = &clk_regmap_divider_ops,
> +		.ops = &clk_regmap_divider_ro_ops,
>  		.parent_hws = (const struct clk_hw *[]) {
>  			&g12a_mipi_dsi_pxclk_sel.hw
>  		},
> @@ -5421,6 +5500,32 @@ static int meson_g12a_dvfs_setup(struct platform_device *pdev)
>  	return 0;
>  }
>  
> +static int meson_g12a_vclk_setup(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct clk *notifier_clk;
> +	int ret;
> +
> +	/* Setup clock notifier for vclk2 */
> +	notifier_clk = devm_clk_hw_get_clk(dev, &g12a_vclk2.hw, DVFS_CON_ID);
> +	ret = devm_clk_notifier_register(dev, notifier_clk, &g12a_vclk2_data.nb);
> +	if (ret) {
> +		dev_err(dev, "failed to register the vlkc2 notifier\n");
> +		return ret;
> +	}
> +
> +	/* Setup clock notifier for vclk2_div */
> +	notifier_clk = devm_clk_hw_get_clk(dev, &g12a_vclk2_div.hw, DVFS_CON_ID);
> +	ret = devm_clk_notifier_register(dev, notifier_clk,
> +					 &g12a_vclk2_div_data.nb);
> +	if (ret) {
> +		dev_err(dev, "failed to register the vclk2_div notifier\n");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
>  struct meson_g12a_data {
>  	const struct meson_eeclkc_data eeclkc_data;
>  	int (*dvfs_setup)(struct platform_device *pdev);
> @@ -5443,6 +5548,10 @@ static int meson_g12a_probe(struct platform_device *pdev)
>  	g12a_data = container_of(eeclkc_data, struct meson_g12a_data,
>  				 eeclkc_data);
>  
> +	ret = meson_g12a_vclk_setup(pdev);
> +	if (ret)
> +		return ret;
> +
>  	if (g12a_data->dvfs_setup)
>  		return g12a_data->dvfs_setup(pdev);


-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

  reply	other threads:[~2023-05-30  8:25 UTC|newest]

Thread overview: 170+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-30  7:38 [PATCH v5 00/17] drm/meson: add support for MIPI DSI Display Neil Armstrong
2023-05-30  7:38 ` Neil Armstrong
2023-05-30  7:38 ` Neil Armstrong
2023-05-30  7:38 ` Neil Armstrong
2023-05-30  7:38 ` Neil Armstrong
2023-05-30  7:38 ` [PATCH v5 01/17] clk: meson: g12a: prefix private CLK IDs defines with PRIV Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  8:08   ` Jerome Brunet
2023-05-30  8:08     ` Jerome Brunet
2023-05-30  8:08     ` Jerome Brunet
2023-05-30  8:08     ` Jerome Brunet
2023-05-30  8:08     ` Jerome Brunet
2023-05-30 15:56     ` Neil Armstrong
2023-05-30 15:56       ` Neil Armstrong
2023-05-30 15:56       ` Neil Armstrong
2023-05-30 15:56       ` Neil Armstrong
2023-05-30 15:56       ` Neil Armstrong
2023-05-31 16:08       ` Jerome Brunet
2023-05-31 16:08         ` Jerome Brunet
2023-05-31 16:08         ` Jerome Brunet
2023-05-31 16:08         ` Jerome Brunet
2023-05-31 16:08         ` Jerome Brunet
2023-05-30  7:38 ` [PATCH v5 02/17] clk: meson: g12a: add CTS_ENCL & CTS_ENCL_SEL clocks Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38 ` [PATCH v5 03/17] dt-bindings: clk: g12a-clkc: add VCLK2_SEL and CTS_ENCL clock ids Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30 17:25   ` Conor Dooley
2023-05-30 17:25     ` Conor Dooley
2023-05-30 17:25     ` Conor Dooley
2023-05-30 17:25     ` Conor Dooley
2023-05-30 17:25     ` Conor Dooley
2023-05-30  7:38 ` [PATCH v5 04/17] clk: meson: g12: use VCLK2_SEL, CTS_ENCL & CTS_ENCL_SEL public CLK IDs Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38 ` [PATCH v5 05/17] clk: meson: g12a: make VCLK2 and ENCL clock path configurable by CCF Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  8:14   ` Jerome Brunet [this message]
2023-05-30  8:14     ` Jerome Brunet
2023-05-30  8:14     ` Jerome Brunet
2023-05-30  8:14     ` Jerome Brunet
2023-05-30  8:14     ` Jerome Brunet
2023-05-30 15:57     ` Neil Armstrong
2023-05-30 15:57       ` Neil Armstrong
2023-05-30 15:57       ` Neil Armstrong
2023-05-30 15:57       ` Neil Armstrong
2023-05-30 15:57       ` Neil Armstrong
2023-05-30 19:36       ` Martin Blumenstingl
2023-05-30 19:36         ` Martin Blumenstingl
2023-05-30 19:36         ` Martin Blumenstingl
2023-05-30 19:36         ` Martin Blumenstingl
2023-05-30 19:36         ` Martin Blumenstingl
2023-05-30  7:38 ` [PATCH v5 06/17] dt-bindings: display: add Amlogic MIPI DSI Host Controller bindings Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30 17:28   ` Conor Dooley
2023-05-30 17:28     ` Conor Dooley
2023-05-30 17:28     ` Conor Dooley
2023-05-30 17:28     ` Conor Dooley
2023-05-30 17:28     ` Conor Dooley
2023-05-30  7:38 ` [PATCH v5 07/17] dt-bindings: display: meson-vpu: add third DPI output port Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38 ` [PATCH v5 08/17] drm/meson: fix unbind path if HDMI fails to bind Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-31  9:19   ` Nicolas Belin
2023-05-31  9:19     ` Nicolas Belin
2023-05-31  9:19     ` Nicolas Belin
2023-05-31  9:19     ` Nicolas Belin
2023-05-31  9:19     ` Nicolas Belin
2023-05-30  7:38 ` [PATCH v5 09/17] drm/meson: only use components with dw-hdmi Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-31  9:21   ` Nicolas Belin
2023-05-31  9:21     ` Nicolas Belin
2023-05-31  9:21     ` Nicolas Belin
2023-05-31  9:21     ` Nicolas Belin
2023-05-31  9:21     ` Nicolas Belin
2023-05-30  7:38 ` [PATCH v5 10/17] drm/meson: venc: add ENCL encoder setup for MIPI-DSI output Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-31  9:21   ` Nicolas Belin
2023-05-31  9:21     ` Nicolas Belin
2023-05-31  9:21     ` Nicolas Belin
2023-05-31  9:21     ` Nicolas Belin
2023-05-31  9:21     ` Nicolas Belin
2023-05-30  7:38 ` [PATCH v5 11/17] drm/meson: add DSI encoder Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-31  9:22   ` Nicolas Belin
2023-05-31  9:22     ` Nicolas Belin
2023-05-31  9:22     ` Nicolas Belin
2023-05-31  9:22     ` Nicolas Belin
2023-05-31  9:22     ` Nicolas Belin
2023-05-30  7:38 ` [PATCH v5 12/17] drm/meson: add support for MIPI-DSI transceiver Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-31  9:22   ` Nicolas Belin
2023-05-31  9:22     ` Nicolas Belin
2023-05-31  9:22     ` Nicolas Belin
2023-05-31  9:22     ` Nicolas Belin
2023-05-31  9:22     ` Nicolas Belin
2023-05-30  7:38 ` [PATCH v5 13/17] drm/panel: khadas-ts050: update timings to achieve 60Hz refresh rate Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-31  9:23   ` Nicolas Belin
2023-05-31  9:23     ` Nicolas Belin
2023-05-31  9:23     ` Nicolas Belin
2023-05-31  9:23     ` Nicolas Belin
2023-05-31  9:23     ` Nicolas Belin
2023-05-30  7:38 ` [PATCH v5 14/17] arm64: meson: g12-common: add the MIPI DSI nodes Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38 ` [PATCH v5 15/17] DONOTMERGE: arm64: meson: khadas-vim3l: add DSI panel Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38 ` [PATCH v5 16/17] dt-bindings: arm: amlogic: Document the MNT Reform 2 CM4 adapter with a BPI-CM4 Module Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30 17:23   ` Conor Dooley
2023-05-30 17:23     ` Conor Dooley
2023-05-30 17:23     ` Conor Dooley
2023-05-30 17:23     ` Conor Dooley
2023-05-30 17:23     ` Conor Dooley
2023-05-30  7:38 ` [PATCH v5 17/17] arm64: dts: amlogic: meson-g12b-bananapi-cm4: add support for MNT Reform2 with CM4 adaper Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-05-30  7:38   ` Neil Armstrong
2023-06-01 14:12 ` (subset) [PATCH v5 00/17] drm/meson: add support for MIPI DSI Display Neil Armstrong
2023-06-01 14:12   ` Neil Armstrong
2023-06-01 14:12   ` Neil Armstrong
2023-06-01 14:12   ` Neil Armstrong
2023-06-01 14:12   ` Neil Armstrong

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=1jv8ga445j.fsf@starbuckisacylon.baylibre.com \
    --to=jbrunet@baylibre.com \
    --cc=airlied@gmail.com \
    --cc=conor+dt@kernel.org \
    --cc=daniel@ffwll.ch \
    --cc=devicetree@vger.kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=khilman@baylibre.com \
    --cc=kishon@kernel.org \
    --cc=krzysztof.kozlowski+dt@linaro.org \
    --cc=linux-amlogic@lists.infradead.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-phy@lists.infradead.org \
    --cc=lukas@mntre.com \
    --cc=martin.blumenstingl@googlemail.com \
    --cc=mturquette@baylibre.com \
    --cc=nbelin@baylibre.com \
    --cc=neil.armstrong@linaro.org \
    --cc=p.zabel@pengutronix.de \
    --cc=robh+dt@kernel.org \
    --cc=sam@ravnborg.org \
    --cc=sboyd@kernel.org \
    /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.