diff options
Diffstat (limited to 'arch/sh/kernel')
-rw-r--r-- | arch/sh/kernel/cpu/sh4a/clock-sh7785.c | 77 |
1 files changed, 12 insertions, 65 deletions
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c index 7021ab0bfb88..a4a9bcbec664 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c | |||
@@ -19,6 +19,12 @@ | |||
19 | 19 | ||
20 | static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18, | 20 | static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18, |
21 | 24, 32, 36, 48 }; | 21 | 24, 32, 36, 48 }; |
22 | |||
23 | static struct clk_div_mult_table cpg_div = { | ||
24 | .divisors = div2, | ||
25 | .nr_divisors = ARRAY_SIZE(div2), | ||
26 | }; | ||
27 | |||
22 | struct clk_priv { | 28 | struct clk_priv { |
23 | unsigned int shift; | 29 | unsigned int shift; |
24 | 30 | ||
@@ -52,82 +58,23 @@ FRQMR_CLK_DATA(ifc, 28, 0x000e); | |||
52 | static unsigned long frqmr_recalc(struct clk *clk) | 58 | static unsigned long frqmr_recalc(struct clk *clk) |
53 | { | 59 | { |
54 | struct clk_priv *data = clk->priv; | 60 | struct clk_priv *data = clk->priv; |
55 | unsigned int idx; | 61 | unsigned int idx = (__raw_readl(FRQMR1) >> data->shift) & 0x000f; |
56 | |||
57 | idx = (__raw_readl(FRQMR1) >> data->shift) & 0x000f; | ||
58 | |||
59 | return clk->parent->rate / div2[idx]; | ||
60 | } | ||
61 | |||
62 | static void frqmr_build_rate_table(struct clk *clk) | ||
63 | { | ||
64 | struct clk_priv *data = clk->priv; | ||
65 | int i, entry; | ||
66 | |||
67 | for (i = entry = 0; i < ARRAY_SIZE(div2); i++) { | ||
68 | if ((data->div_bitmap & (1 << i)) == 0) | ||
69 | continue; | ||
70 | 62 | ||
71 | data->freq_table[entry].index = entry; | 63 | clk_rate_table_build(clk, data->freq_table, ARRAY_SIZE(div2), |
72 | data->freq_table[entry].frequency = | 64 | &cpg_div, &data->div_bitmap); |
73 | clk->parent->rate / div2[i]; | 65 | |
74 | 66 | return data->freq_table[idx].frequency; | |
75 | entry++; | ||
76 | } | ||
77 | |||
78 | if (entry == 0) { | ||
79 | pr_warning("clkfwk: failed to build frequency table " | ||
80 | "for \"%s\" clk!\n", clk->name); | ||
81 | return; | ||
82 | } | ||
83 | |||
84 | /* Termination entry */ | ||
85 | data->freq_table[entry].index = entry; | ||
86 | data->freq_table[entry].frequency = CPUFREQ_TABLE_END; | ||
87 | } | 67 | } |
88 | 68 | ||
89 | static long frqmr_round_rate(struct clk *clk, unsigned long rate) | 69 | static long frqmr_round_rate(struct clk *clk, unsigned long rate) |
90 | { | 70 | { |
91 | struct clk_priv *data = clk->priv; | 71 | struct clk_priv *data = clk->priv; |
92 | unsigned long rate_error, rate_error_prev = ~0UL; | ||
93 | unsigned long rate_best_fit = rate; | ||
94 | unsigned long highest, lowest; | ||
95 | int i; | ||
96 | |||
97 | highest = lowest = 0; | ||
98 | |||
99 | for (i = 0; data->freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { | ||
100 | unsigned long freq = data->freq_table[i].frequency; | ||
101 | |||
102 | if (freq == CPUFREQ_ENTRY_INVALID) | ||
103 | continue; | ||
104 | |||
105 | if (freq > highest) | ||
106 | highest = freq; | ||
107 | if (freq < lowest) | ||
108 | lowest = freq; | ||
109 | |||
110 | rate_error = abs(freq - rate); | ||
111 | if (rate_error < rate_error_prev) { | ||
112 | rate_best_fit = freq; | ||
113 | rate_error_prev = rate_error; | ||
114 | } | ||
115 | |||
116 | if (rate_error == 0) | ||
117 | break; | ||
118 | } | ||
119 | |||
120 | if (rate >= highest) | ||
121 | rate_best_fit = highest; | ||
122 | if (rate <= lowest) | ||
123 | rate_best_fit = lowest; | ||
124 | 72 | ||
125 | return rate_best_fit; | 73 | return clk_rate_table_round(clk, data->freq_table, rate); |
126 | } | 74 | } |
127 | 75 | ||
128 | static struct clk_ops frqmr_clk_ops = { | 76 | static struct clk_ops frqmr_clk_ops = { |
129 | .recalc = frqmr_recalc, | 77 | .recalc = frqmr_recalc, |
130 | .build_rate_table = frqmr_build_rate_table, | ||
131 | .round_rate = frqmr_round_rate, | 78 | .round_rate = frqmr_round_rate, |
132 | }; | 79 | }; |
133 | 80 | ||