From 65800b2c4012e11f1c33692e6727e743a05c6efe Mon Sep 17 00:00:00 2001 From: Russ Dill Date: Mon, 26 Nov 2012 11:20:09 -0800 Subject: clk: Don't mark shared helper functions as inline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The helper functions that access the opaque struct clk should not be marked inline since they are contained in clk.c, but expected to be used by other compilation units. This causes compile errors under gcc-4.7 In file included from arch/arm/mach-omap2/clockdomain.c:25:0: arch/arm/mach-omap2/clockdomain.c: In function ‘clkdm_clk_disable’: include/linux/clk-provider.h:338:12: error: inlining failed in call to always_inline ‘__clk_get_enable_count’: function body not available arch/arm/mach-omap2/clockdomain.c:1001:28: error: called from here make[1]: *** [arch/arm/mach-omap2/clockdomain.o] Error 1 make: *** [arch/arm/mach-omap2] Error 2 Signed-off-by: Russ Dill Signed-off-by: Mike Turquette [mturquette@linaro.org: removed fixes made redundant by commit 93532c8a] [mturquette@linaro.org: improved $SUBJECT] diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 251e45d..9777466 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -259,32 +259,32 @@ late_initcall(clk_disable_unused); /*** helper functions ***/ -inline const char *__clk_get_name(struct clk *clk) +const char *__clk_get_name(struct clk *clk) { return !clk ? NULL : clk->name; } -inline struct clk_hw *__clk_get_hw(struct clk *clk) +struct clk_hw *__clk_get_hw(struct clk *clk) { return !clk ? NULL : clk->hw; } -inline u8 __clk_get_num_parents(struct clk *clk) +u8 __clk_get_num_parents(struct clk *clk) { return !clk ? 0 : clk->num_parents; } -inline struct clk *__clk_get_parent(struct clk *clk) +struct clk *__clk_get_parent(struct clk *clk) { return !clk ? NULL : clk->parent; } -inline unsigned int __clk_get_enable_count(struct clk *clk) +unsigned int __clk_get_enable_count(struct clk *clk) { return !clk ? 0 : clk->enable_count; } -inline unsigned int __clk_get_prepare_count(struct clk *clk) +unsigned int __clk_get_prepare_count(struct clk *clk) { return !clk ? 0 : clk->prepare_count; } @@ -310,7 +310,7 @@ out: return ret; } -inline unsigned long __clk_get_flags(struct clk *clk) +unsigned long __clk_get_flags(struct clk *clk) { return !clk ? 0 : clk->flags; } -- cgit v0.10.2 From 4895084c87ab0973308021d755596798160b682a Mon Sep 17 00:00:00 2001 From: Niels de Vos Date: Thu, 13 Dec 2012 13:12:25 +0100 Subject: clk: export __clk_get_name for re-use in imx-ipu-v3 and others This fixes the following error when building for arm-imx: > ERROR: "__clk_get_name" [drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.ko] undefined! > make[1]: *** [__modpost] Error 1 > make: *** [modules] Error 2 There are valid usecases to get the name of a clock, be it for debugging purposes or to register a children of a clock like done in this IPU driver. Therefore exporting __clk_get_name() and make it available for others makes sense. Reported-by: Peter Robinson CC: Sascha Hauer CC: Mike Turquette Signed-off-by: Niels de Vos Signed-off-by: Mike Turquette [mturquette@linaro.org: removal of inline made redundant by 65800b2] diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 9777466..eea70da 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -263,6 +263,7 @@ const char *__clk_get_name(struct clk *clk) { return !clk ? NULL : clk->name; } +EXPORT_SYMBOL_GPL(__clk_get_name); struct clk_hw *__clk_get_hw(struct clk *clk) { -- cgit v0.10.2 From bab53301c3846ae9a5e1142dca2976f434f70481 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Mon, 3 Dec 2012 16:14:37 +0800 Subject: clk: fixed-factor: round_rate should use do_div clk->rate = parent->rate / div * mult The formula is OK. But it may overflow while we do operate with unsigned long. So use do_div instead. Signed-off-by: Haojian Zhuang Signed-off-by: Mike Turquette [mturquette@linaro.org: improved $SUBJECT] diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c index a489985..1ef271e 100644 --- a/drivers/clk/clk-fixed-factor.c +++ b/drivers/clk/clk-fixed-factor.c @@ -28,8 +28,11 @@ static unsigned long clk_factor_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_fixed_factor *fix = to_clk_fixed_factor(hw); + unsigned long long int rate; - return parent_rate * fix->mult / fix->div; + rate = (unsigned long long int)parent_rate * fix->mult; + do_div(rate, fix->div); + return (unsigned long)rate; } static long clk_factor_round_rate(struct clk_hw *hw, unsigned long rate, -- cgit v0.10.2 From 9f58b9b9fe3646421d9de251a4c5eec6d299a395 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 18 Dec 2012 15:43:45 +0800 Subject: clk: max77686: Fix return value checking for devm_kzalloc devm_kzalloc returns NULL on failure. Signed-off-by: Axel Lin Signed-off-by: Mike Turquette diff --git a/drivers/clk/clk-max77686.c b/drivers/clk/clk-max77686.c index d098f72..8944214 100644 --- a/drivers/clk/clk-max77686.c +++ b/drivers/clk/clk-max77686.c @@ -132,7 +132,7 @@ static int max77686_clk_register(struct device *dev, max77686->lookup = devm_kzalloc(dev, sizeof(struct clk_lookup), GFP_KERNEL); - if (IS_ERR(max77686->lookup)) + if (!max77686->lookup) return -ENOMEM; max77686->lookup->con_id = hw->init->name; @@ -151,13 +151,13 @@ static int max77686_clk_probe(struct platform_device *pdev) max77686_clks = devm_kzalloc(&pdev->dev, sizeof(struct max77686_clk *) * MAX77686_CLKS_NUM, GFP_KERNEL); - if (IS_ERR(max77686_clks)) + if (!max77686_clks) return -ENOMEM; for (i = 0; i < MAX77686_CLKS_NUM; i++) { max77686_clks[i] = devm_kzalloc(&pdev->dev, sizeof(struct max77686_clk), GFP_KERNEL); - if (IS_ERR(max77686_clks[i])) + if (!max77686_clks[i]) return -ENOMEM; } -- cgit v0.10.2 From 1af599df6bdad9ee34ae9e50efcda273e12b9d4f Mon Sep 17 00:00:00 2001 From: Prashant Gaikwad Date: Wed, 26 Dec 2012 19:16:22 +0530 Subject: clk: human-readable debugfs clock tree summary Adds debug file "clk_summary" in /sys/kernel/debug/clk dir. It helps to view all the clock registered in human-readable format. For example: clock enable_cnt prepare_cnt rate --------------------------------------------------------------------- i2s0_sync 0 0 24000000 spdif_in_sync 0 0 24000000 spdif_mux 0 0 24000000 spdif 0 0 24000000 spdif_doubler 0 0 48000000 spdif_div 0 0 48000000 spdif_2x 0 0 48000000 clk_32k 2 2 32768 blink_override 1 1 32768 blink 1 1 32768 clk_m 2 2 12000000 clk_out_3_mux 0 0 12000000 clk_out_3 0 0 12000000 pll_ref 3 3 12000000 pll_e_mux 0 0 12000000 pll_e 0 0 100000000 cml0 0 0 100000000 cml1 0 0 100000000 pciex 0 0 100000000 pll_d2 0 0 1000000 pll_d2_out0 0 0 500000 pll_d 0 0 1000000 pll_d_out0 0 0 500000 dsib_mux 0 0 500000 dsib 0 0 500000 dsia 0 0 500000 Signed-off-by: Prashant Gaikwad Signed-off-by: Mike Turquette diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index eea70da..8622b9d 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -35,6 +35,67 @@ static struct dentry *rootdir; static struct dentry *orphandir; static int inited = 0; +static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level) +{ + if (!c) + return; + + seq_printf(s, "%*s%-*s %-11d %-12d %-10lu", + level * 3 + 1, "", + 30 - level * 3, c->name, + c->enable_count, c->prepare_count, c->rate); + seq_printf(s, "\n"); +} + +static void clk_summary_show_subtree(struct seq_file *s, struct clk *c, + int level) +{ + struct clk *child; + struct hlist_node *tmp; + + if (!c) + return; + + clk_summary_show_one(s, c, level); + + hlist_for_each_entry(child, tmp, &c->children, child_node) + clk_summary_show_subtree(s, child, level + 1); +} + +static int clk_summary_show(struct seq_file *s, void *data) +{ + struct clk *c; + struct hlist_node *tmp; + + seq_printf(s, " clock enable_cnt prepare_cnt rate\n"); + seq_printf(s, "---------------------------------------------------------------------\n"); + + mutex_lock(&prepare_lock); + + hlist_for_each_entry(c, tmp, &clk_root_list, child_node) + clk_summary_show_subtree(s, c, 0); + + hlist_for_each_entry(c, tmp, &clk_orphan_list, child_node) + clk_summary_show_subtree(s, c, 0); + + mutex_unlock(&prepare_lock); + + return 0; +} + + +static int clk_summary_open(struct inode *inode, struct file *file) +{ + return single_open(file, clk_summary_show, inode->i_private); +} + +static const struct file_operations clk_summary_fops = { + .open = clk_summary_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + /* caller must hold prepare_lock */ static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry) { @@ -168,12 +229,18 @@ static int __init clk_debug_init(void) { struct clk *clk; struct hlist_node *tmp; + struct dentry *d; rootdir = debugfs_create_dir("clk", NULL); if (!rootdir) return -ENOMEM; + d = debugfs_create_file("clk_summary", S_IRUGO, rootdir, NULL, + &clk_summary_fops); + if (!d) + return -ENOMEM; + orphandir = debugfs_create_dir("orphans", rootdir); if (!orphandir) -- cgit v0.10.2 From bddca8944a7ab6699984c4b1b677261eb1c8d819 Mon Sep 17 00:00:00 2001 From: Prashant Gaikwad Date: Wed, 26 Dec 2012 19:16:23 +0530 Subject: clk: JSON debugfs clock tree summary Clock information is dumped in JSON format which is easy for machines to parse. Each clock is represented as an object which has same name as clock and following properties - enable_count - prepare_count - rate Output is verified using online JSON editor. Signed-off-by: Prashant Gaikwad Signed-off-by: Mike Turquette diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 8622b9d..593a2e4 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -96,6 +96,76 @@ static const struct file_operations clk_summary_fops = { .release = single_release, }; +static void clk_dump_one(struct seq_file *s, struct clk *c, int level) +{ + if (!c) + return; + + seq_printf(s, "\"%s\": { ", c->name); + seq_printf(s, "\"enable_count\": %d,", c->enable_count); + seq_printf(s, "\"prepare_count\": %d,", c->prepare_count); + seq_printf(s, "\"rate\": %lu", c->rate); +} + +static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level) +{ + struct clk *child; + struct hlist_node *tmp; + + if (!c) + return; + + clk_dump_one(s, c, level); + + hlist_for_each_entry(child, tmp, &c->children, child_node) { + seq_printf(s, ","); + clk_dump_subtree(s, child, level + 1); + } + + seq_printf(s, "}"); +} + +static int clk_dump(struct seq_file *s, void *data) +{ + struct clk *c; + struct hlist_node *tmp; + bool first_node = true; + + seq_printf(s, "{"); + + mutex_lock(&prepare_lock); + + hlist_for_each_entry(c, tmp, &clk_root_list, child_node) { + if (!first_node) + seq_printf(s, ","); + first_node = false; + clk_dump_subtree(s, c, 0); + } + + hlist_for_each_entry(c, tmp, &clk_orphan_list, child_node) { + seq_printf(s, ","); + clk_dump_subtree(s, c, 0); + } + + mutex_unlock(&prepare_lock); + + seq_printf(s, "}"); + return 0; +} + + +static int clk_dump_open(struct inode *inode, struct file *file) +{ + return single_open(file, clk_dump, inode->i_private); +} + +static const struct file_operations clk_dump_fops = { + .open = clk_dump_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + /* caller must hold prepare_lock */ static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry) { @@ -241,6 +311,11 @@ static int __init clk_debug_init(void) if (!d) return -ENOMEM; + d = debugfs_create_file("clk_dump", S_IRUGO, rootdir, NULL, + &clk_dump_fops); + if (!d) + return -ENOMEM; + orphandir = debugfs_create_dir("orphans", rootdir); if (!orphandir) -- cgit v0.10.2 From 3fe296cf5a66a82bc9077865b89075ce813f7f5d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 18 Dec 2012 15:54:52 +0800 Subject: clk: max77686: Remove unnecessary NULL checking for container_of() container_of() never returns NULL, thus remove the NULL checking for it. Also rename get_max77686_clk() to to_max77686_clk() for better readability. Signed-off-by: Axel Lin Signed-off-by: Mike Turquette diff --git a/drivers/clk/clk-max77686.c b/drivers/clk/clk-max77686.c index 8944214..90bf59c 100644 --- a/drivers/clk/clk-max77686.c +++ b/drivers/clk/clk-max77686.c @@ -44,33 +44,23 @@ struct max77686_clk { struct clk_lookup *lookup; }; -static struct max77686_clk *get_max77686_clk(struct clk_hw *hw) +static struct max77686_clk *to_max77686_clk(struct clk_hw *hw) { return container_of(hw, struct max77686_clk, hw); } static int max77686_clk_prepare(struct clk_hw *hw) { - struct max77686_clk *max77686; - int ret; - - max77686 = get_max77686_clk(hw); - if (!max77686) - return -ENOMEM; - - ret = regmap_update_bits(max77686->iodev->regmap, - MAX77686_REG_32KHZ, max77686->mask, max77686->mask); + struct max77686_clk *max77686 = to_max77686_clk(hw); - return ret; + return regmap_update_bits(max77686->iodev->regmap, + MAX77686_REG_32KHZ, max77686->mask, + max77686->mask); } static void max77686_clk_unprepare(struct clk_hw *hw) { - struct max77686_clk *max77686; - - max77686 = get_max77686_clk(hw); - if (!max77686) - return; + struct max77686_clk *max77686 = to_max77686_clk(hw); regmap_update_bits(max77686->iodev->regmap, MAX77686_REG_32KHZ, max77686->mask, ~max77686->mask); @@ -78,14 +68,10 @@ static void max77686_clk_unprepare(struct clk_hw *hw) static int max77686_clk_is_enabled(struct clk_hw *hw) { - struct max77686_clk *max77686; + struct max77686_clk *max77686 = to_max77686_clk(hw); int ret; u32 val; - max77686 = get_max77686_clk(hw); - if (!max77686) - return -ENOMEM; - ret = regmap_read(max77686->iodev->regmap, MAX77686_REG_32KHZ, &val); -- cgit v0.10.2 From 35a5db55ab96eadb07b3d5f7258558c680ebc2f0 Mon Sep 17 00:00:00 2001 From: Tony Prisk Date: Thu, 27 Dec 2012 13:14:29 +1300 Subject: clk: vt8500: Fix error in PLL calculations on non-exact match. When a PLL frequency calculation is performed and a non-exact match is found the wrong multiplier and divisors are returned. Signed-off-by: Tony Prisk Signed-off-by: Mike Turquette diff --git a/drivers/clk/clk-vt8500.c b/drivers/clk/clk-vt8500.c index fe25570..0cb26be 100644 --- a/drivers/clk/clk-vt8500.c +++ b/drivers/clk/clk-vt8500.c @@ -361,9 +361,9 @@ static void wm8650_find_pll_bits(unsigned long rate, unsigned long parent_rate, /* if we got here, it wasn't an exact match */ pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate, rate - best_err); - *multiplier = mul; - *divisor1 = div1; - *divisor2 = div2; + *multiplier = best_mul; + *divisor1 = best_div1; + *divisor2 = best_div2; } static int vtwm_pll_set_rate(struct clk_hw *hw, unsigned long rate, -- cgit v0.10.2 From 72480014b86c8b51fb51c5c6a0525876055c37c7 Mon Sep 17 00:00:00 2001 From: Tony Prisk Date: Thu, 27 Dec 2012 13:14:30 +1300 Subject: clk: vt8500: Fix device clock divisor calculations When calculating device clock divisor values in set_rate and round_rate, we do a simple integer divide. If parent_rate / rate has a fraction, this is dropped which results in the device clock being set too high. This patch corrects the problem by adding 1 to the calculated divisor if the division would have had a decimal result. Signed-off-by: Tony Prisk Signed-off-by: Mike Turquette diff --git a/drivers/clk/clk-vt8500.c b/drivers/clk/clk-vt8500.c index 0cb26be..3306c2b 100644 --- a/drivers/clk/clk-vt8500.c +++ b/drivers/clk/clk-vt8500.c @@ -123,6 +123,10 @@ static long vt8500_dclk_round_rate(struct clk_hw *hw, unsigned long rate, struct clk_device *cdev = to_clk_device(hw); u32 divisor = *prate / rate; + /* If prate / rate would be decimal, incr the divisor */ + if (rate * divisor < *prate) + divisor++; + /* * If this is a request for SDMMC we have to adjust the divisor * when >31 to use the fixed predivisor @@ -141,6 +145,10 @@ static int vt8500_dclk_set_rate(struct clk_hw *hw, unsigned long rate, u32 divisor = parent_rate / rate; unsigned long flags = 0; + /* If prate / rate would be decimal, incr the divisor */ + if (rate * divisor < *prate) + divisor++; + if (divisor == cdev->div_mask + 1) divisor = 0; -- cgit v0.10.2 From 58eb5a6763deab71208fbff15b09055fac884b11 Mon Sep 17 00:00:00 2001 From: Tony Prisk Date: Thu, 27 Dec 2012 13:14:31 +1300 Subject: clk: vt8500: Fix division-by-0 when requested rate=0 A request to vt8500_dclk_(round_rate/set_rate) with rate=0 results in a division-by-0 in the kernel. Signed-off-by: Tony Prisk Signed-off-by: Mike Turquette diff --git a/drivers/clk/clk-vt8500.c b/drivers/clk/clk-vt8500.c index 3306c2b..db7d41f 100644 --- a/drivers/clk/clk-vt8500.c +++ b/drivers/clk/clk-vt8500.c @@ -121,7 +121,12 @@ static long vt8500_dclk_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { struct clk_device *cdev = to_clk_device(hw); - u32 divisor = *prate / rate; + u32 divisor; + + if (rate == 0) + return 0; + + divisor = *prate / rate; /* If prate / rate would be decimal, incr the divisor */ if (rate * divisor < *prate) @@ -142,9 +147,14 @@ static int vt8500_dclk_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct clk_device *cdev = to_clk_device(hw); - u32 divisor = parent_rate / rate; + u32 divisor; unsigned long flags = 0; + if (rate == 0) + return 0; + + divisor = parent_rate / rate; + /* If prate / rate would be decimal, incr the divisor */ if (rate * divisor < *prate) divisor++; -- cgit v0.10.2 From abb165a80b42a5dd6ca001597422f0d28b2cd59a Mon Sep 17 00:00:00 2001 From: Tony Prisk Date: Fri, 28 Dec 2012 14:24:41 +1300 Subject: clk: vt8500: Add support for WM8750/WM8850 PLL clocks This patch adds support for the new PLL module found in WM8750 and WM8850 SoCs. Signed-off-by: Tony Prisk Signed-off-by: Mike Turquette diff --git a/drivers/clk/clk-vt8500.c b/drivers/clk/clk-vt8500.c index db7d41f..2515d4f 100644 --- a/drivers/clk/clk-vt8500.c +++ b/drivers/clk/clk-vt8500.c @@ -41,6 +41,7 @@ struct clk_device { #define PLL_TYPE_VT8500 0 #define PLL_TYPE_WM8650 1 +#define PLL_TYPE_WM8750 2 struct clk_pll { struct clk_hw hw; @@ -316,6 +317,16 @@ static __init void vtwm_device_clk_init(struct device_node *node) #define WM8650_BITS_TO_VAL(m, d1, d2) \ ((d2 << 13) | (d1 << 10) | (m & 0x3FF)) +/* Helper macros for PLL_WM8750 */ +#define WM8750_PLL_MUL(x) (((x >> 16) & 0xFF) + 1) +#define WM8750_PLL_DIV(x) ((((x >> 8) & 1) + 1) * (1 << (x & 7))) + +#define WM8750_BITS_TO_FREQ(r, m, d1, d2) \ + (r * (m+1) / ((d1+1) * (1 << d2))) + +#define WM8750_BITS_TO_VAL(f, m, d1, d2) \ + ((f << 24) | ((m - 1) << 16) | ((d1 - 1) << 8) | d2) + static void vt8500_find_pll_bits(unsigned long rate, unsigned long parent_rate, u32 *multiplier, u32 *prediv) @@ -384,11 +395,82 @@ static void wm8650_find_pll_bits(unsigned long rate, unsigned long parent_rate, *divisor2 = best_div2; } +static u32 wm8750_get_filter(u32 parent_rate, u32 divisor1) +{ + /* calculate frequency (MHz) after pre-divisor */ + u32 freq = (parent_rate / 1000000) / (divisor1 + 1); + + if ((freq < 10) || (freq > 200)) + pr_warn("%s: PLL recommended input frequency 10..200Mhz (requested %d Mhz)\n", + __func__, freq); + + if (freq >= 166) + return 7; + else if (freq >= 104) + return 6; + else if (freq >= 65) + return 5; + else if (freq >= 42) + return 4; + else if (freq >= 26) + return 3; + else if (freq >= 16) + return 2; + else if (freq >= 10) + return 1; + + return 0; +} + +static void wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate, + u32 *filter, u32 *multiplier, u32 *divisor1, u32 *divisor2) +{ + u32 mul, div1, div2; + u32 best_mul, best_div1, best_div2; + unsigned long tclk, rate_err, best_err; + + best_err = (unsigned long)-1; + + /* Find the closest match (lower or equal to requested) */ + for (div1 = 1; div1 >= 0; div1--) + for (div2 = 7; div2 >= 0; div2--) + for (mul = 0; mul <= 255; mul++) { + tclk = parent_rate * (mul + 1) / ((div1 + 1) * (1 << div2)); + if (tclk > rate) + continue; + /* error will always be +ve */ + rate_err = rate - tclk; + if (rate_err == 0) { + *filter = wm8750_get_filter(parent_rate, div1); + *multiplier = mul; + *divisor1 = div1; + *divisor2 = div2; + return; + } + + if (rate_err < best_err) { + best_err = rate_err; + best_mul = mul; + best_div1 = div1; + best_div2 = div2; + } + } + + /* if we got here, it wasn't an exact match */ + pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate, + rate - best_err); + + *filter = wm8750_get_filter(parent_rate, best_div1); + *multiplier = best_mul; + *divisor1 = best_div1; + *divisor2 = best_div2; +} + static int vtwm_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct clk_pll *pll = to_clk_pll(hw); - u32 mul, div1, div2; + u32 filter, mul, div1, div2; u32 pll_val; unsigned long flags = 0; @@ -403,6 +485,9 @@ static int vtwm_pll_set_rate(struct clk_hw *hw, unsigned long rate, wm8650_find_pll_bits(rate, parent_rate, &mul, &div1, &div2); pll_val = WM8650_BITS_TO_VAL(mul, div1, div2); break; + case PLL_TYPE_WM8750: + wm8750_find_pll_bits(rate, parent_rate, &filter, &mul, &div1, &div2); + pll_val = WM8750_BITS_TO_VAL(filter, mul, div1, div2); default: pr_err("%s: invalid pll type\n", __func__); return 0; @@ -423,7 +508,7 @@ static long vtwm_pll_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { struct clk_pll *pll = to_clk_pll(hw); - u32 mul, div1, div2; + u32 filter, mul, div1, div2; long round_rate; switch (pll->type) { @@ -435,6 +520,9 @@ static long vtwm_pll_round_rate(struct clk_hw *hw, unsigned long rate, wm8650_find_pll_bits(rate, *prate, &mul, &div1, &div2); round_rate = WM8650_BITS_TO_FREQ(*prate, mul, div1, div2); break; + case PLL_TYPE_WM8750: + wm8750_find_pll_bits(rate, *prate, &filter, &mul, &div1, &div2); + round_rate = WM8750_BITS_TO_FREQ(*prate, mul, div1, div2); default: round_rate = 0; } @@ -458,6 +546,10 @@ static unsigned long vtwm_pll_recalc_rate(struct clk_hw *hw, pll_freq = parent_rate * WM8650_PLL_MUL(pll_val); pll_freq /= WM8650_PLL_DIV(pll_val); break; + case PLL_TYPE_WM8750: + pll_freq = parent_rate * WM8750_PLL_MUL(pll_val); + pll_freq /= WM8750_PLL_DIV(pll_val); + break; default: pll_freq = 0; } @@ -526,10 +618,16 @@ static void __init wm8650_pll_init(struct device_node *node) vtwm_pll_clk_init(node, PLL_TYPE_WM8650); } +static void __init wm8750_pll_init(struct device_node *node) +{ + vtwm_pll_clk_init(node, PLL_TYPE_WM8750); +} + static const __initconst struct of_device_id clk_match[] = { { .compatible = "fixed-clock", .data = of_fixed_clk_setup, }, { .compatible = "via,vt8500-pll-clock", .data = vt8500_pll_init, }, { .compatible = "wm,wm8650-pll-clock", .data = wm8650_pll_init, }, + { .compatible = "wm,wm8750-pll-clock", .data = wm8750_pll_init, }, { .compatible = "via,vt8500-device-clock", .data = vtwm_device_clk_init, }, { /* sentinel */ } -- cgit v0.10.2 From e4eda8e0654c19cd7e3d143b051f3d5c213f0b43 Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Sun, 6 Jan 2013 18:21:43 +0400 Subject: clk: remove exported function from __init section The symbol of_fixed_clk_setup is exported and annotated __init. This looks like section mismatch. Fix this by removing the __init annotation of of_fixed_clk_setup. Signed-off-by: Denis Efremov Signed-off-by: Mike Turquette diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c index af78ed6..a53b53b 100644 --- a/drivers/clk/clk-fixed-rate.c +++ b/drivers/clk/clk-fixed-rate.c @@ -85,7 +85,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name, /** * of_fixed_clk_setup() - Setup function for simple fixed rate clock */ -void __init of_fixed_clk_setup(struct device_node *node) +void of_fixed_clk_setup(struct device_node *node) { struct clk *clk; const char *clk_name = node->name; -- cgit v0.10.2 From f1ba28a1f0fa16f3d0e78d199f3f9bf13e2d487b Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 7 Jan 2013 02:05:19 +0100 Subject: clk: max77686: Avoid double free at remove time The clk_lookup entry is dropped at remove time by a call to clkdev_drop(). That function frees the entry, which is also freed by the driver core as it has been allocated through devm_kzalloc(). This results in a double free. Use kzalloc() instead of devm_kzalloc() to fix this. Signed-off-by: Laurent Pinchart Signed-off-by: Mike Turquette diff --git a/drivers/clk/clk-max77686.c b/drivers/clk/clk-max77686.c index 90bf59c..9f57bc3 100644 --- a/drivers/clk/clk-max77686.c +++ b/drivers/clk/clk-max77686.c @@ -116,8 +116,7 @@ static int max77686_clk_register(struct device *dev, if (IS_ERR(clk)) return -ENOMEM; - max77686->lookup = devm_kzalloc(dev, sizeof(struct clk_lookup), - GFP_KERNEL); + max77686->lookup = kzalloc(sizeof(struct clk_lookup), GFP_KERNEL); if (!max77686->lookup) return -ENOMEM; -- cgit v0.10.2 From 38a8b096f86dea54cc64f4daa3402d0c4f2df43e Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 7 Jan 2013 23:38:55 -0200 Subject: clk: mxs: Index is always positive Fix the following warnings when building with W=1 option: drivers/clk/mxs/clk-imx23.c: In function 'mx23_clocks_init': drivers/clk/mxs/clk-imx23.c:149:16: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] drivers/clk/mxs/clk-imx23.c:165:16: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] ... drivers/clk/mxs/clk-imx28.c: In function 'mx28_clocks_init': drivers/clk/mxs/clk-imx28.c:227:16: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] drivers/clk/mxs/clk-imx28.c:244:16: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] Signed-off-by: Fabio Estevam Acked-by: Shawn Guo Signed-off-by: Mike Turquette diff --git a/drivers/clk/mxs/clk-imx23.c b/drivers/clk/mxs/clk-imx23.c index 8dd476e..b5c06f9 100644 --- a/drivers/clk/mxs/clk-imx23.c +++ b/drivers/clk/mxs/clk-imx23.c @@ -99,7 +99,7 @@ static enum imx23_clk clks_init_on[] __initdata = { int __init mx23_clocks_init(void) { struct device_node *np; - int i; + u32 i; clk_misc_init(); diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c index db3af08..126370a 100644 --- a/drivers/clk/mxs/clk-imx28.c +++ b/drivers/clk/mxs/clk-imx28.c @@ -154,7 +154,7 @@ static enum imx28_clk clks_init_on[] __initdata = { int __init mx28_clocks_init(void) { struct device_node *np; - int i; + u32 i; clk_misc_init(); -- cgit v0.10.2 From eb8b8f2e7164b819ca35a3d6240198fdb98d0ef3 Mon Sep 17 00:00:00 2001 From: Barry Song Date: Thu, 20 Dec 2012 16:51:31 +0800 Subject: clk: prima2: enable dt-binding clkdev mapping this patche deletes hard code that registers clkdev by things like: clk_register_clkdev(clk, NULL, "b0030000.nand"); clk_register_clkdev(clk, NULL, "b0040000.audio"); clk_register_clkdev(clk, NULL, "b0080000.usp"); prima2 clock controller becomes a clock provider and every dt node just declares its clock sources by dt prop. it also makes us easier to extend this driver to support both prima2 and marco as marco has different address mapping with prima2. Signed-off-by: Barry Song Signed-off-by: Mike Turquette diff --git a/Documentation/devicetree/bindings/clock/prima2-clock.txt b/Documentation/devicetree/bindings/clock/prima2-clock.txt new file mode 100644 index 0000000..5016979 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/prima2-clock.txt @@ -0,0 +1,73 @@ +* Clock bindings for CSR SiRFprimaII + +Required properties: +- compatible: Should be "sirf,prima2-clkc" +- reg: Address and length of the register set +- interrupts: Should contain clock controller interrupt +- #clock-cells: Should be <1> + +The clock consumer should specify the desired clock by having the clock +ID in its "clocks" phandle cell. The following is a full list of prima2 +clocks and IDs. + + Clock ID + --------------------------- + rtc 0 + osc 1 + pll1 2 + pll2 3 + pll3 4 + mem 5 + sys 6 + security 7 + dsp 8 + gps 9 + mf 10 + io 11 + cpu 12 + uart0 13 + uart1 14 + uart2 15 + tsc 16 + i2c0 17 + i2c1 18 + spi0 19 + spi1 20 + pwmc 21 + efuse 22 + pulse 23 + dmac0 24 + dmac1 25 + nand 26 + audio 27 + usp0 28 + usp1 29 + usp2 30 + vip 31 + gfx 32 + mm 33 + lcd 34 + vpp 35 + mmc01 36 + mmc23 37 + mmc45 38 + usbpll 39 + usb0 40 + usb1 41 + +Examples: + +clks: clock-controller@88000000 { + compatible = "sirf,prima2-clkc"; + reg = <0x88000000 0x1000>; + interrupts = <3>; + #clock-cells = <1>; +}; + +i2c0: i2c@b00e0000 { + cell-index = <0>; + compatible = "sirf,prima2-i2c"; + reg = <0xb00e0000 0x10000>; + interrupts = <24>; + clocks = <&clks 17>; +}; diff --git a/arch/arm/boot/dts/prima2.dtsi b/arch/arm/boot/dts/prima2.dtsi index 055fca5..3329719 100644 --- a/arch/arm/boot/dts/prima2.dtsi +++ b/arch/arm/boot/dts/prima2.dtsi @@ -58,10 +58,11 @@ #size-cells = <1>; ranges = <0x88000000 0x88000000 0x40000>; - clock-controller@88000000 { + clks: clock-controller@88000000 { compatible = "sirf,prima2-clkc"; reg = <0x88000000 0x1000>; interrupts = <3>; + #clock-cells = <1>; }; reset-controller@88010000 { @@ -85,6 +86,7 @@ compatible = "sirf,prima2-memc"; reg = <0x90000000 0x10000>; interrupts = <27>; + clocks = <&clks 5>; }; }; @@ -104,6 +106,7 @@ compatible = "sirf,prima2-vpp"; reg = <0x90020000 0x10000>; interrupts = <31>; + clocks = <&clks 35>; }; }; @@ -117,6 +120,7 @@ compatible = "powervr,sgx531"; reg = <0x98000000 0x8000000>; interrupts = <6>; + clocks = <&clks 32>; }; }; @@ -130,6 +134,7 @@ compatible = "sirf,prima2-video-codec"; reg = <0xa0000000 0x8000000>; interrupts = <5>; + clocks = <&clks 33>; }; }; @@ -149,12 +154,14 @@ compatible = "sirf,prima2-gps"; reg = <0xa8010000 0x10000>; interrupts = <7>; + clocks = <&clks 9>; }; dsp@a9000000 { compatible = "sirf,prima2-dsp"; reg = <0xa9000000 0x1000000>; interrupts = <8>; + clocks = <&clks 8>; }; }; @@ -174,12 +181,14 @@ compatible = "sirf,prima2-nand"; reg = <0xb0030000 0x10000>; interrupts = <41>; + clocks = <&clks 26>; }; audio@b0040000 { compatible = "sirf,prima2-audio"; reg = <0xb0040000 0x10000>; interrupts = <35>; + clocks = <&clks 27>; }; uart0: uart@b0050000 { @@ -187,6 +196,7 @@ compatible = "sirf,prima2-uart"; reg = <0xb0050000 0x10000>; interrupts = <17>; + clocks = <&clks 13>; }; uart1: uart@b0060000 { @@ -194,6 +204,7 @@ compatible = "sirf,prima2-uart"; reg = <0xb0060000 0x10000>; interrupts = <18>; + clocks = <&clks 14>; }; uart2: uart@b0070000 { @@ -201,6 +212,7 @@ compatible = "sirf,prima2-uart"; reg = <0xb0070000 0x10000>; interrupts = <19>; + clocks = <&clks 15>; }; usp0: usp@b0080000 { @@ -208,6 +220,7 @@ compatible = "sirf,prima2-usp"; reg = <0xb0080000 0x10000>; interrupts = <20>; + clocks = <&clks 28>; }; usp1: usp@b0090000 { @@ -215,6 +228,7 @@ compatible = "sirf,prima2-usp"; reg = <0xb0090000 0x10000>; interrupts = <21>; + clocks = <&clks 29>; }; usp2: usp@b00a0000 { @@ -222,6 +236,7 @@ compatible = "sirf,prima2-usp"; reg = <0xb00a0000 0x10000>; interrupts = <22>; + clocks = <&clks 30>; }; dmac0: dma-controller@b00b0000 { @@ -229,6 +244,7 @@ compatible = "sirf,prima2-dmac"; reg = <0xb00b0000 0x10000>; interrupts = <12>; + clocks = <&clks 24>; }; dmac1: dma-controller@b0160000 { @@ -236,11 +252,13 @@ compatible = "sirf,prima2-dmac"; reg = <0xb0160000 0x10000>; interrupts = <13>; + clocks = <&clks 25>; }; vip@b00C0000 { compatible = "sirf,prima2-vip"; reg = <0xb00C0000 0x10000>; + clocks = <&clks 31>; }; spi0: spi@b00d0000 { @@ -248,6 +266,7 @@ compatible = "sirf,prima2-spi"; reg = <0xb00d0000 0x10000>; interrupts = <15>; + clocks = <&clks 19>; }; spi1: spi@b0170000 { @@ -255,6 +274,7 @@ compatible = "sirf,prima2-spi"; reg = <0xb0170000 0x10000>; interrupts = <16>; + clocks = <&clks 20>; }; i2c0: i2c@b00e0000 { @@ -262,6 +282,7 @@ compatible = "sirf,prima2-i2c"; reg = <0xb00e0000 0x10000>; interrupts = <24>; + clocks = <&clks 17>; }; i2c1: i2c@b00f0000 { @@ -269,12 +290,14 @@ compatible = "sirf,prima2-i2c"; reg = <0xb00f0000 0x10000>; interrupts = <25>; + clocks = <&clks 18>; }; tsc@b0110000 { compatible = "sirf,prima2-tsc"; reg = <0xb0110000 0x10000>; interrupts = <33>; + clocks = <&clks 16>; }; gpio: pinctrl@b0120000 { @@ -507,17 +530,20 @@ pwm@b0130000 { compatible = "sirf,prima2-pwm"; reg = <0xb0130000 0x10000>; + clocks = <&clks 21>; }; efusesys@b0140000 { compatible = "sirf,prima2-efuse"; reg = <0xb0140000 0x10000>; + clocks = <&clks 22>; }; pulsec@b0150000 { compatible = "sirf,prima2-pulsec"; reg = <0xb0150000 0x10000>; interrupts = <48>; + clocks = <&clks 23>; }; pci-iobg { @@ -616,12 +642,14 @@ compatible = "chipidea,ci13611a-prima2"; reg = <0xb8000000 0x10000>; interrupts = <10>; + clocks = <&clks 40>; }; usb1: usb@b00f0000 { compatible = "chipidea,ci13611a-prima2"; reg = <0xb8010000 0x10000>; interrupts = <11>; + clocks = <&clks 41>; }; sata@b00f0000 { @@ -634,6 +662,7 @@ compatible = "sirf,prima2-security"; reg = <0xb8030000 0x10000>; interrupts = <42>; + clocks = <&clks 7>; }; }; }; diff --git a/drivers/clk/clk-prima2.c b/drivers/clk/clk-prima2.c index a203ecc..f8e9d0c 100644 --- a/drivers/clk/clk-prima2.c +++ b/drivers/clk/clk-prima2.c @@ -1025,20 +1025,67 @@ static struct of_device_id rsc_ids[] = { {}, }; +enum prima2_clk_index { + /* 0 1 2 3 4 5 6 7 8 9 */ + rtc, osc, pll1, pll2, pll3, mem, sys, security, dsp, gps, + mf, io, cpu, uart0, uart1, uart2, tsc, i2c0, i2c1, spi0, + spi1, pwmc, efuse, pulse, dmac0, dmac1, nand, audio, usp0, usp1, + usp2, vip, gfx, mm, lcd, vpp, mmc01, mmc23, mmc45, usbpll, + usb0, usb1, maxclk, +}; + +static __initdata struct clk_hw* prima2_clk_hw_array[maxclk] = { + NULL, /* dummy */ + NULL, + &clk_pll1.hw, + &clk_pll2.hw, + &clk_pll3.hw, + &clk_mem.hw, + &clk_sys.hw, + &clk_security.hw, + &clk_dsp.hw, + &clk_gps.hw, + &clk_mf.hw, + &clk_io.hw, + &clk_cpu.hw, + &clk_uart0.hw, + &clk_uart1.hw, + &clk_uart2.hw, + &clk_tsc.hw, + &clk_i2c0.hw, + &clk_i2c1.hw, + &clk_spi0.hw, + &clk_spi1.hw, + &clk_pwmc.hw, + &clk_efuse.hw, + &clk_pulse.hw, + &clk_dmac0.hw, + &clk_dmac1.hw, + &clk_nand.hw, + &clk_audio.hw, + &clk_usp0.hw, + &clk_usp1.hw, + &clk_usp2.hw, + &clk_vip.hw, + &clk_gfx.hw, + &clk_mm.hw, + &clk_lcd.hw, + &clk_vpp.hw, + &clk_mmc01.hw, + &clk_mmc23.hw, + &clk_mmc45.hw, + &usb_pll_clk_hw, + &clk_usb0.hw, + &clk_usb1.hw, +}; + +static struct clk *prima2_clks[maxclk]; +static struct clk_onecell_data clk_data; + void __init sirfsoc_of_clk_init(void) { - struct clk *clk; struct device_node *np; - - np = of_find_matching_node(NULL, clkc_ids); - if (!np) - panic("unable to find compatible clkc node in dtb\n"); - - sirfsoc_clk_vbase = of_iomap(np, 0); - if (!sirfsoc_clk_vbase) - panic("unable to map clkc registers\n"); - - of_node_put(np); + int i; np = of_find_matching_node(NULL, rsc_ids); if (!np) @@ -1050,122 +1097,30 @@ void __init sirfsoc_of_clk_init(void) of_node_put(np); + np = of_find_matching_node(NULL, clkc_ids); + if (!np) + return; + + sirfsoc_clk_vbase = of_iomap(np, 0); + if (!sirfsoc_clk_vbase) + panic("unable to map clkc registers\n"); /* These are always available (RTC and 26MHz OSC)*/ - clk = clk_register_fixed_rate(NULL, "rtc", NULL, + prima2_clks[rtc] = clk_register_fixed_rate(NULL, "rtc", NULL, CLK_IS_ROOT, 32768); - BUG_ON(IS_ERR(clk)); - clk = clk_register_fixed_rate(NULL, "osc", NULL, + prima2_clks[osc]= clk_register_fixed_rate(NULL, "osc", NULL, CLK_IS_ROOT, 26000000); - BUG_ON(IS_ERR(clk)); - - clk = clk_register(NULL, &clk_pll1.hw); - BUG_ON(IS_ERR(clk)); - clk = clk_register(NULL, &clk_pll2.hw); - BUG_ON(IS_ERR(clk)); - clk = clk_register(NULL, &clk_pll3.hw); - BUG_ON(IS_ERR(clk)); - clk = clk_register(NULL, &clk_mem.hw); - BUG_ON(IS_ERR(clk)); - clk = clk_register(NULL, &clk_sys.hw); - BUG_ON(IS_ERR(clk)); - clk = clk_register(NULL, &clk_security.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "b8030000.security"); - clk = clk_register(NULL, &clk_dsp.hw); - BUG_ON(IS_ERR(clk)); - clk = clk_register(NULL, &clk_gps.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "a8010000.gps"); - clk = clk_register(NULL, &clk_mf.hw); - BUG_ON(IS_ERR(clk)); - clk = clk_register(NULL, &clk_io.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "io"); - clk = clk_register(NULL, &clk_cpu.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "cpu"); - clk = clk_register(NULL, &clk_uart0.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "b0050000.uart"); - clk = clk_register(NULL, &clk_uart1.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "b0060000.uart"); - clk = clk_register(NULL, &clk_uart2.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "b0070000.uart"); - clk = clk_register(NULL, &clk_tsc.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "b0110000.tsc"); - clk = clk_register(NULL, &clk_i2c0.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "b00e0000.i2c"); - clk = clk_register(NULL, &clk_i2c1.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "b00f0000.i2c"); - clk = clk_register(NULL, &clk_spi0.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "b00d0000.spi"); - clk = clk_register(NULL, &clk_spi1.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "b0170000.spi"); - clk = clk_register(NULL, &clk_pwmc.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "b0130000.pwm"); - clk = clk_register(NULL, &clk_efuse.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "b0140000.efusesys"); - clk = clk_register(NULL, &clk_pulse.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "b0150000.pulsec"); - clk = clk_register(NULL, &clk_dmac0.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "b00b0000.dma-controller"); - clk = clk_register(NULL, &clk_dmac1.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "b0160000.dma-controller"); - clk = clk_register(NULL, &clk_nand.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "b0030000.nand"); - clk = clk_register(NULL, &clk_audio.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "b0040000.audio"); - clk = clk_register(NULL, &clk_usp0.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "b0080000.usp"); - clk = clk_register(NULL, &clk_usp1.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "b0090000.usp"); - clk = clk_register(NULL, &clk_usp2.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "b00a0000.usp"); - clk = clk_register(NULL, &clk_vip.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "b00c0000.vip"); - clk = clk_register(NULL, &clk_gfx.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "98000000.graphics"); - clk = clk_register(NULL, &clk_mm.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "a0000000.multimedia"); - clk = clk_register(NULL, &clk_lcd.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "90010000.display"); - clk = clk_register(NULL, &clk_vpp.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "90020000.vpp"); - clk = clk_register(NULL, &clk_mmc01.hw); - BUG_ON(IS_ERR(clk)); - clk = clk_register(NULL, &clk_mmc23.hw); - BUG_ON(IS_ERR(clk)); - clk = clk_register(NULL, &clk_mmc45.hw); - BUG_ON(IS_ERR(clk)); - clk = clk_register(NULL, &usb_pll_clk_hw); - BUG_ON(IS_ERR(clk)); - clk = clk_register(NULL, &clk_usb0.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "b00e0000.usb"); - clk = clk_register(NULL, &clk_usb1.hw); - BUG_ON(IS_ERR(clk)); - clk_register_clkdev(clk, NULL, "b00f0000.usb"); + + for (i = pll1; i < maxclk; i++) { + prima2_clks[i] = clk_register(NULL, prima2_clk_hw_array[i]); + BUG_ON(!prima2_clks[i]); + } + clk_register_clkdev(prima2_clks[cpu], NULL, "cpu"); + clk_register_clkdev(prima2_clks[io], NULL, "io"); + clk_register_clkdev(prima2_clks[mem], NULL, "mem"); + + clk_data.clks = prima2_clks; + clk_data.clk_num = maxclk; + + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); } -- cgit v0.10.2 From 1a3cd18475a98b9587a181b8d8ebc7f5cdedb4b0 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 15 Jan 2013 10:28:05 +0000 Subject: clk-divider: fix macros The macro is_power_of_two() in clk-divider.c was defined as !(i & ~i) which is always true. Instead use is_power_of_2() from log2.h. Also add brackets around the macro arguments in div_mask to avoid any future operator precedence problems. Signed-off-by: James Hogan Cc: Joe Perches Signed-off-by: Mike Turquette [mturquette@linaro.org: use log2.h per Joe Perches; update changelog] diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index a9204c6..68b4021 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -16,6 +16,7 @@ #include #include #include +#include /* * DOC: basic adjustable divider clock that cannot gate @@ -29,8 +30,7 @@ #define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw) -#define div_mask(d) ((1 << (d->width)) - 1) -#define is_power_of_two(i) !(i & ~i) +#define div_mask(d) ((1 << ((d)->width)) - 1) static unsigned int _get_table_maxdiv(const struct clk_div_table *table) { @@ -137,7 +137,7 @@ static bool _is_valid_table_div(const struct clk_div_table *table, static bool _is_valid_div(struct clk_divider *divider, unsigned int div) { if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) - return is_power_of_two(div); + return is_power_of_2(div); if (divider->table) return _is_valid_table_div(divider->table, div); return true; -- cgit v0.10.2 From 135a829744067cb825b48f7422e22861e57d5ecd Mon Sep 17 00:00:00 2001 From: Mike Turquette Date: Fri, 18 Jan 2013 13:00:05 -0800 Subject: clk: beautify Makefile The list of common clock types was getting a bit unmanageable. This patch puts only one file on each line and reorders the object files alphabetically. Also a newline is added to separate the sections. Reported-by: Stephen Boyd Cc: Prashant Gaikwad Signed-off-by: Mike Turquette diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index ee90e87..e73b1d6 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -1,8 +1,13 @@ # common clock types obj-$(CONFIG_HAVE_CLK) += clk-devres.o obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o -obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed-rate.o clk-gate.o \ - clk-mux.o clk-divider.o clk-fixed-factor.o +obj-$(CONFIG_COMMON_CLK) += clk.o +obj-$(CONFIG_COMMON_CLK) += clk-divider.o +obj-$(CONFIG_COMMON_CLK) += clk-fixed-factor.o +obj-$(CONFIG_COMMON_CLK) += clk-fixed-rate.o +obj-$(CONFIG_COMMON_CLK) += clk-gate.o +obj-$(CONFIG_COMMON_CLK) += clk-mux.o + # SoCs specific obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o -- cgit v0.10.2 From 4cfe54e57910b59444d34a05284db27df416f20b Mon Sep 17 00:00:00 2001 From: Nestor Ovroy Date: Fri, 18 Jan 2013 17:07:39 +0100 Subject: clk: Deduplicate exit code in clk_set_rate On non-out case 'return ret;' is equivalent to 'return 0;' as the ret variable is initialized at 0 and never changed. Signed-off-by: Nestor Ovroy diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 593a2e4..ad2ac94 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1093,9 +1093,6 @@ int clk_set_rate(struct clk *clk, unsigned long rate) /* change the rates */ clk_change_rate(top); - mutex_unlock(&prepare_lock); - - return 0; out: mutex_unlock(&prepare_lock); -- cgit v0.10.2 From f2f6c2556dcc432e50003bc8fa4d62d95906f149 Mon Sep 17 00:00:00 2001 From: Prashant Gaikwad Date: Fri, 4 Jan 2013 12:30:52 +0530 Subject: clk: add common of_clk_init() function Modify of_clk_init function so that it will determine which driver to initialize based on device tree instead of each driver registering to it. Based on a similar patch for drivers/irqchip by Thomas Petazzoni and drivers/clocksource by Stephen Warren. Signed-off-by: Prashant Gaikwad Tested-by: Tony Prisk Tested-by: Pawel Moll Tested-by: Rob Herring Tested-by: Josh Cartwright Reviewed-by: Josh Cartwright Acked-by: Maxime Ripard Signed-off-by: Mike Turquette [mturquette@linaro.org: merge conflict from missing CLKSRC_OF_TABLES()] Signed-off-by: Mike Turquette diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c index a53b53b..dc58fbd 100644 --- a/drivers/clk/clk-fixed-rate.c +++ b/drivers/clk/clk-fixed-rate.c @@ -101,4 +101,5 @@ void of_fixed_clk_setup(struct device_node *node) of_clk_add_provider(node, of_clk_src_simple_get, clk); } EXPORT_SYMBOL_GPL(of_fixed_clk_setup); +CLK_OF_DECLARE(fixed_clk, "fixed-clock", of_fixed_clk_setup); #endif diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index ad2ac94..fabbfe1 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -18,6 +18,7 @@ #include #include #include +#include static DEFINE_SPINLOCK(enable_lock); static DEFINE_MUTEX(prepare_lock); @@ -1803,6 +1804,11 @@ struct of_clk_provider { void *data; }; +extern struct of_device_id __clk_of_table[]; + +static const struct of_device_id __clk_of_table_sentinel + __used __section(__clk_of_table_end); + static LIST_HEAD(of_clk_providers); static DEFINE_MUTEX(of_clk_lock); @@ -1931,6 +1937,9 @@ void __init of_clk_init(const struct of_device_id *matches) { struct device_node *np; + if (!matches) + matches = __clk_of_table; + for_each_matching_node(np, matches) { const struct of_device_id *match = of_match_node(matches, np); of_clk_init_cb_t clk_init_cb = match->data; diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index d1ea7ce..c1fe60ad 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -150,6 +150,15 @@ #endif +#ifdef CONFIG_COMMON_CLK +#define CLK_OF_TABLES() . = ALIGN(8); \ + VMLINUX_SYMBOL(__clk_of_table) = .; \ + *(__clk_of_table) \ + *(__clk_of_table_end) +#else +#define CLK_OF_TABLES() +#endif + #define KERNEL_DTB() \ STRUCT_ALIGN(); \ VMLINUX_SYMBOL(__dtb_start) = .; \ @@ -493,6 +502,7 @@ DEV_DISCARD(init.rodata) \ CPU_DISCARD(init.rodata) \ MEM_DISCARD(init.rodata) \ + CLK_OF_TABLES() \ KERNEL_DTB() #define INIT_TEXT \ diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 4989b8a..7f197d7 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -379,7 +379,13 @@ struct clk_onecell_data { }; struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data); const char *of_clk_get_parent_name(struct device_node *np, int index); + void of_clk_init(const struct of_device_id *matches); +#define CLK_OF_DECLARE(name, compat, fn) \ + static const struct of_device_id __clk_of_table_##name \ + __used __section(__clk_of_table) \ + = { .compatible = compat, .data = fn }; + #endif /* CONFIG_COMMON_CLK */ #endif /* CLK_PROVIDER_H */ -- cgit v0.10.2 From 85a181986c9cf8bbd2c4f2fb6f2add7ac5db1f76 Mon Sep 17 00:00:00 2001 From: Prashant Gaikwad Date: Fri, 4 Jan 2013 12:30:54 +0530 Subject: clk: sunxi: Use common of_clk_init() function Use common of_clk_init() function to initialize clocks. Signed-off-by: Prashant Gaikwad Acked-by: Maxime Ripard Signed-off-by: Mike Turquette diff --git a/drivers/clk/clk-sunxi.c b/drivers/clk/clk-sunxi.c deleted file mode 100644 index 0e831b5..0000000 --- a/drivers/clk/clk-sunxi.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2012 Maxime Ripard - * - * Maxime Ripard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include - -static const __initconst struct of_device_id clk_match[] = { - { .compatible = "fixed-clock", .data = of_fixed_clk_setup, }, - {} -}; - -void __init sunxi_init_clocks(void) -{ - of_clk_init(clk_match); -} diff --git a/drivers/clocksource/sunxi_timer.c b/drivers/clocksource/sunxi_timer.c index 3cd1bd3..93d09d0 100644 --- a/drivers/clocksource/sunxi_timer.c +++ b/drivers/clocksource/sunxi_timer.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #define TIMER_CTL_REG 0x00 #define TIMER_CTL_ENABLE (1 << 0) @@ -124,7 +124,7 @@ static void __init sunxi_timer_init(void) if (irq <= 0) panic("Can't parse IRQ"); - sunxi_init_clocks(); + of_clk_init(NULL); clk = of_clk_get(node, 0); if (IS_ERR(clk)) diff --git a/include/linux/clk/sunxi.h b/include/linux/clk/sunxi.h deleted file mode 100644 index e074fdd..0000000 --- a/include/linux/clk/sunxi.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2012 Maxime Ripard - * - * Maxime Ripard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __LINUX_CLK_SUNXI_H_ -#define __LINUX_CLK_SUNXI_H_ - -void __init sunxi_init_clocks(void); - -#endif -- cgit v0.10.2 From d34bcdeb43331f87acf21423df26a8567c07de67 Mon Sep 17 00:00:00 2001 From: Prashant Gaikwad Date: Fri, 4 Jan 2013 12:30:55 +0530 Subject: clk: highbank: Use common of_clk_init() function Use common of_clk_init() function for clocks initialization. Signed-off-by: Prashant Gaikwad Tested-by: Rob Herring Signed-off-by: Mike Turquette diff --git a/arch/arm/mach-highbank/core.h b/arch/arm/mach-highbank/core.h index 80235b4..3f65206 100644 --- a/arch/arm/mach-highbank/core.h +++ b/arch/arm/mach-highbank/core.h @@ -2,7 +2,6 @@ #define __HIGHBANK_CORE_H extern void highbank_set_cpu_jump(int cpu, void *jump_addr); -extern void highbank_clocks_init(void); extern void highbank_restart(char, const char *); extern void __iomem *scu_base_addr; diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c index 981dc1e..f710f16 100644 --- a/arch/arm/mach-highbank/highbank.c +++ b/arch/arm/mach-highbank/highbank.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -116,7 +117,7 @@ static void __init highbank_timer_init(void) WARN_ON(!timer_base); irq = irq_of_parse_and_map(np, 0); - highbank_clocks_init(); + of_clk_init(NULL); lookup.clk = of_clk_get(np, 0); clkdev_add(&lookup); diff --git a/drivers/clk/clk-highbank.c b/drivers/clk/clk-highbank.c index 52fecad..5d1de2e 100644 --- a/drivers/clk/clk-highbank.c +++ b/drivers/clk/clk-highbank.c @@ -314,33 +314,23 @@ static void __init hb_pll_init(struct device_node *node) { hb_clk_init(node, &clk_pll_ops); } +CLK_OF_DECLARE(hb_pll, "calxeda,hb-pll-clock", hb_pll_init); static void __init hb_a9periph_init(struct device_node *node) { hb_clk_init(node, &a9periphclk_ops); } +CLK_OF_DECLARE(hb_a9periph, "calxeda,hb-a9periph-clock", hb_a9periph_init); static void __init hb_a9bus_init(struct device_node *node) { struct clk *clk = hb_clk_init(node, &a9bclk_ops); clk_prepare_enable(clk); } +CLK_OF_DECLARE(hb_a9bus, "calxeda,hb-a9bus-clock", hb_a9bus_init); static void __init hb_emmc_init(struct device_node *node) { hb_clk_init(node, &periclk_ops); } - -static const __initconst struct of_device_id clk_match[] = { - { .compatible = "fixed-clock", .data = of_fixed_clk_setup, }, - { .compatible = "calxeda,hb-pll-clock", .data = hb_pll_init, }, - { .compatible = "calxeda,hb-a9periph-clock", .data = hb_a9periph_init, }, - { .compatible = "calxeda,hb-a9bus-clock", .data = hb_a9bus_init, }, - { .compatible = "calxeda,hb-emmc-clock", .data = hb_emmc_init, }, - {} -}; - -void __init highbank_clocks_init(void) -{ - of_clk_init(clk_match); -} +CLK_OF_DECLARE(hb_emmc, "calxeda,hb-emmc-clock", hb_emmc_init); -- cgit v0.10.2 From 5b6e0adb69674c684c33503f50010644b049029c Mon Sep 17 00:00:00 2001 From: Prashant Gaikwad Date: Fri, 4 Jan 2013 12:30:56 +0530 Subject: clk: vt8500: Use common of_clk_init() function Use common of_clk_init() function for clock initialization. Signed-off-by: Prashant Gaikwad Tested-by: Tony Prisk Signed-off-by: Mike Turquette [mturquette@linaro.org: added entry for wm8750-pll-clock] Signed-off-by: Mike Turquette diff --git a/drivers/clk/clk-vt8500.c b/drivers/clk/clk-vt8500.c index 2515d4f..b5538bb 100644 --- a/drivers/clk/clk-vt8500.c +++ b/drivers/clk/clk-vt8500.c @@ -291,7 +291,7 @@ static __init void vtwm_device_clk_init(struct device_node *node) rc = of_clk_add_provider(node, of_clk_src_simple_get, clk); clk_register_clkdev(clk, clk_name, NULL); } - +CLK_OF_DECLARE(vt8500_device, "via,vt8500-device-clock", vtwm_device_clk_init); /* PLL clock related functions */ @@ -612,26 +612,19 @@ static void __init vt8500_pll_init(struct device_node *node) { vtwm_pll_clk_init(node, PLL_TYPE_VT8500); } +CLK_OF_DECLARE(vt8500_pll, "via,vt8500-pll-clock", vt8500_pll_init); static void __init wm8650_pll_init(struct device_node *node) { vtwm_pll_clk_init(node, PLL_TYPE_WM8650); } +CLK_OF_DECLARE(wm8650_pll, "wm,wm8650-pll-clock", wm8650_pll_init); static void __init wm8750_pll_init(struct device_node *node) { vtwm_pll_clk_init(node, PLL_TYPE_WM8750); } - -static const __initconst struct of_device_id clk_match[] = { - { .compatible = "fixed-clock", .data = of_fixed_clk_setup, }, - { .compatible = "via,vt8500-pll-clock", .data = vt8500_pll_init, }, - { .compatible = "wm,wm8650-pll-clock", .data = wm8650_pll_init, }, - { .compatible = "wm,wm8750-pll-clock", .data = wm8750_pll_init, }, - { .compatible = "via,vt8500-device-clock", - .data = vtwm_device_clk_init, }, - { /* sentinel */ } -}; +CLK_OF_DECLARE(wm8750_pll, "wm,wm8750-pll-clock", wm8750_pll_init); void __init vtwm_clk_init(void __iomem *base) { @@ -640,5 +633,5 @@ void __init vtwm_clk_init(void __iomem *base) pmc_base = base; - of_clk_init(clk_match); + of_clk_init(NULL); } -- cgit v0.10.2 From 10290030d7d31e387f602190ece2cdb3abfb3d71 Mon Sep 17 00:00:00 2001 From: Prashant Gaikwad Date: Fri, 4 Jan 2013 12:30:57 +0530 Subject: clk: zynq: Use common of_clk_init() function Use common of_clk_init() function for clock initialization. Signed-off-by: Prashant Gaikwad Reviewed-by: Josh Cartwright Tested-by: Josh Cartwright Signed-off-by: Mike Turquette diff --git a/drivers/clk/clk-zynq.c b/drivers/clk/clk-zynq.c index 37a3051..b14a25f 100644 --- a/drivers/clk/clk-zynq.c +++ b/drivers/clk/clk-zynq.c @@ -81,6 +81,7 @@ static void __init zynq_pll_clk_setup(struct device_node *np) if (WARN_ON(ret)) return; } +CLK_OF_DECLARE(zynq_pll, "xlnx,zynq-pll", zynq_pll_clk_setup); struct zynq_periph_clk { struct clk_hw hw; @@ -187,6 +188,7 @@ static void __init zynq_periph_clk_setup(struct device_node *np) if (WARN_ON(err)) return; } +CLK_OF_DECLARE(zynq_periph, "xlnx,zynq-periph-clock", zynq_periph_clk_setup); /* CPU Clock domain is modelled as a mux with 4 children subclks, whose * derivative rates depend on CLK_621_TRUE @@ -366,18 +368,10 @@ static void __init zynq_cpu_clk_setup(struct device_node *np) if (WARN_ON(err)) return; } - -static const __initconst struct of_device_id zynq_clk_match[] = { - { .compatible = "fixed-clock", .data = of_fixed_clk_setup, }, - { .compatible = "xlnx,zynq-pll", .data = zynq_pll_clk_setup, }, - { .compatible = "xlnx,zynq-periph-clock", - .data = zynq_periph_clk_setup, }, - { .compatible = "xlnx,zynq-cpu-clock", .data = zynq_cpu_clk_setup, }, - {} -}; +CLK_OF_DECLARE(zynq_cpu, "xlnx,zynq-cpu-clock", zynq_cpu_clk_setup); void __init xilinx_zynq_clocks_init(void __iomem *slcr) { slcr_base = slcr; - of_clk_init(zynq_clk_match); + of_clk_init(NULL); } -- cgit v0.10.2 From 8ae5ac5607b5baf7c1178998032ba752f61c7165 Mon Sep 17 00:00:00 2001 From: Prashant Gaikwad Date: Fri, 4 Jan 2013 12:30:58 +0530 Subject: clk: vexpress: Use common of_clk_init() function Use common of_clk_init() function for clock initialization. Signed-off-by: Prashant Gaikwad Tested-by: Pawel Moll Signed-off-by: Mike Turquette diff --git a/drivers/clk/versatile/clk-vexpress-osc.c b/drivers/clk/versatile/clk-vexpress-osc.c index dcb6ae0..256c8be 100644 --- a/drivers/clk/versatile/clk-vexpress-osc.c +++ b/drivers/clk/versatile/clk-vexpress-osc.c @@ -144,3 +144,4 @@ error: vexpress_config_func_put(osc->func); kfree(osc); } +CLK_OF_DECLARE(vexpress_soc, "arm,vexpress-osc", vexpress_osc_of_setup); diff --git a/drivers/clk/versatile/clk-vexpress.c b/drivers/clk/versatile/clk-vexpress.c index c742ac7..f889f2f 100644 --- a/drivers/clk/versatile/clk-vexpress.c +++ b/drivers/clk/versatile/clk-vexpress.c @@ -99,19 +99,13 @@ struct clk *vexpress_sp810_of_get(struct of_phandle_args *clkspec, void *data) return vexpress_sp810_timerclken[clkspec->args[0]]; } -static const __initconst struct of_device_id vexpress_fixed_clk_match[] = { - { .compatible = "fixed-clock", .data = of_fixed_clk_setup, }, - { .compatible = "arm,vexpress-osc", .data = vexpress_osc_of_setup, }, - {} -}; - void __init vexpress_clk_of_init(void) { struct device_node *node; struct clk *clk; struct clk *refclk, *timclk; - of_clk_init(vexpress_fixed_clk_match); + of_clk_init(NULL); node = of_find_compatible_node(NULL, NULL, "arm,sp810"); vexpress_sp810_init(of_iomap(node, 0)); -- cgit v0.10.2 From fde8bc59c03c0ad1fa4f655e0ed5cc1f76d11e8b Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 14 Feb 2013 23:26:52 +0100 Subject: clk: sunxi: remove stale Makefile entry Patch 85a18198 "clk: sunxi: Use common of_clk_init() function" removed the clk-sunxi.c file but left the Makefile entry, which causes a build error in multi_v7_defconfig: make[4]: *** No rule to make target `drivers/clk/clk-sunxi.o', needed by `drivers/clk/built-in.o'. The obvious fix is to remove the extraneous line from the Makefile. Signed-off-by: Arnd Bergmann Cc: Prashant Gaikwad Cc: Maxime Ripard Signed-off-by: Mike Turquette diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index e73b1d6..0ad642f 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -25,7 +25,6 @@ endif obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o obj-$(CONFIG_ARCH_U8500) += ux500/ obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o -obj-$(CONFIG_ARCH_SUNXI) += clk-sunxi.o obj-$(CONFIG_ARCH_ZYNQ) += clk-zynq.o # Chip specific -- cgit v0.10.2