diff mbox series

[v3,2/7] clk: st: flexgen: embed soc clock outputs within compatible data

Message ID 20210330205125.25708-3-avolmat@me.com (mailing list archive)
State New, archived
Headers show
Series clk: st: embed clock outputs within drivers | expand

Commit Message

Alain Volmat March 30, 2021, 8:51 p.m. UTC
In order to avoid relying on the old style description via the DT
clock-output-names, add compatible data describing the flexgen
outputs clocks for all STiH407/STiH410 and STiH418 SOCs.

In order to ease transition between the two methods, this commit
introduce the new compatible without removing the old method.
Once DTs will be fixed, the method relying on DT clock-output-names
will be removed from this driver as well as old compatibles.

Signed-off-by: Alain Volmat <avolmat@me.com>
---
v3: add comments about CLK_IS_CRITICAL reason
    don't put clk-proc-stfe as CLK_IS_CRITICAL
v2: add some missing clock as CLK_IS_CRITICAL

 drivers/clk/st/clk-flexgen.c | 366 +++++++++++++++++++++++++++++++++--
 1 file changed, 352 insertions(+), 14 deletions(-)

Comments

Patrice CHOTARD March 31, 2021, 4:06 p.m. UTC | #1
Hi Alain

I have tested your series on STiH410-B2260 board and it misses a critical flag, see below

On 3/30/21 10:51 PM, Alain Volmat wrote:
> In order to avoid relying on the old style description via the DT
> clock-output-names, add compatible data describing the flexgen
> outputs clocks for all STiH407/STiH410 and STiH418 SOCs.
> 
> In order to ease transition between the two methods, this commit
> introduce the new compatible without removing the old method.
> Once DTs will be fixed, the method relying on DT clock-output-names
> will be removed from this driver as well as old compatibles.
> 
> Signed-off-by: Alain Volmat <avolmat@me.com>
> ---
> v3: add comments about CLK_IS_CRITICAL reason
>     don't put clk-proc-stfe as CLK_IS_CRITICAL
> v2: add some missing clock as CLK_IS_CRITICAL
> 
>  drivers/clk/st/clk-flexgen.c | 366 +++++++++++++++++++++++++++++++++--
>  1 file changed, 352 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c
> index 55873d4b7603..69711c6c47a4 100644
> --- a/drivers/clk/st/clk-flexgen.c
> +++ b/drivers/clk/st/clk-flexgen.c
> @@ -16,9 +16,16 @@
>  #include <linux/of.h>
>  #include <linux/of_address.h>
>  
> +struct clkgen_clk_out {
> +	const char *name;
> +	unsigned long flags;
> +};
> +
>  struct clkgen_data {
>  	unsigned long flags;
>  	bool mode;
> +	const struct clkgen_clk_out *outputs;
> +	const unsigned int outputs_nb;
>  };
>  
>  struct flexgen {
> @@ -295,6 +302,289 @@ static const struct clkgen_data clkgen_video = {
>  	.mode = 1,
>  };
>  
> +static const struct clkgen_clk_out clkgen_stih407_a0_clk_out[] = {
> +	/* This clk needs to be on so that memory interface is accessible */
> +	{ .name = "clk-ic-lmi0", .flags = CLK_IS_CRITICAL },
> +};
> +
> +static const struct clkgen_data clkgen_stih407_a0 = {
> +	.outputs = clkgen_stih407_a0_clk_out,
> +	.outputs_nb = ARRAY_SIZE(clkgen_stih407_a0_clk_out),
> +};
> +
> +static const struct clkgen_clk_out clkgen_stih410_a0_clk_out[] = {
> +	/* Those clks need to be on so that memory interface is accessible */
> +	{ .name = "clk-ic-lmi0", .flags = CLK_IS_CRITICAL },
> +	{ .name = "clk-ic-lmi1", .flags = CLK_IS_CRITICAL },
> +};
> +
> +static const struct clkgen_data clkgen_stih410_a0 = {
> +	.outputs = clkgen_stih410_a0_clk_out,
> +	.outputs_nb = ARRAY_SIZE(clkgen_stih410_a0_clk_out),
> +};
> +
> +static const struct clkgen_clk_out clkgen_stih407_c0_clk_out[] = {
> +	{ .name = "clk-icn-gpu", },
> +	{ .name = "clk-fdma", },
> +	{ .name = "clk-nand", },
> +	{ .name = "clk-hva", },
> +	{ .name = "clk-proc-stfe", },
> +	{ .name = "clk-proc-tp", },
> +	{ .name = "clk-rx-icn-dmu", },
> +	{ .name = "clk-rx-icn-hva", },
> +	/* This clk needs to be on to keep bus interconnect alive */
> +	{ .name = "clk-icn-cpu", .flags = CLK_IS_CRITICAL },
> +	/* This clk needs to be on to keep bus interconnect alive */
> +	{ .name = "clk-tx-icn-dmu", .flags = CLK_IS_CRITICAL },
> +	{ .name = "clk-mmc-0", },
> +	{ .name = "clk-mmc-1", },
> +	{ .name = "clk-jpegdec", },
> +	/* This clk needs to be on to keep A9 running */
> +	{ .name = "clk-ext2fa9", .flags = CLK_IS_CRITICAL },
> +	{ .name = "clk-ic-bdisp-0", },
> +	{ .name = "clk-ic-bdisp-1", },
> +	{ .name = "clk-pp-dmu", },
> +	{ .name = "clk-vid-dmu", },
> +	{ .name = "clk-dss-lpc", },
> +	{ .name = "clk-st231-aud-0", },
> +	{ .name = "clk-st231-gp-1", },
> +	{ .name = "clk-st231-dmu", },
> +	/* This clk needs to be on to keep bus interconnect alive */
> +	{ .name = "clk-icn-lmi", .flags = CLK_IS_CRITICAL },
> +	{ .name = "clk-tx-icn-disp-1", },
> +	/* This clk needs to be on to keep bus interconnect alive */
> +	{ .name = "clk-icn-sbc", .flags = CLK_IS_CRITICAL },
> +	{ .name = "clk-stfe-frc2", },
> +	{ .name = "clk-eth-phy", },
> +	{ .name = "clk-eth-ref-phyclk", },
> +	{ .name = "clk-flash-promip", },
> +	{ .name = "clk-main-disp", },
> +	{ .name = "clk-aux-disp", },
> +	{ .name = "clk-compo-dvp", },
> +};
> +
> +static const struct clkgen_data clkgen_stih407_c0 = {
> +	.outputs = clkgen_stih407_c0_clk_out,
> +	.outputs_nb = ARRAY_SIZE(clkgen_stih407_c0_clk_out),
> +};
> +
> +static const struct clkgen_clk_out clkgen_stih410_c0_clk_out[] = {
> +	{ .name = "clk-icn-gpu", },
> +	{ .name = "clk-fdma", },
> +	{ .name = "clk-nand", },
> +	{ .name = "clk-hva", },
> +	{ .name = "clk-proc-stfe", },
> +	{ .name = "clk-proc-tp", },
> +	{ .name = "clk-rx-icn-dmu", },
> +	{ .name = "clk-rx-icn-hva", },
> +	/* This clk needs to be on to keep bus interconnect alive */
> +	{ .name = "clk-icn-cpu", .flags = CLK_IS_CRITICAL },
> +	/* This clk needs to be on to keep bus interconnect alive */
> +	{ .name = "clk-tx-icn-dmu", .flags = CLK_IS_CRITICAL },
> +	{ .name = "clk-mmc-0", },
> +	{ .name = "clk-mmc-1", },
> +	{ .name = "clk-jpegdec", },
> +	/* This clk needs to be on to keep A9 running */
> +	{ .name = "clk-ext2fa9", .flags = CLK_IS_CRITICAL },
> +	{ .name = "clk-ic-bdisp-0", },
> +	{ .name = "clk-ic-bdisp-1", },
> +	{ .name = "clk-pp-dmu", },
> +	{ .name = "clk-vid-dmu", },
> +	{ .name = "clk-dss-lpc", },
> +	{ .name = "clk-st231-aud-0", },
> +	{ .name = "clk-st231-gp-1", },
> +	{ .name = "clk-st231-dmu", },
> +	/* This clk needs to be on to keep bus interconnect alive */
> +	{ .name = "clk-icn-lmi", .flags = CLK_IS_CRITICAL },
> +	{ .name = "clk-tx-icn-disp-1", },
> +	/* This clk needs to be on to keep bus interconnect alive */
> +	{ .name = "clk-icn-sbc", .flags = CLK_IS_CRITICAL },
> +	{ .name = "clk-stfe-frc2", },
> +	{ .name = "clk-eth-phy", },
> +	{ .name = "clk-eth-ref-phyclk", },
> +	{ .name = "clk-flash-promip", },
> +	{ .name = "clk-main-disp", },
> +	{ .name = "clk-aux-disp", },
> +	{ .name = "clk-compo-dvp", },
> +	{ .name = "clk-tx-icn-hades", },
> +	{ .name = "clk-rx-icn-hades", },
> +	{ .name = "clk-icn-reg-16", },

Need to add CLK_IS_CRITICAL for clk-icn-reg-16
This was a long time bug which is hidden by usage of clk_ignore_unused in bootargs.

With that fix, you can add 

Reviewed-by: Patrice Chotard <patrice.chotard@foss.st.com>

Thanks
Patrice

> +	{ .name = "clk-pp-hades", },
> +	{ .name = "clk-clust-hades", },
> +	{ .name = "clk-hwpe-hades", },
> +	{ .name = "clk-fc-hades", },
> +};
> +
> +static const struct clkgen_data clkgen_stih410_c0 = {
> +	.outputs = clkgen_stih410_c0_clk_out,
> +	.outputs_nb = ARRAY_SIZE(clkgen_stih410_c0_clk_out),
> +};
> +
> +static const struct clkgen_clk_out clkgen_stih418_c0_clk_out[] = {
> +	{ .name = "clk-icn-gpu", },
> +	{ .name = "clk-fdma", },
> +	{ .name = "clk-nand", },
> +	{ .name = "clk-hva", },
> +	{ .name = "clk-proc-stfe", },
> +	{ .name = "clk-tp", },
> +	/* This clk needs to be on to keep bus interconnect alive */
> +	{ .name = "clk-rx-icn-dmu", .flags = CLK_IS_CRITICAL },
> +	/* This clk needs to be on to keep bus interconnect alive */
> +	{ .name = "clk-rx-icn-hva", .flags = CLK_IS_CRITICAL },
> +	{ .name = "clk-icn-cpu", .flags = CLK_IS_CRITICAL },
> +	/* This clk needs to be on to keep bus interconnect alive */
> +	{ .name = "clk-tx-icn-dmu", .flags = CLK_IS_CRITICAL },
> +	{ .name = "clk-mmc-0", },
> +	{ .name = "clk-mmc-1", },
> +	{ .name = "clk-jpegdec", },
> +	/* This clk needs to be on to keep bus interconnect alive */
> +	{ .name = "clk-icn-reg", .flags = CLK_IS_CRITICAL },
> +	{ .name = "clk-proc-bdisp-0", },
> +	{ .name = "clk-proc-bdisp-1", },
> +	{ .name = "clk-pp-dmu", },
> +	{ .name = "clk-vid-dmu", },
> +	{ .name = "clk-dss-lpc", },
> +	{ .name = "clk-st231-aud-0", },
> +	{ .name = "clk-st231-gp-1", },
> +	{ .name = "clk-st231-dmu", },
> +	/* This clk needs to be on to keep bus interconnect alive */
> +	{ .name = "clk-icn-lmi", .flags = CLK_IS_CRITICAL },
> +	/* This clk needs to be on to keep bus interconnect alive */
> +	{ .name = "clk-tx-icn-1", .flags = CLK_IS_CRITICAL },
> +	/* This clk needs to be on to keep bus interconnect alive */
> +	{ .name = "clk-icn-sbc", .flags = CLK_IS_CRITICAL },
> +	{ .name = "clk-stfe-frc2", },
> +	{ .name = "clk-eth-phyref", },
> +	{ .name = "clk-eth-ref-phyclk", },
> +	{ .name = "clk-flash-promip", },
> +	{ .name = "clk-main-disp", },
> +	{ .name = "clk-aux-disp", },
> +	{ .name = "clk-compo-dvp", },
> +	/* This clk needs to be on to keep bus interconnect alive */
> +	{ .name = "clk-tx-icn-hades", .flags = CLK_IS_CRITICAL },
> +	/* This clk needs to be on to keep bus interconnect alive */
> +	{ .name = "clk-rx-icn-hades", .flags = CLK_IS_CRITICAL },
> +	/* This clk needs to be on to keep bus interconnect alive */
> +	{ .name = "clk-icn-reg-16", .flags = CLK_IS_CRITICAL },
> +	{ .name = "clk-pp-hevc", },
> +	{ .name = "clk-clust-hevc", },
> +	{ .name = "clk-hwpe-hevc", },
> +	{ .name = "clk-fc-hevc", },
> +	{ .name = "clk-proc-mixer", },
> +	{ .name = "clk-proc-sc", },
> +	{ .name = "clk-avsp-hevc", },
> +};
> +
> +static const struct clkgen_data clkgen_stih418_c0 = {
> +	.outputs = clkgen_stih418_c0_clk_out,
> +	.outputs_nb = ARRAY_SIZE(clkgen_stih418_c0_clk_out),
> +};
> +
> +static const struct clkgen_clk_out clkgen_stih407_d0_clk_out[] = {
> +	{ .name = "clk-pcm-0", },
> +	{ .name = "clk-pcm-1", },
> +	{ .name = "clk-pcm-2", },
> +	{ .name = "clk-spdiff", },
> +};
> +
> +static const struct clkgen_data clkgen_stih407_d0 = {
> +	.flags = CLK_SET_RATE_PARENT,
> +	.outputs = clkgen_stih407_d0_clk_out,
> +	.outputs_nb = ARRAY_SIZE(clkgen_stih407_d0_clk_out),
> +};
> +
> +static const struct clkgen_clk_out clkgen_stih410_d0_clk_out[] = {
> +	{ .name = "clk-pcm-0", },
> +	{ .name = "clk-pcm-1", },
> +	{ .name = "clk-pcm-2", },
> +	{ .name = "clk-spdiff", },
> +	{ .name = "clk-pcmr10-master", },
> +	{ .name = "clk-usb2-phy", },
> +};
> +
> +static const struct clkgen_data clkgen_stih410_d0 = {
> +	.flags = CLK_SET_RATE_PARENT,
> +	.outputs = clkgen_stih410_d0_clk_out,
> +	.outputs_nb = ARRAY_SIZE(clkgen_stih410_d0_clk_out),
> +};
> +
> +static const struct clkgen_clk_out clkgen_stih407_d2_clk_out[] = {
> +	{ .name = "clk-pix-main-disp", },
> +	{ .name = "clk-pix-pip", },
> +	{ .name = "clk-pix-gdp1", },
> +	{ .name = "clk-pix-gdp2", },
> +	{ .name = "clk-pix-gdp3", },
> +	{ .name = "clk-pix-gdp4", },
> +	{ .name = "clk-pix-aux-disp", },
> +	{ .name = "clk-denc", },
> +	{ .name = "clk-pix-hddac", },
> +	{ .name = "clk-hddac", },
> +	{ .name = "clk-sddac", },
> +	{ .name = "clk-pix-dvo", },
> +	{ .name = "clk-dvo", },
> +	{ .name = "clk-pix-hdmi", },
> +	{ .name = "clk-tmds-hdmi", },
> +	{ .name = "clk-ref-hdmiphy", },
> +};
> +
> +static const struct clkgen_data clkgen_stih407_d2 = {
> +	.outputs = clkgen_stih407_d2_clk_out,
> +	.outputs_nb = ARRAY_SIZE(clkgen_stih407_d2_clk_out),
> +	.flags = CLK_SET_RATE_PARENT,
> +	.mode = 1,
> +};
> +
> +static const struct clkgen_clk_out clkgen_stih418_d2_clk_out[] = {
> +	{ .name = "clk-pix-main-disp", },
> +	{ .name = "", },
> +	{ .name = "", },
> +	{ .name = "", },
> +	{ .name = "", },
> +	{ .name = "clk-tmds-hdmi-div2", },
> +	{ .name = "clk-pix-aux-disp", },
> +	{ .name = "clk-denc", },
> +	{ .name = "clk-pix-hddac", },
> +	{ .name = "clk-hddac", },
> +	{ .name = "clk-sddac", },
> +	{ .name = "clk-pix-dvo", },
> +	{ .name = "clk-dvo", },
> +	{ .name = "clk-pix-hdmi", },
> +	{ .name = "clk-tmds-hdmi", },
> +	{ .name = "clk-ref-hdmiphy", },
> +	{ .name = "", }, { .name = "", }, { .name = "", }, { .name = "", },
> +	{ .name = "", }, { .name = "", }, { .name = "", }, { .name = "", },
> +	{ .name = "", }, { .name = "", }, { .name = "", }, { .name = "", },
> +	{ .name = "", }, { .name = "", }, { .name = "", }, { .name = "", },
> +	{ .name = "", }, { .name = "", }, { .name = "", }, { .name = "", },
> +	{ .name = "", }, { .name = "", }, { .name = "", }, { .name = "", },
> +	{ .name = "", }, { .name = "", }, { .name = "", }, { .name = "", },
> +	{ .name = "", }, { .name = "", }, { .name = "", },
> +	{ .name = "clk-vp9", },
> +};
> +
> +static const struct clkgen_data clkgen_stih418_d2 = {
> +	.outputs = clkgen_stih418_d2_clk_out,
> +	.outputs_nb = ARRAY_SIZE(clkgen_stih418_d2_clk_out),
> +	.flags = CLK_SET_RATE_PARENT,
> +	.mode = 1,
> +};
> +
> +static const struct clkgen_clk_out clkgen_stih407_d3_clk_out[] = {
> +	{ .name = "clk-stfe-frc1", },
> +	{ .name = "clk-tsout-0", },
> +	{ .name = "clk-tsout-1", },
> +	{ .name = "clk-mchi", },
> +	{ .name = "clk-vsens-compo", },
> +	{ .name = "clk-frc1-remote", },
> +	{ .name = "clk-lpc-0", },
> +	{ .name = "clk-lpc-1", },
> +};
> +
> +static const struct clkgen_data clkgen_stih407_d3 = {
> +	.outputs = clkgen_stih407_d3_clk_out,
> +	.outputs_nb = ARRAY_SIZE(clkgen_stih407_d3_clk_out),
> +};
> +
>  static const struct of_device_id flexgen_of_match[] = {
>  	{
>  		.compatible = "st,flexgen-audio",
> @@ -304,6 +594,46 @@ static const struct of_device_id flexgen_of_match[] = {
>  		.compatible = "st,flexgen-video",
>  		.data = &clkgen_video,
>  	},
> +	{
> +		.compatible = "st,flexgen-stih407-a0",
> +		.data = &clkgen_stih407_a0,
> +	},
> +	{
> +		.compatible = "st,flexgen-stih410-a0",
> +		.data = &clkgen_stih410_a0,
> +	},
> +	{
> +		.compatible = "st,flexgen-stih407-c0",
> +		.data = &clkgen_stih407_c0,
> +	},
> +	{
> +		.compatible = "st,flexgen-stih410-c0",
> +		.data = &clkgen_stih410_c0,
> +	},
> +	{
> +		.compatible = "st,flexgen-stih418-c0",
> +		.data = &clkgen_stih418_c0,
> +	},
> +	{
> +		.compatible = "st,flexgen-stih407-d0",
> +		.data = &clkgen_stih407_d0,
> +	},
> +	{
> +		.compatible = "st,flexgen-stih410-d0",
> +		.data = &clkgen_stih410_d0,
> +	},
> +	{
> +		.compatible = "st,flexgen-stih407-d2",
> +		.data = &clkgen_stih407_d2,
> +	},
> +	{
> +		.compatible = "st,flexgen-stih418-d2",
> +		.data = &clkgen_stih418_d2,
> +	},
> +	{
> +		.compatible = "st,flexgen-stih407-d3",
> +		.data = &clkgen_stih407_d3,
> +	},
>  	{}
>  };
>  
> @@ -320,6 +650,7 @@ static void __init st_of_flexgen_setup(struct device_node *np)
>  	unsigned long flex_flags = 0;
>  	int ret;
>  	bool clk_mode = 0;
> +	const char *clk_name;
>  
>  	pnode = of_get_parent(np);
>  	if (!pnode)
> @@ -347,13 +678,17 @@ static void __init st_of_flexgen_setup(struct device_node *np)
>  	if (!clk_data)
>  		goto err;
>  
> -	ret = of_property_count_strings(np, "clock-output-names");
> -	if (ret <= 0) {
> -		pr_err("%s: Failed to get number of output clocks (%d)",
> -				__func__, clk_data->clk_num);
> -		goto err;
> -	}
> -	clk_data->clk_num = ret;
> +	/* First try to get output information from the compatible data */
> +	if (!data || !data->outputs_nb || !data->outputs) {
> +		ret = of_property_count_strings(np, "clock-output-names");
> +		if (ret <= 0) {
> +			pr_err("%s: Failed to get number of output clocks (%d)",
> +					__func__, clk_data->clk_num);
> +			goto err;
> +		}
> +		clk_data->clk_num = ret;
> +	} else
> +		clk_data->clk_num = data->outputs_nb;
>  
>  	clk_data->clks = kcalloc(clk_data->clk_num, sizeof(struct clk *),
>  			GFP_KERNEL);
> @@ -368,16 +703,19 @@ static void __init st_of_flexgen_setup(struct device_node *np)
>  
>  	for (i = 0; i < clk_data->clk_num; i++) {
>  		struct clk *clk;
> -		const char *clk_name;
>  
> -		if (of_property_read_string_index(np, "clock-output-names",
> -						  i, &clk_name)) {
> -			break;
> +		if (!data || !data->outputs_nb || !data->outputs) {
> +			if (of_property_read_string_index(np,
> +							  "clock-output-names",
> +							  i, &clk_name))
> +				break;
> +			flex_flags &= ~CLK_IS_CRITICAL;
> +			of_clk_detect_critical(np, i, &flex_flags);
> +		} else {
> +			clk_name = data->outputs[i].name;
> +			flex_flags = data->flags | data->outputs[i].flags;
>  		}
>  
> -		flex_flags &= ~CLK_IS_CRITICAL;
> -		of_clk_detect_critical(np, i, &flex_flags);
> -
>  		/*
>  		 * If we read an empty clock name then the output is unused
>  		 */
>
diff mbox series

Patch

diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c
index 55873d4b7603..69711c6c47a4 100644
--- a/drivers/clk/st/clk-flexgen.c
+++ b/drivers/clk/st/clk-flexgen.c
@@ -16,9 +16,16 @@ 
 #include <linux/of.h>
 #include <linux/of_address.h>
 
+struct clkgen_clk_out {
+	const char *name;
+	unsigned long flags;
+};
+
 struct clkgen_data {
 	unsigned long flags;
 	bool mode;
+	const struct clkgen_clk_out *outputs;
+	const unsigned int outputs_nb;
 };
 
 struct flexgen {
@@ -295,6 +302,289 @@  static const struct clkgen_data clkgen_video = {
 	.mode = 1,
 };
 
+static const struct clkgen_clk_out clkgen_stih407_a0_clk_out[] = {
+	/* This clk needs to be on so that memory interface is accessible */
+	{ .name = "clk-ic-lmi0", .flags = CLK_IS_CRITICAL },
+};
+
+static const struct clkgen_data clkgen_stih407_a0 = {
+	.outputs = clkgen_stih407_a0_clk_out,
+	.outputs_nb = ARRAY_SIZE(clkgen_stih407_a0_clk_out),
+};
+
+static const struct clkgen_clk_out clkgen_stih410_a0_clk_out[] = {
+	/* Those clks need to be on so that memory interface is accessible */
+	{ .name = "clk-ic-lmi0", .flags = CLK_IS_CRITICAL },
+	{ .name = "clk-ic-lmi1", .flags = CLK_IS_CRITICAL },
+};
+
+static const struct clkgen_data clkgen_stih410_a0 = {
+	.outputs = clkgen_stih410_a0_clk_out,
+	.outputs_nb = ARRAY_SIZE(clkgen_stih410_a0_clk_out),
+};
+
+static const struct clkgen_clk_out clkgen_stih407_c0_clk_out[] = {
+	{ .name = "clk-icn-gpu", },
+	{ .name = "clk-fdma", },
+	{ .name = "clk-nand", },
+	{ .name = "clk-hva", },
+	{ .name = "clk-proc-stfe", },
+	{ .name = "clk-proc-tp", },
+	{ .name = "clk-rx-icn-dmu", },
+	{ .name = "clk-rx-icn-hva", },
+	/* This clk needs to be on to keep bus interconnect alive */
+	{ .name = "clk-icn-cpu", .flags = CLK_IS_CRITICAL },
+	/* This clk needs to be on to keep bus interconnect alive */
+	{ .name = "clk-tx-icn-dmu", .flags = CLK_IS_CRITICAL },
+	{ .name = "clk-mmc-0", },
+	{ .name = "clk-mmc-1", },
+	{ .name = "clk-jpegdec", },
+	/* This clk needs to be on to keep A9 running */
+	{ .name = "clk-ext2fa9", .flags = CLK_IS_CRITICAL },
+	{ .name = "clk-ic-bdisp-0", },
+	{ .name = "clk-ic-bdisp-1", },
+	{ .name = "clk-pp-dmu", },
+	{ .name = "clk-vid-dmu", },
+	{ .name = "clk-dss-lpc", },
+	{ .name = "clk-st231-aud-0", },
+	{ .name = "clk-st231-gp-1", },
+	{ .name = "clk-st231-dmu", },
+	/* This clk needs to be on to keep bus interconnect alive */
+	{ .name = "clk-icn-lmi", .flags = CLK_IS_CRITICAL },
+	{ .name = "clk-tx-icn-disp-1", },
+	/* This clk needs to be on to keep bus interconnect alive */
+	{ .name = "clk-icn-sbc", .flags = CLK_IS_CRITICAL },
+	{ .name = "clk-stfe-frc2", },
+	{ .name = "clk-eth-phy", },
+	{ .name = "clk-eth-ref-phyclk", },
+	{ .name = "clk-flash-promip", },
+	{ .name = "clk-main-disp", },
+	{ .name = "clk-aux-disp", },
+	{ .name = "clk-compo-dvp", },
+};
+
+static const struct clkgen_data clkgen_stih407_c0 = {
+	.outputs = clkgen_stih407_c0_clk_out,
+	.outputs_nb = ARRAY_SIZE(clkgen_stih407_c0_clk_out),
+};
+
+static const struct clkgen_clk_out clkgen_stih410_c0_clk_out[] = {
+	{ .name = "clk-icn-gpu", },
+	{ .name = "clk-fdma", },
+	{ .name = "clk-nand", },
+	{ .name = "clk-hva", },
+	{ .name = "clk-proc-stfe", },
+	{ .name = "clk-proc-tp", },
+	{ .name = "clk-rx-icn-dmu", },
+	{ .name = "clk-rx-icn-hva", },
+	/* This clk needs to be on to keep bus interconnect alive */
+	{ .name = "clk-icn-cpu", .flags = CLK_IS_CRITICAL },
+	/* This clk needs to be on to keep bus interconnect alive */
+	{ .name = "clk-tx-icn-dmu", .flags = CLK_IS_CRITICAL },
+	{ .name = "clk-mmc-0", },
+	{ .name = "clk-mmc-1", },
+	{ .name = "clk-jpegdec", },
+	/* This clk needs to be on to keep A9 running */
+	{ .name = "clk-ext2fa9", .flags = CLK_IS_CRITICAL },
+	{ .name = "clk-ic-bdisp-0", },
+	{ .name = "clk-ic-bdisp-1", },
+	{ .name = "clk-pp-dmu", },
+	{ .name = "clk-vid-dmu", },
+	{ .name = "clk-dss-lpc", },
+	{ .name = "clk-st231-aud-0", },
+	{ .name = "clk-st231-gp-1", },
+	{ .name = "clk-st231-dmu", },
+	/* This clk needs to be on to keep bus interconnect alive */
+	{ .name = "clk-icn-lmi", .flags = CLK_IS_CRITICAL },
+	{ .name = "clk-tx-icn-disp-1", },
+	/* This clk needs to be on to keep bus interconnect alive */
+	{ .name = "clk-icn-sbc", .flags = CLK_IS_CRITICAL },
+	{ .name = "clk-stfe-frc2", },
+	{ .name = "clk-eth-phy", },
+	{ .name = "clk-eth-ref-phyclk", },
+	{ .name = "clk-flash-promip", },
+	{ .name = "clk-main-disp", },
+	{ .name = "clk-aux-disp", },
+	{ .name = "clk-compo-dvp", },
+	{ .name = "clk-tx-icn-hades", },
+	{ .name = "clk-rx-icn-hades", },
+	{ .name = "clk-icn-reg-16", },
+	{ .name = "clk-pp-hades", },
+	{ .name = "clk-clust-hades", },
+	{ .name = "clk-hwpe-hades", },
+	{ .name = "clk-fc-hades", },
+};
+
+static const struct clkgen_data clkgen_stih410_c0 = {
+	.outputs = clkgen_stih410_c0_clk_out,
+	.outputs_nb = ARRAY_SIZE(clkgen_stih410_c0_clk_out),
+};
+
+static const struct clkgen_clk_out clkgen_stih418_c0_clk_out[] = {
+	{ .name = "clk-icn-gpu", },
+	{ .name = "clk-fdma", },
+	{ .name = "clk-nand", },
+	{ .name = "clk-hva", },
+	{ .name = "clk-proc-stfe", },
+	{ .name = "clk-tp", },
+	/* This clk needs to be on to keep bus interconnect alive */
+	{ .name = "clk-rx-icn-dmu", .flags = CLK_IS_CRITICAL },
+	/* This clk needs to be on to keep bus interconnect alive */
+	{ .name = "clk-rx-icn-hva", .flags = CLK_IS_CRITICAL },
+	{ .name = "clk-icn-cpu", .flags = CLK_IS_CRITICAL },
+	/* This clk needs to be on to keep bus interconnect alive */
+	{ .name = "clk-tx-icn-dmu", .flags = CLK_IS_CRITICAL },
+	{ .name = "clk-mmc-0", },
+	{ .name = "clk-mmc-1", },
+	{ .name = "clk-jpegdec", },
+	/* This clk needs to be on to keep bus interconnect alive */
+	{ .name = "clk-icn-reg", .flags = CLK_IS_CRITICAL },
+	{ .name = "clk-proc-bdisp-0", },
+	{ .name = "clk-proc-bdisp-1", },
+	{ .name = "clk-pp-dmu", },
+	{ .name = "clk-vid-dmu", },
+	{ .name = "clk-dss-lpc", },
+	{ .name = "clk-st231-aud-0", },
+	{ .name = "clk-st231-gp-1", },
+	{ .name = "clk-st231-dmu", },
+	/* This clk needs to be on to keep bus interconnect alive */
+	{ .name = "clk-icn-lmi", .flags = CLK_IS_CRITICAL },
+	/* This clk needs to be on to keep bus interconnect alive */
+	{ .name = "clk-tx-icn-1", .flags = CLK_IS_CRITICAL },
+	/* This clk needs to be on to keep bus interconnect alive */
+	{ .name = "clk-icn-sbc", .flags = CLK_IS_CRITICAL },
+	{ .name = "clk-stfe-frc2", },
+	{ .name = "clk-eth-phyref", },
+	{ .name = "clk-eth-ref-phyclk", },
+	{ .name = "clk-flash-promip", },
+	{ .name = "clk-main-disp", },
+	{ .name = "clk-aux-disp", },
+	{ .name = "clk-compo-dvp", },
+	/* This clk needs to be on to keep bus interconnect alive */
+	{ .name = "clk-tx-icn-hades", .flags = CLK_IS_CRITICAL },
+	/* This clk needs to be on to keep bus interconnect alive */
+	{ .name = "clk-rx-icn-hades", .flags = CLK_IS_CRITICAL },
+	/* This clk needs to be on to keep bus interconnect alive */
+	{ .name = "clk-icn-reg-16", .flags = CLK_IS_CRITICAL },
+	{ .name = "clk-pp-hevc", },
+	{ .name = "clk-clust-hevc", },
+	{ .name = "clk-hwpe-hevc", },
+	{ .name = "clk-fc-hevc", },
+	{ .name = "clk-proc-mixer", },
+	{ .name = "clk-proc-sc", },
+	{ .name = "clk-avsp-hevc", },
+};
+
+static const struct clkgen_data clkgen_stih418_c0 = {
+	.outputs = clkgen_stih418_c0_clk_out,
+	.outputs_nb = ARRAY_SIZE(clkgen_stih418_c0_clk_out),
+};
+
+static const struct clkgen_clk_out clkgen_stih407_d0_clk_out[] = {
+	{ .name = "clk-pcm-0", },
+	{ .name = "clk-pcm-1", },
+	{ .name = "clk-pcm-2", },
+	{ .name = "clk-spdiff", },
+};
+
+static const struct clkgen_data clkgen_stih407_d0 = {
+	.flags = CLK_SET_RATE_PARENT,
+	.outputs = clkgen_stih407_d0_clk_out,
+	.outputs_nb = ARRAY_SIZE(clkgen_stih407_d0_clk_out),
+};
+
+static const struct clkgen_clk_out clkgen_stih410_d0_clk_out[] = {
+	{ .name = "clk-pcm-0", },
+	{ .name = "clk-pcm-1", },
+	{ .name = "clk-pcm-2", },
+	{ .name = "clk-spdiff", },
+	{ .name = "clk-pcmr10-master", },
+	{ .name = "clk-usb2-phy", },
+};
+
+static const struct clkgen_data clkgen_stih410_d0 = {
+	.flags = CLK_SET_RATE_PARENT,
+	.outputs = clkgen_stih410_d0_clk_out,
+	.outputs_nb = ARRAY_SIZE(clkgen_stih410_d0_clk_out),
+};
+
+static const struct clkgen_clk_out clkgen_stih407_d2_clk_out[] = {
+	{ .name = "clk-pix-main-disp", },
+	{ .name = "clk-pix-pip", },
+	{ .name = "clk-pix-gdp1", },
+	{ .name = "clk-pix-gdp2", },
+	{ .name = "clk-pix-gdp3", },
+	{ .name = "clk-pix-gdp4", },
+	{ .name = "clk-pix-aux-disp", },
+	{ .name = "clk-denc", },
+	{ .name = "clk-pix-hddac", },
+	{ .name = "clk-hddac", },
+	{ .name = "clk-sddac", },
+	{ .name = "clk-pix-dvo", },
+	{ .name = "clk-dvo", },
+	{ .name = "clk-pix-hdmi", },
+	{ .name = "clk-tmds-hdmi", },
+	{ .name = "clk-ref-hdmiphy", },
+};
+
+static const struct clkgen_data clkgen_stih407_d2 = {
+	.outputs = clkgen_stih407_d2_clk_out,
+	.outputs_nb = ARRAY_SIZE(clkgen_stih407_d2_clk_out),
+	.flags = CLK_SET_RATE_PARENT,
+	.mode = 1,
+};
+
+static const struct clkgen_clk_out clkgen_stih418_d2_clk_out[] = {
+	{ .name = "clk-pix-main-disp", },
+	{ .name = "", },
+	{ .name = "", },
+	{ .name = "", },
+	{ .name = "", },
+	{ .name = "clk-tmds-hdmi-div2", },
+	{ .name = "clk-pix-aux-disp", },
+	{ .name = "clk-denc", },
+	{ .name = "clk-pix-hddac", },
+	{ .name = "clk-hddac", },
+	{ .name = "clk-sddac", },
+	{ .name = "clk-pix-dvo", },
+	{ .name = "clk-dvo", },
+	{ .name = "clk-pix-hdmi", },
+	{ .name = "clk-tmds-hdmi", },
+	{ .name = "clk-ref-hdmiphy", },
+	{ .name = "", }, { .name = "", }, { .name = "", }, { .name = "", },
+	{ .name = "", }, { .name = "", }, { .name = "", }, { .name = "", },
+	{ .name = "", }, { .name = "", }, { .name = "", }, { .name = "", },
+	{ .name = "", }, { .name = "", }, { .name = "", }, { .name = "", },
+	{ .name = "", }, { .name = "", }, { .name = "", }, { .name = "", },
+	{ .name = "", }, { .name = "", }, { .name = "", }, { .name = "", },
+	{ .name = "", }, { .name = "", }, { .name = "", }, { .name = "", },
+	{ .name = "", }, { .name = "", }, { .name = "", },
+	{ .name = "clk-vp9", },
+};
+
+static const struct clkgen_data clkgen_stih418_d2 = {
+	.outputs = clkgen_stih418_d2_clk_out,
+	.outputs_nb = ARRAY_SIZE(clkgen_stih418_d2_clk_out),
+	.flags = CLK_SET_RATE_PARENT,
+	.mode = 1,
+};
+
+static const struct clkgen_clk_out clkgen_stih407_d3_clk_out[] = {
+	{ .name = "clk-stfe-frc1", },
+	{ .name = "clk-tsout-0", },
+	{ .name = "clk-tsout-1", },
+	{ .name = "clk-mchi", },
+	{ .name = "clk-vsens-compo", },
+	{ .name = "clk-frc1-remote", },
+	{ .name = "clk-lpc-0", },
+	{ .name = "clk-lpc-1", },
+};
+
+static const struct clkgen_data clkgen_stih407_d3 = {
+	.outputs = clkgen_stih407_d3_clk_out,
+	.outputs_nb = ARRAY_SIZE(clkgen_stih407_d3_clk_out),
+};
+
 static const struct of_device_id flexgen_of_match[] = {
 	{
 		.compatible = "st,flexgen-audio",
@@ -304,6 +594,46 @@  static const struct of_device_id flexgen_of_match[] = {
 		.compatible = "st,flexgen-video",
 		.data = &clkgen_video,
 	},
+	{
+		.compatible = "st,flexgen-stih407-a0",
+		.data = &clkgen_stih407_a0,
+	},
+	{
+		.compatible = "st,flexgen-stih410-a0",
+		.data = &clkgen_stih410_a0,
+	},
+	{
+		.compatible = "st,flexgen-stih407-c0",
+		.data = &clkgen_stih407_c0,
+	},
+	{
+		.compatible = "st,flexgen-stih410-c0",
+		.data = &clkgen_stih410_c0,
+	},
+	{
+		.compatible = "st,flexgen-stih418-c0",
+		.data = &clkgen_stih418_c0,
+	},
+	{
+		.compatible = "st,flexgen-stih407-d0",
+		.data = &clkgen_stih407_d0,
+	},
+	{
+		.compatible = "st,flexgen-stih410-d0",
+		.data = &clkgen_stih410_d0,
+	},
+	{
+		.compatible = "st,flexgen-stih407-d2",
+		.data = &clkgen_stih407_d2,
+	},
+	{
+		.compatible = "st,flexgen-stih418-d2",
+		.data = &clkgen_stih418_d2,
+	},
+	{
+		.compatible = "st,flexgen-stih407-d3",
+		.data = &clkgen_stih407_d3,
+	},
 	{}
 };
 
@@ -320,6 +650,7 @@  static void __init st_of_flexgen_setup(struct device_node *np)
 	unsigned long flex_flags = 0;
 	int ret;
 	bool clk_mode = 0;
+	const char *clk_name;
 
 	pnode = of_get_parent(np);
 	if (!pnode)
@@ -347,13 +678,17 @@  static void __init st_of_flexgen_setup(struct device_node *np)
 	if (!clk_data)
 		goto err;
 
-	ret = of_property_count_strings(np, "clock-output-names");
-	if (ret <= 0) {
-		pr_err("%s: Failed to get number of output clocks (%d)",
-				__func__, clk_data->clk_num);
-		goto err;
-	}
-	clk_data->clk_num = ret;
+	/* First try to get output information from the compatible data */
+	if (!data || !data->outputs_nb || !data->outputs) {
+		ret = of_property_count_strings(np, "clock-output-names");
+		if (ret <= 0) {
+			pr_err("%s: Failed to get number of output clocks (%d)",
+					__func__, clk_data->clk_num);
+			goto err;
+		}
+		clk_data->clk_num = ret;
+	} else
+		clk_data->clk_num = data->outputs_nb;
 
 	clk_data->clks = kcalloc(clk_data->clk_num, sizeof(struct clk *),
 			GFP_KERNEL);
@@ -368,16 +703,19 @@  static void __init st_of_flexgen_setup(struct device_node *np)
 
 	for (i = 0; i < clk_data->clk_num; i++) {
 		struct clk *clk;
-		const char *clk_name;
 
-		if (of_property_read_string_index(np, "clock-output-names",
-						  i, &clk_name)) {
-			break;
+		if (!data || !data->outputs_nb || !data->outputs) {
+			if (of_property_read_string_index(np,
+							  "clock-output-names",
+							  i, &clk_name))
+				break;
+			flex_flags &= ~CLK_IS_CRITICAL;
+			of_clk_detect_critical(np, i, &flex_flags);
+		} else {
+			clk_name = data->outputs[i].name;
+			flex_flags = data->flags | data->outputs[i].flags;
 		}
 
-		flex_flags &= ~CLK_IS_CRITICAL;
-		of_clk_detect_critical(np, i, &flex_flags);
-
 		/*
 		 * If we read an empty clock name then the output is unused
 		 */