diff options
Diffstat (limited to 'drivers/sh/clk')
-rw-r--r-- | drivers/sh/clk/core.c | 116 | ||||
-rw-r--r-- | drivers/sh/clk/cpg.c | 79 |
2 files changed, 84 insertions, 111 deletions
diff --git a/drivers/sh/clk/core.c b/drivers/sh/clk/core.c index dc8d022c07a..7715de2629c 100644 --- a/drivers/sh/clk/core.c +++ b/drivers/sh/clk/core.c @@ -25,7 +25,6 @@ #include <linux/seq_file.h> #include <linux/err.h> #include <linux/io.h> -#include <linux/debugfs.h> #include <linux/cpufreq.h> #include <linux/clk.h> #include <linux/sh_clk.h> @@ -173,6 +172,26 @@ long clk_rate_div_range_round(struct clk *clk, unsigned int div_min, return clk_rate_round_helper(&div_range_round); } +static long clk_rate_mult_range_iter(unsigned int pos, + struct clk_rate_round_data *rounder) +{ + return clk_get_rate(rounder->arg) * pos; +} + +long clk_rate_mult_range_round(struct clk *clk, unsigned int mult_min, + unsigned int mult_max, unsigned long rate) +{ + struct clk_rate_round_data mult_range_round = { + .min = mult_min, + .max = mult_max, + .func = clk_rate_mult_range_iter, + .arg = clk_get_parent(clk), + .rate = rate, + }; + + return clk_rate_round_helper(&mult_range_round); +} + int clk_rate_table_find(struct clk *clk, struct cpufreq_frequency_table *freq_table, unsigned long rate) @@ -205,9 +224,6 @@ int clk_reparent(struct clk *child, struct clk *parent) list_add(&child->sibling, &parent->children); child->parent = parent; - /* now do the debugfs renaming to reattach the child - to the proper parent */ - return 0; } @@ -339,7 +355,7 @@ static int clk_establish_mapping(struct clk *clk) */ if (!clk->parent) { clk->mapping = &dummy_mapping; - return 0; + goto out; } /* @@ -368,6 +384,9 @@ static int clk_establish_mapping(struct clk *clk) } clk->mapping = mapping; +out: + clk->mapped_reg = clk->mapping->base; + clk->mapped_reg += (phys_addr_t)clk->enable_reg - clk->mapping->phys; return 0; } @@ -386,10 +405,12 @@ static void clk_teardown_mapping(struct clk *clk) /* Nothing to do */ if (mapping == &dummy_mapping) - return; + goto out; kref_put(&mapping->ref, clk_destroy_mapping); clk->mapping = NULL; +out: + clk->mapped_reg = NULL; } int clk_register(struct clk *clk) @@ -665,89 +686,6 @@ static int __init clk_syscore_init(void) subsys_initcall(clk_syscore_init); #endif -/* - * debugfs support to trace clock tree hierarchy and attributes - */ -static struct dentry *clk_debugfs_root; - -static int clk_debugfs_register_one(struct clk *c) -{ - int err; - struct dentry *d; - struct clk *pa = c->parent; - char s[255]; - char *p = s; - - p += sprintf(p, "%p", c); - d = debugfs_create_dir(s, pa ? pa->dentry : clk_debugfs_root); - if (!d) - return -ENOMEM; - c->dentry = d; - - d = debugfs_create_u8("usecount", S_IRUGO, c->dentry, (u8 *)&c->usecount); - if (!d) { - err = -ENOMEM; - goto err_out; - } - d = debugfs_create_u32("rate", S_IRUGO, c->dentry, (u32 *)&c->rate); - if (!d) { - err = -ENOMEM; - goto err_out; - } - d = debugfs_create_x32("flags", S_IRUGO, c->dentry, (u32 *)&c->flags); - if (!d) { - err = -ENOMEM; - goto err_out; - } - return 0; - -err_out: - debugfs_remove_recursive(c->dentry); - return err; -} - -static int clk_debugfs_register(struct clk *c) -{ - int err; - struct clk *pa = c->parent; - - if (pa && !pa->dentry) { - err = clk_debugfs_register(pa); - if (err) - return err; - } - - if (!c->dentry) { - err = clk_debugfs_register_one(c); - if (err) - return err; - } - return 0; -} - -static int __init clk_debugfs_init(void) -{ - struct clk *c; - struct dentry *d; - int err; - - d = debugfs_create_dir("clock", NULL); - if (!d) - return -ENOMEM; - clk_debugfs_root = d; - - list_for_each_entry(c, &clock_list, node) { - err = clk_debugfs_register(c); - if (err) - goto err_out; - } - return 0; -err_out: - debugfs_remove_recursive(clk_debugfs_root); - return err; -} -late_initcall(clk_debugfs_init); - static int __init clk_late_init(void) { unsigned long flags; diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c index 82dd6fb1783..45fee368b09 100644 --- a/drivers/sh/clk/cpg.c +++ b/drivers/sh/clk/cpg.c @@ -15,15 +15,15 @@ static int sh_clk_mstp32_enable(struct clk *clk) { - __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit), - clk->enable_reg); + iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit), + clk->mapped_reg); return 0; } static void sh_clk_mstp32_disable(struct clk *clk) { - __raw_writel(__raw_readl(clk->enable_reg) | (1 << clk->enable_bit), - clk->enable_reg); + iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit), + clk->mapped_reg); } static struct clk_ops sh_clk_mstp32_clk_ops = { @@ -72,7 +72,7 @@ static unsigned long sh_clk_div6_recalc(struct clk *clk) clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, table, NULL); - idx = __raw_readl(clk->enable_reg) & 0x003f; + idx = ioread32(clk->mapped_reg) & 0x003f; return clk->freq_table[idx].frequency; } @@ -98,10 +98,10 @@ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent) if (ret < 0) return ret; - value = __raw_readl(clk->enable_reg) & + value = ioread32(clk->mapped_reg) & ~(((1 << clk->src_width) - 1) << clk->src_shift); - __raw_writel(value | (i << clk->src_shift), clk->enable_reg); + iowrite32(value | (i << clk->src_shift), clk->mapped_reg); /* Rebuild the frequency table */ clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, @@ -119,10 +119,10 @@ static int sh_clk_div6_set_rate(struct clk *clk, unsigned long rate) if (idx < 0) return idx; - value = __raw_readl(clk->enable_reg); + value = ioread32(clk->mapped_reg); value &= ~0x3f; value |= idx; - __raw_writel(value, clk->enable_reg); + iowrite32(value, clk->mapped_reg); return 0; } @@ -133,9 +133,9 @@ static int sh_clk_div6_enable(struct clk *clk) ret = sh_clk_div6_set_rate(clk, clk->rate); if (ret == 0) { - value = __raw_readl(clk->enable_reg); + value = ioread32(clk->mapped_reg); value &= ~0x100; /* clear stop bit to enable clock */ - __raw_writel(value, clk->enable_reg); + iowrite32(value, clk->mapped_reg); } return ret; } @@ -144,10 +144,10 @@ static void sh_clk_div6_disable(struct clk *clk) { unsigned long value; - value = __raw_readl(clk->enable_reg); + value = ioread32(clk->mapped_reg); value |= 0x100; /* stop clock */ value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */ - __raw_writel(value, clk->enable_reg); + iowrite32(value, clk->mapped_reg); } static struct clk_ops sh_clk_div6_clk_ops = { @@ -167,6 +167,38 @@ static struct clk_ops sh_clk_div6_reparent_clk_ops = { .set_parent = sh_clk_div6_set_parent, }; +static int __init sh_clk_init_parent(struct clk *clk) +{ + u32 val; + + if (clk->parent) + return 0; + + if (!clk->parent_table || !clk->parent_num) + return 0; + + if (!clk->src_width) { + pr_err("sh_clk_init_parent: cannot select parent clock\n"); + return -EINVAL; + } + + val = (ioread32(clk->mapped_reg) >> clk->src_shift); + val &= (1 << clk->src_width) - 1; + + if (val >= clk->parent_num) { + pr_err("sh_clk_init_parent: parent table size failed\n"); + return -EINVAL; + } + + clk->parent = clk->parent_table[val]; + if (!clk->parent) { + pr_err("sh_clk_init_parent: unable to set parent"); + return -EINVAL; + } + + return 0; +} + static int __init sh_clk_div6_register_ops(struct clk *clks, int nr, struct clk_ops *ops) { @@ -190,8 +222,11 @@ static int __init sh_clk_div6_register_ops(struct clk *clks, int nr, clkp->ops = ops; clkp->freq_table = freq_table + (k * freq_table_size); clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; - ret = clk_register(clkp); + if (ret < 0) + break; + + ret = sh_clk_init_parent(clkp); } return ret; @@ -217,7 +252,7 @@ static unsigned long sh_clk_div4_recalc(struct clk *clk) clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, table, &clk->arch_flags); - idx = (__raw_readl(clk->enable_reg) >> clk->enable_bit) & 0x000f; + idx = (ioread32(clk->mapped_reg) >> clk->enable_bit) & 0x000f; return clk->freq_table[idx].frequency; } @@ -235,15 +270,15 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent) */ if (parent->flags & CLK_ENABLE_ON_INIT) - value = __raw_readl(clk->enable_reg) & ~(1 << 7); + value = ioread32(clk->mapped_reg) & ~(1 << 7); else - value = __raw_readl(clk->enable_reg) | (1 << 7); + value = ioread32(clk->mapped_reg) | (1 << 7); ret = clk_reparent(clk, parent); if (ret < 0) return ret; - __raw_writel(value, clk->enable_reg); + iowrite32(value, clk->mapped_reg); /* Rebiuld the frequency table */ clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, @@ -260,10 +295,10 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate) if (idx < 0) return idx; - value = __raw_readl(clk->enable_reg); + value = ioread32(clk->mapped_reg); value &= ~(0xf << clk->enable_bit); value |= (idx << clk->enable_bit); - __raw_writel(value, clk->enable_reg); + iowrite32(value, clk->mapped_reg); if (d4t->kick) d4t->kick(clk); @@ -273,13 +308,13 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate) static int sh_clk_div4_enable(struct clk *clk) { - __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << 8), clk->enable_reg); + iowrite32(ioread32(clk->mapped_reg) & ~(1 << 8), clk->mapped_reg); return 0; } static void sh_clk_div4_disable(struct clk *clk) { - __raw_writel(__raw_readl(clk->enable_reg) | (1 << 8), clk->enable_reg); + iowrite32(ioread32(clk->mapped_reg) | (1 << 8), clk->mapped_reg); } static struct clk_ops sh_clk_div4_clk_ops = { |