summaryrefslogtreecommitdiffstats
path: root/drivers/clk/st
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/st')
-rw-r--r--drivers/clk/st/clk-flexgen.c367
-rw-r--r--drivers/clk/st/clkgen-fsyn.c113
-rw-r--r--drivers/clk/st/clkgen-pll.c121
3 files changed, 560 insertions, 41 deletions
diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c
index 55873d4b7603..7ae4f656191e 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,290 @@ 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", },
+ /* This clk needs to be on to keep bus interconnect alive */
+ { .name = "clk-icn-reg-16", .flags = CLK_IS_CRITICAL },
+ { .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 +595,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 +651,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 +679,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 +704,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 --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c
index dd6062e043e0..164285d6be97 100644
--- a/drivers/clk/st/clkgen-fsyn.c
+++ b/drivers/clk/st/clkgen-fsyn.c
@@ -66,6 +66,16 @@ struct clkgen_quadfs_data {
unsigned long *);
};
+struct clkgen_clk_out {
+ const char *name;
+ unsigned long flags;
+};
+
+struct clkgen_quadfs_data_clks {
+ struct clkgen_quadfs_data *data;
+ const struct clkgen_clk_out *outputs;
+};
+
static const struct clk_ops st_quadfs_pll_c32_ops;
static int clk_fs660c32_dig_get_params(unsigned long input,
@@ -115,6 +125,18 @@ static const struct clkgen_quadfs_data st_fs660c32_C = {
.get_rate = clk_fs660c32_dig_get_rate,
};
+static const struct clkgen_clk_out st_fs660c32_C_clks[] = {
+ { .name = "clk-s-c0-fs0-ch0", },
+ { .name = "clk-s-c0-fs0-ch1", },
+ { .name = "clk-s-c0-fs0-ch2", },
+ { .name = "clk-s-c0-fs0-ch3", },
+};
+
+static const struct clkgen_quadfs_data_clks st_fs660c32_C_data = {
+ .data = (struct clkgen_quadfs_data *)&st_fs660c32_C,
+ .outputs = st_fs660c32_C_clks,
+};
+
static const struct clkgen_quadfs_data st_fs660c32_D = {
.nrst_present = true,
.nrst = { CLKGEN_FIELD(0x2a0, 0x1, 0),
@@ -156,6 +178,46 @@ static const struct clkgen_quadfs_data st_fs660c32_D = {
.get_params = clk_fs660c32_dig_get_params,
.get_rate = clk_fs660c32_dig_get_rate,};
+static const struct clkgen_quadfs_data_clks st_fs660c32_D_data = {
+ .data = (struct clkgen_quadfs_data *)&st_fs660c32_D,
+};
+
+static const struct clkgen_clk_out st_fs660c32_D0_clks[] = {
+ { .name = "clk-s-d0-fs0-ch0", },
+ { .name = "clk-s-d0-fs0-ch1", },
+ { .name = "clk-s-d0-fs0-ch2", },
+ { .name = "clk-s-d0-fs0-ch3", },
+};
+
+static const struct clkgen_quadfs_data_clks st_fs660c32_D0_data = {
+ .data = (struct clkgen_quadfs_data *)&st_fs660c32_D,
+ .outputs = st_fs660c32_D0_clks,
+};
+
+static const struct clkgen_clk_out st_fs660c32_D2_clks[] = {
+ { .name = "clk-s-d2-fs0-ch0", },
+ { .name = "clk-s-d2-fs0-ch1", },
+ { .name = "clk-s-d2-fs0-ch2", },
+ { .name = "clk-s-d2-fs0-ch3", },
+};
+
+static const struct clkgen_quadfs_data_clks st_fs660c32_D2_data = {
+ .data = (struct clkgen_quadfs_data *)&st_fs660c32_D,
+ .outputs = st_fs660c32_D2_clks,
+};
+
+static const struct clkgen_clk_out st_fs660c32_D3_clks[] = {
+ { .name = "clk-s-d3-fs0-ch0", },
+ { .name = "clk-s-d3-fs0-ch1", },
+ { .name = "clk-s-d3-fs0-ch2", },
+ { .name = "clk-s-d3-fs0-ch3", },
+};
+
+static const struct clkgen_quadfs_data_clks st_fs660c32_D3_data = {
+ .data = (struct clkgen_quadfs_data *)&st_fs660c32_D,
+ .outputs = st_fs660c32_D3_clks,
+};
+
/**
* DOC: A Frequency Synthesizer that multiples its input clock by a fixed factor
*
@@ -857,7 +919,7 @@ static struct clk * __init st_clk_register_quadfs_fsynth(
static void __init st_of_create_quadfs_fsynths(
struct device_node *np, const char *pll_name,
- struct clkgen_quadfs_data *quadfs, void __iomem *reg,
+ struct clkgen_quadfs_data_clks *quadfs, void __iomem *reg,
spinlock_t *lock)
{
struct clk_onecell_data *clk_data;
@@ -881,9 +943,15 @@ static void __init st_of_create_quadfs_fsynths(
const char *clk_name;
unsigned long flags = 0;
- if (of_property_read_string_index(np, "clock-output-names",
- fschan, &clk_name)) {
- break;
+ if (quadfs->outputs) {
+ clk_name = quadfs->outputs[fschan].name;
+ flags = quadfs->outputs[fschan].flags;
+ } else {
+ if (of_property_read_string_index(np,
+ "clock-output-names",
+ fschan, &clk_name))
+ break;
+ of_clk_detect_critical(np, fschan, &flags);
}
/*
@@ -892,10 +960,8 @@ static void __init st_of_create_quadfs_fsynths(
if (*clk_name == '\0')
continue;
- of_clk_detect_critical(np, fschan, &flags);
-
clk = st_clk_register_quadfs_fsynth(clk_name, pll_name,
- quadfs, reg, fschan,
+ quadfs->data, reg, fschan,
flags, lock);
/*
@@ -915,7 +981,7 @@ static void __init st_of_create_quadfs_fsynths(
}
static void __init st_of_quadfs_setup(struct device_node *np,
- struct clkgen_quadfs_data *data)
+ struct clkgen_quadfs_data_clks *datac)
{
struct clk *clk;
const char *pll_name, *clk_parent_name;
@@ -940,7 +1006,7 @@ static void __init st_of_quadfs_setup(struct device_node *np,
spin_lock_init(lock);
- clk = st_clk_register_quadfs_pll(pll_name, clk_parent_name, data,
+ clk = st_clk_register_quadfs_pll(pll_name, clk_parent_name, datac->data,
reg, lock);
if (IS_ERR(clk))
goto err_exit;
@@ -950,7 +1016,7 @@ static void __init st_of_quadfs_setup(struct device_node *np,
__clk_get_name(clk_get_parent(clk)),
(unsigned int)clk_get_rate(clk));
- st_of_create_quadfs_fsynths(np, pll_name, data, reg, lock);
+ st_of_create_quadfs_fsynths(np, pll_name, datac, reg, lock);
err_exit:
kfree(pll_name); /* No longer need local copy of the PLL name */
@@ -958,12 +1024,35 @@ err_exit:
static void __init st_of_quadfs660C_setup(struct device_node *np)
{
- st_of_quadfs_setup(np, (struct clkgen_quadfs_data *) &st_fs660c32_C);
+ st_of_quadfs_setup(np,
+ (struct clkgen_quadfs_data_clks *) &st_fs660c32_C_data);
}
CLK_OF_DECLARE(quadfs660C, "st,quadfs-pll", st_of_quadfs660C_setup);
static void __init st_of_quadfs660D_setup(struct device_node *np)
{
- st_of_quadfs_setup(np, (struct clkgen_quadfs_data *) &st_fs660c32_D);
+ st_of_quadfs_setup(np,
+ (struct clkgen_quadfs_data_clks *) &st_fs660c32_D_data);
}
CLK_OF_DECLARE(quadfs660D, "st,quadfs", st_of_quadfs660D_setup);
+
+static void __init st_of_quadfs660D0_setup(struct device_node *np)
+{
+ st_of_quadfs_setup(np,
+ (struct clkgen_quadfs_data_clks *) &st_fs660c32_D0_data);
+}
+CLK_OF_DECLARE(quadfs660D0, "st,quadfs-d0", st_of_quadfs660D0_setup);
+
+static void __init st_of_quadfs660D2_setup(struct device_node *np)
+{
+ st_of_quadfs_setup(np,
+ (struct clkgen_quadfs_data_clks *) &st_fs660c32_D2_data);
+}
+CLK_OF_DECLARE(quadfs660D2, "st,quadfs-d2", st_of_quadfs660D2_setup);
+
+static void __init st_of_quadfs660D3_setup(struct device_node *np)
+{
+ st_of_quadfs_setup(np,
+ (struct clkgen_quadfs_data_clks *) &st_fs660c32_D3_data);
+}
+CLK_OF_DECLARE(quadfs660D3, "st,quadfs-d3", st_of_quadfs660D3_setup);
diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c
index 119c5b33080c..b36e4d803636 100644
--- a/drivers/clk/st/clkgen-pll.c
+++ b/drivers/clk/st/clkgen-pll.c
@@ -57,6 +57,17 @@ struct clkgen_pll_data {
const struct clk_ops *ops;
};
+struct clkgen_clk_out {
+ const char *name;
+ unsigned long flags;
+};
+
+struct clkgen_pll_data_clks {
+ struct clkgen_pll_data *data;
+ const struct clkgen_clk_out *outputs;
+};
+
+
static const struct clk_ops stm_pll3200c32_ops;
static const struct clk_ops stm_pll3200c32_a9_ops;
static const struct clk_ops stm_pll4600c28_ops;
@@ -74,6 +85,28 @@ static const struct clkgen_pll_data st_pll3200c32_cx_0 = {
.ops = &stm_pll3200c32_ops,
};
+static const struct clkgen_pll_data_clks st_pll3200c32_cx_0_legacy_data = {
+ .data = (struct clkgen_pll_data *)&st_pll3200c32_cx_0,
+};
+
+static const struct clkgen_clk_out st_pll3200c32_ax_0_clks[] = {
+ { .name = "clk-s-a0-pll-odf-0", },
+};
+
+static const struct clkgen_pll_data_clks st_pll3200c32_a0_data = {
+ .data = (struct clkgen_pll_data *)&st_pll3200c32_cx_0,
+ .outputs = st_pll3200c32_ax_0_clks,
+};
+
+static const struct clkgen_clk_out st_pll3200c32_cx_0_clks[] = {
+ { .name = "clk-s-c0-pll0-odf-0", },
+};
+
+static const struct clkgen_pll_data_clks st_pll3200c32_c0_data = {
+ .data = (struct clkgen_pll_data *)&st_pll3200c32_cx_0,
+ .outputs = st_pll3200c32_cx_0_clks,
+};
+
static const struct clkgen_pll_data st_pll3200c32_cx_1 = {
/* 407 C0 PLL1 */
.pdn_status = CLKGEN_FIELD(0x2c8, 0x1, 8),
@@ -87,6 +120,19 @@ static const struct clkgen_pll_data st_pll3200c32_cx_1 = {
.ops = &stm_pll3200c32_ops,
};
+static const struct clkgen_pll_data_clks st_pll3200c32_cx_1_legacy_data = {
+ .data = (struct clkgen_pll_data *)&st_pll3200c32_cx_1,
+};
+
+static const struct clkgen_clk_out st_pll3200c32_cx_1_clks[] = {
+ { .name = "clk-s-c0-pll1-odf-0", },
+};
+
+static const struct clkgen_pll_data_clks st_pll3200c32_c1_data = {
+ .data = (struct clkgen_pll_data *)&st_pll3200c32_cx_1,
+ .outputs = st_pll3200c32_cx_1_clks,
+};
+
static const struct clkgen_pll_data st_pll3200c32_407_a9 = {
/* 407 A9 */
.pdn_status = CLKGEN_FIELD(0x1a8, 0x1, 0),
@@ -104,6 +150,15 @@ static const struct clkgen_pll_data st_pll3200c32_407_a9 = {
.ops = &stm_pll3200c32_a9_ops,
};
+static const struct clkgen_clk_out st_pll3200c32_407_a9_clks[] = {
+ { .name = "clockgen-a9-pll-odf", },
+};
+
+static const struct clkgen_pll_data_clks st_pll3200c32_407_a9_data = {
+ .data = (struct clkgen_pll_data *)&st_pll3200c32_407_a9,
+ .outputs = st_pll3200c32_407_a9_clks,
+};
+
static struct clkgen_pll_data st_pll4600c28_418_a9 = {
/* 418 A9 */
.pdn_status = CLKGEN_FIELD(0x1a8, 0x1, 0),
@@ -120,6 +175,15 @@ static struct clkgen_pll_data st_pll4600c28_418_a9 = {
.ops = &stm_pll4600c28_ops,
};
+static const struct clkgen_clk_out st_pll4600c28_418_a9_clks[] = {
+ { .name = "clockgen-a9-pll-odf", },
+};
+
+static const struct clkgen_pll_data_clks st_pll4600c28_418_a9_data = {
+ .data = (struct clkgen_pll_data *)&st_pll4600c28_418_a9,
+ .outputs = st_pll4600c28_418_a9_clks,
+};
+
/**
* DOC: Clock Generated by PLL, rate set and enabled by bootloader
*
@@ -146,7 +210,6 @@ struct clkgen_pll {
u32 ndiv;
u32 idf;
- u32 odf;
u32 cp;
};
@@ -685,7 +748,7 @@ static struct clk * __init clkgen_odf_register(const char *parent_name,
static void __init clkgen_c32_pll_setup(struct device_node *np,
- struct clkgen_pll_data *data)
+ struct clkgen_pll_data_clks *datac)
{
struct clk *clk;
const char *parent_name, *pll_name;
@@ -705,14 +768,14 @@ static void __init clkgen_c32_pll_setup(struct device_node *np,
of_clk_detect_critical(np, 0, &pll_flags);
- clk = clkgen_pll_register(parent_name, data, pll_base, pll_flags,
- np->name, data->lock);
+ clk = clkgen_pll_register(parent_name, datac->data, pll_base, pll_flags,
+ np->name, datac->data->lock);
if (IS_ERR(clk))
return;
pll_name = __clk_get_name(clk);
- num_odfs = data->num_odfs;
+ num_odfs = datac->data->num_odfs;
clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
if (!clk_data)
@@ -730,14 +793,21 @@ static void __init clkgen_c32_pll_setup(struct device_node *np,
const char *clk_name;
unsigned long odf_flags = 0;
- if (of_property_read_string_index(np, "clock-output-names",
- odf, &clk_name))
- return;
+ if (datac->outputs) {
+ clk_name = datac->outputs[odf].name;
+ odf_flags = datac->outputs[odf].flags;
+ } else {
+ if (of_property_read_string_index(np,
+ "clock-output-names",
+ odf, &clk_name))
+ return;
- of_clk_detect_critical(np, odf, &odf_flags);
+ of_clk_detect_critical(np, odf, &odf_flags);
+ }
- clk = clkgen_odf_register(pll_name, pll_base, data, odf_flags,
- odf, &clkgena_c32_odf_lock, clk_name);
+ clk = clkgen_odf_register(pll_name, pll_base, datac->data,
+ odf_flags, odf, &clkgena_c32_odf_lock,
+ clk_name);
if (IS_ERR(clk))
goto err;
@@ -755,27 +825,48 @@ err:
static void __init clkgen_c32_pll0_setup(struct device_node *np)
{
clkgen_c32_pll_setup(np,
- (struct clkgen_pll_data *) &st_pll3200c32_cx_0);
+ (struct clkgen_pll_data_clks *) &st_pll3200c32_cx_0_legacy_data);
}
CLK_OF_DECLARE(c32_pll0, "st,clkgen-pll0", clkgen_c32_pll0_setup);
+static void __init clkgen_c32_pll0_a0_setup(struct device_node *np)
+{
+ clkgen_c32_pll_setup(np,
+ (struct clkgen_pll_data_clks *) &st_pll3200c32_a0_data);
+}
+CLK_OF_DECLARE(c32_pll0_a0, "st,clkgen-pll0-a0", clkgen_c32_pll0_a0_setup);
+
+static void __init clkgen_c32_pll0_c0_setup(struct device_node *np)
+{
+ clkgen_c32_pll_setup(np,
+ (struct clkgen_pll_data_clks *) &st_pll3200c32_c0_data);
+}
+CLK_OF_DECLARE(c32_pll0_c0, "st,clkgen-pll0-c0", clkgen_c32_pll0_c0_setup);
+
static void __init clkgen_c32_pll1_setup(struct device_node *np)
{
clkgen_c32_pll_setup(np,
- (struct clkgen_pll_data *) &st_pll3200c32_cx_1);
+ (struct clkgen_pll_data_clks *) &st_pll3200c32_cx_1_legacy_data);
}
CLK_OF_DECLARE(c32_pll1, "st,clkgen-pll1", clkgen_c32_pll1_setup);
+static void __init clkgen_c32_pll1_c0_setup(struct device_node *np)
+{
+ clkgen_c32_pll_setup(np,
+ (struct clkgen_pll_data_clks *) &st_pll3200c32_c1_data);
+}
+CLK_OF_DECLARE(c32_pll1_c0, "st,clkgen-pll1-c0", clkgen_c32_pll1_c0_setup);
+
static void __init clkgen_c32_plla9_setup(struct device_node *np)
{
clkgen_c32_pll_setup(np,
- (struct clkgen_pll_data *) &st_pll3200c32_407_a9);
+ (struct clkgen_pll_data_clks *) &st_pll3200c32_407_a9_data);
}
CLK_OF_DECLARE(c32_plla9, "st,stih407-clkgen-plla9", clkgen_c32_plla9_setup);
static void __init clkgen_c28_plla9_setup(struct device_node *np)
{
clkgen_c32_pll_setup(np,
- (struct clkgen_pll_data *) &st_pll4600c28_418_a9);
+ (struct clkgen_pll_data_clks *) &st_pll4600c28_418_a9_data);
}
CLK_OF_DECLARE(c28_plla9, "st,stih418-clkgen-plla9", clkgen_c28_plla9_setup);