These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / clk / st / clkgen-mux.c
index ef65146..5dc5ce2 100644 (file)
@@ -15,7 +15,9 @@
 
 #include <linux/slab.h>
 #include <linux/of_address.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include "clkgen.h"
 
 static DEFINE_SPINLOCK(clkgena_divmux_lock);
 static DEFINE_SPINLOCK(clkgenf_lock);
@@ -24,20 +26,17 @@ static const char ** __init clkgen_mux_get_parents(struct device_node *np,
                                                       int *num_parents)
 {
        const char **parents;
-       int nparents, i;
+       int nparents;
 
-       nparents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+       nparents = of_clk_get_parent_count(np);
        if (WARN_ON(nparents <= 0))
                return ERR_PTR(-EINVAL);
 
-       parents = kzalloc(nparents * sizeof(const char *), GFP_KERNEL);
+       parents = kcalloc(nparents, sizeof(const char *), GFP_KERNEL);
        if (!parents)
                return ERR_PTR(-ENOMEM);
 
-       for (i = 0; i < nparents; i++)
-               parents[i] = of_clk_get_parent_name(np, i);
-
-       *num_parents = nparents;
+       *num_parents = of_clk_parent_fill(np, parents, nparents);
        return parents;
 }
 
@@ -131,7 +130,7 @@ static int clkgena_divmux_is_enabled(struct clk_hw *hw)
        return (s8)clk_mux_ops.get_parent(mux_hw) > 0;
 }
 
-u8 clkgena_divmux_get_parent(struct clk_hw *hw)
+static u8 clkgena_divmux_get_parent(struct clk_hw *hw)
 {
        struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
        struct clk_hw *mux_hw = &genamux->mux.hw;
@@ -141,7 +140,7 @@ u8 clkgena_divmux_get_parent(struct clk_hw *hw)
        genamux->muxsel = clk_mux_ops.get_parent(mux_hw);
        if ((s8)genamux->muxsel < 0) {
                pr_debug("%s: %s: Invalid parent, setting to default.\n",
-                     __func__, __clk_get_name(hw->clk));
+                     __func__, clk_hw_get_name(hw));
                genamux->muxsel = 0;
        }
 
@@ -168,7 +167,7 @@ static int clkgena_divmux_set_parent(struct clk_hw *hw, u8 index)
        return 0;
 }
 
-unsigned long clkgena_divmux_recalc_rate(struct clk_hw *hw,
+static unsigned long clkgena_divmux_recalc_rate(struct clk_hw *hw,
                unsigned long parent_rate)
 {
        struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
@@ -215,7 +214,7 @@ static const struct clk_ops clkgena_divmux_ops = {
 /**
  * clk_register_genamux - register a genamux clock with the clock framework
  */
-struct clk *clk_register_genamux(const char *name,
+static struct clk * __init clk_register_genamux(const char *name,
                                const char **parent_names, u8 num_parents,
                                void __iomem *reg,
                                const struct clkgena_divmux_data *muxdata,
@@ -237,7 +236,7 @@ struct clk *clk_register_genamux(const char *name,
 
        init.name = name;
        init.ops = &clkgena_divmux_ops;
-       init.flags = CLK_IS_BASIC;
+       init.flags = CLK_IS_BASIC | CLK_GET_RATE_NOCACHE;
        init.parent_names = parent_names;
        init.num_parents = num_parents;
 
@@ -369,11 +368,10 @@ static const struct of_device_id clkgena_divmux_of_match[] = {
        {}
 };
 
-static void __iomem * __init clkgen_get_register_base(
-                               struct device_node *np)
+static void __iomem * __init clkgen_get_register_base(struct device_node *np)
 {
        struct device_node *pnode;
-       void __iomem *reg = NULL;
+       void __iomem *reg;
 
        pnode = of_get_parent(np);
        if (!pnode)
@@ -385,7 +383,7 @@ static void __iomem * __init clkgen_get_register_base(
        return reg;
 }
 
-void __init st_of_clkgena_divmux_setup(struct device_node *np)
+static void __init st_of_clkgena_divmux_setup(struct device_node *np)
 {
        const struct of_device_id *match;
        const struct clkgena_divmux_data *data;
@@ -398,7 +396,7 @@ void __init st_of_clkgena_divmux_setup(struct device_node *np)
        if (WARN_ON(!match))
                return;
 
-       data = (struct clkgena_divmux_data *)match->data;
+       data = match->data;
 
        reg = clkgen_get_register_base(np);
        if (!reg)
@@ -406,18 +404,18 @@ void __init st_of_clkgena_divmux_setup(struct device_node *np)
 
        parents = clkgen_mux_get_parents(np, &num_parents);
        if (IS_ERR(parents))
-               return;
+               goto err_parents;
 
        clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
        if (!clk_data)
-               goto err;
+               goto err_alloc;
 
        clk_data->clk_num = data->num_outputs;
-       clk_data->clks = kzalloc(clk_data->clk_num * sizeof(struct clk *),
+       clk_data->clks = kcalloc(clk_data->clk_num, sizeof(struct clk *),
                                 GFP_KERNEL);
 
        if (!clk_data->clks)
-               goto err;
+               goto err_alloc_clks;
 
        for (i = 0; i < clk_data->clk_num; i++) {
                struct clk *clk;
@@ -447,11 +445,13 @@ void __init st_of_clkgena_divmux_setup(struct device_node *np)
        of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
        return;
 err:
-       if (clk_data)
-               kfree(clk_data->clks);
-
+       kfree(clk_data->clks);
+err_alloc_clks:
        kfree(clk_data);
+err_alloc:
        kfree(parents);
+err_parents:
+       iounmap(reg);
 }
 CLK_OF_DECLARE(clkgenadivmux, "st,clkgena-divmux", st_of_clkgena_divmux_setup);
 
@@ -485,13 +485,13 @@ static const struct of_device_id clkgena_prediv_of_match[] = {
        {}
 };
 
-void __init st_of_clkgena_prediv_setup(struct device_node *np)
+static void __init st_of_clkgena_prediv_setup(struct device_node *np)
 {
        const struct of_device_id *match;
        void __iomem *reg;
        const char *parent_name, *clk_name;
        struct clk *clk;
-       struct clkgena_prediv_data *data;
+       const struct clkgena_prediv_data *data;
 
        match = of_match_node(clkgena_prediv_of_match, np);
        if (!match) {
@@ -499,7 +499,7 @@ void __init st_of_clkgena_prediv_setup(struct device_node *np)
                return;
        }
 
-       data = (struct clkgena_prediv_data *)match->data;
+       data = match->data;
 
        reg = clkgen_get_register_base(np);
        if (!reg)
@@ -507,17 +507,18 @@ void __init st_of_clkgena_prediv_setup(struct device_node *np)
 
        parent_name = of_clk_get_parent_name(np, 0);
        if (!parent_name)
-               return;
+               goto err;
 
        if (of_property_read_string_index(np, "clock-output-names",
                                          0, &clk_name))
-               return;
+               goto err;
 
-       clk = clk_register_divider_table(NULL, clk_name, parent_name, 0,
+       clk = clk_register_divider_table(NULL, clk_name, parent_name,
+                                        CLK_GET_RATE_NOCACHE,
                                         reg + data->offset, data->shift, 1,
                                         0, data->table, NULL);
        if (IS_ERR(clk))
-               return;
+               goto err;
 
        of_clk_add_provider(np, of_clk_src_simple_get, clk);
        pr_debug("%s: parent %s rate %u\n",
@@ -526,6 +527,8 @@ void __init st_of_clkgena_prediv_setup(struct device_node *np)
                (unsigned int)clk_get_rate(clk));
 
        return;
+err:
+       iounmap(reg);
 }
 CLK_OF_DECLARE(clkgenaprediv, "st,clkgena-prediv", st_of_clkgena_prediv_setup);
 
@@ -574,6 +577,7 @@ static struct clkgen_mux_data stih415_a9_mux_data = {
        .offset = 0,
        .shift = 1,
        .width = 2,
+       .lock = &clkgen_a9_lock,
 };
 static struct clkgen_mux_data stih416_a9_mux_data = {
        .offset = 0,
@@ -584,6 +588,7 @@ static struct clkgen_mux_data stih407_a9_mux_data = {
        .offset = 0x1a4,
        .shift = 0,
        .width = 2,
+       .lock = &clkgen_a9_lock,
 };
 
 static const struct of_device_id mux_of_match[] = {
@@ -622,14 +627,14 @@ static const struct of_device_id mux_of_match[] = {
        {}
 };
 
-void __init st_of_clkgen_mux_setup(struct device_node *np)
+static void __init st_of_clkgen_mux_setup(struct device_node *np)
 {
        const struct of_device_id *match;
        struct clk *clk;
        void __iomem *reg;
        const char **parents;
        int num_parents;
-       struct clkgen_mux_data *data;
+       const struct clkgen_mux_data *data;
 
        match = of_match_node(mux_of_match, np);
        if (!match) {
@@ -637,7 +642,7 @@ void __init st_of_clkgen_mux_setup(struct device_node *np)
                return;
        }
 
-       data = (struct clkgen_mux_data *)match->data;
+       data = match->data;
 
        reg = of_iomap(np, 0);
        if (!reg) {
@@ -649,7 +654,7 @@ void __init st_of_clkgen_mux_setup(struct device_node *np)
        if (IS_ERR(parents)) {
                pr_err("%s: Failed to get parents (%ld)\n",
                                __func__, PTR_ERR(parents));
-               return;
+               goto err_parents;
        }
 
        clk = clk_register_mux(NULL, np->name, parents, num_parents,
@@ -665,12 +670,14 @@ void __init st_of_clkgen_mux_setup(struct device_node *np)
                        __clk_get_name(clk_get_parent(clk)),
                        (unsigned int)clk_get_rate(clk));
 
+       kfree(parents);
        of_clk_add_provider(np, of_clk_src_simple_get, clk);
+       return;
 
 err:
        kfree(parents);
-
-       return;
+err_parents:
+       iounmap(reg);
 }
 CLK_OF_DECLARE(clkgen_mux, "st,clkgen-mux", st_of_clkgen_mux_setup);
 
@@ -699,19 +706,19 @@ static const struct of_device_id vcc_of_match[] = {
        {}
 };
 
-void __init st_of_clkgen_vcc_setup(struct device_node *np)
+static void __init st_of_clkgen_vcc_setup(struct device_node *np)
 {
        const struct of_device_id *match;
        void __iomem *reg;
        const char **parents;
        int num_parents, i;
        struct clk_onecell_data *clk_data;
-       struct clkgen_vcc_data *data;
+       const struct clkgen_vcc_data *data;
 
        match = of_match_node(vcc_of_match, np);
        if (WARN_ON(!match))
                return;
-       data = (struct clkgen_vcc_data *)match->data;
+       data = match->data;
 
        reg = of_iomap(np, 0);
        if (!reg)
@@ -719,18 +726,18 @@ void __init st_of_clkgen_vcc_setup(struct device_node *np)
 
        parents = clkgen_mux_get_parents(np, &num_parents);
        if (IS_ERR(parents))
-               return;
+               goto err_parents;
 
        clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
        if (!clk_data)
-               goto err;
+               goto err_alloc;
 
        clk_data->clk_num = VCC_MAX_CHANNELS;
-       clk_data->clks = kzalloc(clk_data->clk_num * sizeof(struct clk *),
+       clk_data->clks = kcalloc(clk_data->clk_num, sizeof(struct clk *),
                                 GFP_KERNEL);
 
        if (!clk_data->clks)
-               goto err;
+               goto err_alloc_clks;
 
        for (i = 0; i < clk_data->clk_num; i++) {
                struct clk *clk;
@@ -749,21 +756,21 @@ void __init st_of_clkgen_vcc_setup(struct device_node *np)
                if (*clk_name == '\0')
                        continue;
 
-               gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
+               gate = kzalloc(sizeof(*gate), GFP_KERNEL);
                if (!gate)
-                       break;
+                       goto err;
 
-               div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
+               div = kzalloc(sizeof(*div), GFP_KERNEL);
                if (!div) {
                        kfree(gate);
-                       break;
+                       goto err;
                }
 
-               mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
+               mux = kzalloc(sizeof(*mux), GFP_KERNEL);
                if (!mux) {
                        kfree(gate);
                        kfree(div);
-                       break;
+                       goto err;
                }
 
                gate->reg = reg + VCC_GATE_OFFSET;
@@ -786,7 +793,8 @@ void __init st_of_clkgen_vcc_setup(struct device_node *np)
                                             &mux->hw, &clk_mux_ops,
                                             &div->hw, &clk_divider_ops,
                                             &gate->hw, &clk_gate_ops,
-                                            data->clk_flags);
+                                            data->clk_flags |
+                                            CLK_GET_RATE_NOCACHE);
                if (IS_ERR(clk)) {
                        kfree(gate);
                        kfree(div);
@@ -821,10 +829,12 @@ err:
                kfree(container_of(composite->mux_hw, struct clk_mux, hw));
        }
 
-       if (clk_data)
-               kfree(clk_data->clks);
-
+       kfree(clk_data->clks);
+err_alloc_clks:
        kfree(clk_data);
+err_alloc:
        kfree(parents);
+err_parents:
+       iounmap(reg);
 }
 CLK_OF_DECLARE(clkgen_vcc, "st,clkgen-vcc", st_of_clkgen_vcc_setup);