Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sh: clock div6 helper code

This patch adds div6 clock helper code. The div6 clocks
are simply 6-bit divide-by-n modules where n is 1 to 64.

Needed for vclk on sh7722, sh7723, sh7343 and sh7366.
sh7724 needs this even more for vclk, fclka, fclkb,
irdaclk and spuclk.

Signed-off-by: Magnus Damm <damm@igel.co.jp>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>

authored by

Magnus Damm and committed by
Paul Mundt
2693e274 a50de78d

+75 -6
+10
arch/sh/include/asm/clock.h
··· 145 145 int sh_clk_div4_register(struct clk *clks, int nr, 146 146 struct clk_div_mult_table *table); 147 147 148 + #define SH_CLK_DIV6(_name, _parent, _reg, _flags) \ 149 + { \ 150 + .name = _name, \ 151 + .parent = _parent, \ 152 + .enable_reg = (void __iomem *)_reg, \ 153 + .flags = _flags, \ 154 + } 155 + 156 + int sh_clk_div6_register(struct clk *clks, int nr); 157 + 148 158 #endif /* __ASM_SH_CLOCK_H */
+65 -6
arch/sh/kernel/cpu/clock-cpg.c
··· 38 38 return ret; 39 39 } 40 40 41 + static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate) 42 + { 43 + return clk_rate_table_round(clk, clk->freq_table, rate); 44 + } 45 + 46 + static int sh_clk_div6_divisors[64] = { 47 + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 48 + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 49 + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 50 + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64 51 + }; 52 + 53 + static struct clk_div_mult_table sh_clk_div6_table = { 54 + .divisors = sh_clk_div6_divisors, 55 + .nr_divisors = ARRAY_SIZE(sh_clk_div6_divisors), 56 + }; 57 + 58 + static unsigned long sh_clk_div6_recalc(struct clk *clk) 59 + { 60 + struct clk_div_mult_table *table = &sh_clk_div6_table; 61 + unsigned int idx; 62 + 63 + clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, 64 + table, NULL); 65 + 66 + idx = __raw_readl(clk->enable_reg) & 0x003f; 67 + 68 + return clk->freq_table[idx].frequency; 69 + } 70 + 71 + static struct clk_ops sh_clk_div6_clk_ops = { 72 + .recalc = sh_clk_div6_recalc, 73 + .round_rate = sh_clk_div_round_rate, 74 + }; 75 + 76 + int __init sh_clk_div6_register(struct clk *clks, int nr) 77 + { 78 + struct clk *clkp; 79 + void *freq_table; 80 + int nr_divs = sh_clk_div6_table.nr_divisors; 81 + int freq_table_size = sizeof(struct cpufreq_frequency_table); 82 + int ret = 0; 83 + int k; 84 + 85 + freq_table_size *= (nr_divs + 1); 86 + 87 + freq_table = alloc_bootmem(freq_table_size * nr); 88 + if (!freq_table) 89 + return -ENOMEM; 90 + 91 + for (k = 0; !ret && (k < nr); k++) { 92 + clkp = clks + k; 93 + 94 + clkp->ops = &sh_clk_div6_clk_ops; 95 + clkp->id = -1; 96 + clkp->freq_table = freq_table + (k * freq_table_size); 97 + clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; 98 + 99 + ret = clk_register(clkp); 100 + } 101 + 102 + return ret; 103 + } 104 + 41 105 static unsigned long sh_clk_div4_recalc(struct clk *clk) 42 106 { 43 107 struct clk_div_mult_table *table = clk->priv; ··· 115 51 return clk->freq_table[idx].frequency; 116 52 } 117 53 118 - static long sh_clk_div4_round_rate(struct clk *clk, unsigned long rate) 119 - { 120 - return clk_rate_table_round(clk, clk->freq_table, rate); 121 - } 122 - 123 54 static struct clk_ops sh_clk_div4_clk_ops = { 124 55 .recalc = sh_clk_div4_recalc, 125 - .round_rate = sh_clk_div4_round_rate, 56 + .round_rate = sh_clk_div_round_rate, 126 57 }; 127 58 128 59 int __init sh_clk_div4_register(struct clk *clks, int nr,