diff options
Diffstat (limited to 'drivers/clk/versatile')
-rw-r--r-- | drivers/clk/versatile/clk-icst.c | 9 | ||||
-rw-r--r-- | drivers/clk/versatile/clk-impd1.c | 1 | ||||
-rw-r--r-- | drivers/clk/versatile/clk-realview.c | 5 | ||||
-rw-r--r-- | drivers/clk/versatile/clk-sp810.c | 79 | ||||
-rw-r--r-- | drivers/clk/versatile/clk-versatile.c | 4 |
5 files changed, 26 insertions, 72 deletions
diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c index bc96f103b..08c5ee976 100644 --- a/drivers/clk/versatile/clk-icst.c +++ b/drivers/clk/versatile/clk-icst.c @@ -13,8 +13,9 @@ * ICST clock code from the ARM tree should probably be merged into this * file. */ -#include <linux/clk.h> -#include <linux/clkdev.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/export.h> #include <linux/err.h> #include <linux/clk-provider.h> #include <linux/io.h> @@ -156,8 +157,10 @@ struct clk *icst_clk_register(struct device *dev, icst->lockreg = base + desc->lock_offset; clk = clk_register(dev, &icst->hw); - if (IS_ERR(clk)) + if (IS_ERR(clk)) { + kfree(pclone); kfree(icst); + } return clk; } diff --git a/drivers/clk/versatile/clk-impd1.c b/drivers/clk/versatile/clk-impd1.c index 1cc1330dc..65c842a21 100644 --- a/drivers/clk/versatile/clk-impd1.c +++ b/drivers/clk/versatile/clk-impd1.c @@ -7,7 +7,6 @@ * published by the Free Software Foundation. */ #include <linux/clk-provider.h> -#include <linux/clk.h> #include <linux/clkdev.h> #include <linux/err.h> #include <linux/io.h> diff --git a/drivers/clk/versatile/clk-realview.c b/drivers/clk/versatile/clk-realview.c index c8b523117..86f70997d 100644 --- a/drivers/clk/versatile/clk-realview.c +++ b/drivers/clk/versatile/clk-realview.c @@ -6,7 +6,6 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include <linux/clk.h> #include <linux/clkdev.h> #include <linux/err.h> #include <linux/io.h> @@ -33,13 +32,13 @@ static const struct icst_params realview_oscvco_params = { .idx2s = icst307_idx2s, }; -static const struct clk_icst_desc __initdata realview_osc0_desc = { +static const struct clk_icst_desc realview_osc0_desc __initconst = { .params = &realview_oscvco_params, .vco_offset = REALVIEW_SYS_OSC0_OFFSET, .lock_offset = REALVIEW_SYS_LOCK_OFFSET, }; -static const struct clk_icst_desc __initdata realview_osc4_desc = { +static const struct clk_icst_desc realview_osc4_desc __initconst = { .params = &realview_oscvco_params, .vco_offset = REALVIEW_SYS_OSC4_OFFSET, .lock_offset = REALVIEW_SYS_LOCK_OFFSET, diff --git a/drivers/clk/versatile/clk-sp810.c b/drivers/clk/versatile/clk-sp810.c index b674ffc4f..a1cdef6b0 100644 --- a/drivers/clk/versatile/clk-sp810.c +++ b/drivers/clk/versatile/clk-sp810.c @@ -12,7 +12,8 @@ */ #include <linux/amba/sp810.h> -#include <linux/clkdev.h> +#include <linux/slab.h> +#include <linux/clk.h> #include <linux/clk-provider.h> #include <linux/err.h> #include <linux/of.h> @@ -32,12 +33,9 @@ struct clk_sp810_timerclken { struct clk_sp810 { struct device_node *node; - int refclk_index, timclk_index; void __iomem *base; spinlock_t lock; struct clk_sp810_timerclken timerclken[4]; - struct clk *refclk; - struct clk *timclk; }; static u8 clk_sp810_timerclken_get_parent(struct clk_hw *hw) @@ -70,55 +68,7 @@ static int clk_sp810_timerclken_set_parent(struct clk_hw *hw, u8 index) return 0; } -/* - * FIXME - setting the parent every time .prepare is invoked is inefficient. - * This is better handled by a dedicated clock tree configuration mechanism at - * init-time. Revisit this later when such a mechanism exists - */ -static int clk_sp810_timerclken_prepare(struct clk_hw *hw) -{ - struct clk_sp810_timerclken *timerclken = to_clk_sp810_timerclken(hw); - struct clk_sp810 *sp810 = timerclken->sp810; - struct clk *old_parent = __clk_get_parent(hw->clk); - struct clk *new_parent; - - if (!sp810->refclk) - sp810->refclk = of_clk_get(sp810->node, sp810->refclk_index); - - if (!sp810->timclk) - sp810->timclk = of_clk_get(sp810->node, sp810->timclk_index); - - if (WARN_ON(IS_ERR(sp810->refclk) || IS_ERR(sp810->timclk))) - return -ENOENT; - - /* Select fastest parent */ - if (clk_get_rate(sp810->refclk) > clk_get_rate(sp810->timclk)) - new_parent = sp810->refclk; - else - new_parent = sp810->timclk; - - /* Switch the parent if necessary */ - if (old_parent != new_parent) { - clk_prepare(new_parent); - clk_set_parent(hw->clk, new_parent); - clk_unprepare(old_parent); - } - - return 0; -} - -static void clk_sp810_timerclken_unprepare(struct clk_hw *hw) -{ - struct clk_sp810_timerclken *timerclken = to_clk_sp810_timerclken(hw); - struct clk_sp810 *sp810 = timerclken->sp810; - - clk_put(sp810->timclk); - clk_put(sp810->refclk); -} - static const struct clk_ops clk_sp810_timerclken_ops = { - .prepare = clk_sp810_timerclken_prepare, - .unprepare = clk_sp810_timerclken_unprepare, .get_parent = clk_sp810_timerclken_get_parent, .set_parent = clk_sp810_timerclken_set_parent, }; @@ -139,24 +89,18 @@ static void __init clk_sp810_of_setup(struct device_node *node) { struct clk_sp810 *sp810 = kzalloc(sizeof(*sp810), GFP_KERNEL); const char *parent_names[2]; + int num = ARRAY_SIZE(parent_names); char name[12]; struct clk_init_data init; int i; + bool deprecated; if (!sp810) { pr_err("Failed to allocate memory for SP810!\n"); return; } - sp810->refclk_index = of_property_match_string(node, "clock-names", - "refclk"); - parent_names[0] = of_clk_get_parent_name(node, sp810->refclk_index); - - sp810->timclk_index = of_property_match_string(node, "clock-names", - "timclk"); - parent_names[1] = of_clk_get_parent_name(node, sp810->timclk_index); - - if (!parent_names[0] || !parent_names[1]) { + if (of_clk_parent_fill(node, parent_names, num) != num) { pr_warn("Failed to obtain parent clocks for SP810!\n"); return; } @@ -169,7 +113,9 @@ static void __init clk_sp810_of_setup(struct device_node *node) init.ops = &clk_sp810_timerclken_ops; init.flags = CLK_IS_BASIC; init.parent_names = parent_names; - init.num_parents = ARRAY_SIZE(parent_names); + init.num_parents = num; + + deprecated = !of_find_property(node, "assigned-clock-parents", NULL); for (i = 0; i < ARRAY_SIZE(sp810->timerclken); i++) { snprintf(name, ARRAY_SIZE(name), "timerclken%d", i); @@ -178,6 +124,15 @@ static void __init clk_sp810_of_setup(struct device_node *node) sp810->timerclken[i].channel = i; sp810->timerclken[i].hw.init = &init; + /* + * If DT isn't setting the parent, force it to be + * the 1 MHz clock without going through the framework. + * We do this before clk_register() so that it can determine + * the parent and setup the tree properly. + */ + if (deprecated) + init.ops->set_parent(&sp810->timerclken[i].hw, 1); + sp810->timerclken[i].clk = clk_register(NULL, &sp810->timerclken[i].hw); WARN_ON(IS_ERR(sp810->timerclken[i].clk)); diff --git a/drivers/clk/versatile/clk-versatile.c b/drivers/clk/versatile/clk-versatile.c index 7a4f8635b..a89a92756 100644 --- a/drivers/clk/versatile/clk-versatile.c +++ b/drivers/clk/versatile/clk-versatile.c @@ -8,8 +8,6 @@ * published by the Free Software Foundation. */ #include <linux/clk-provider.h> -#include <linux/clk.h> -#include <linux/clkdev.h> #include <linux/err.h> #include <linux/of.h> #include <linux/of_address.h> @@ -35,7 +33,7 @@ static const struct icst_params cp_auxosc_params = { .idx2s = icst525_idx2s, }; -static const struct clk_icst_desc __initdata cm_auxosc_desc = { +static const struct clk_icst_desc cm_auxosc_desc __initconst = { .params = &cp_auxosc_params, .vco_offset = 0x1c, .lock_offset = INTEGRATOR_HDR_LOCK_OFFSET, |