aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel')
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7785.c77
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
20static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18, 20static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18,
21 24, 32, 36, 48 }; 21 24, 32, 36, 48 };
22
23static struct clk_div_mult_table cpg_div = {
24 .divisors = div2,
25 .nr_divisors = ARRAY_SIZE(div2),
26};
27
22struct clk_priv { 28struct clk_priv {
23 unsigned int shift; 29 unsigned int shift;
24 30
@@ -52,82 +58,23 @@ FRQMR_CLK_DATA(ifc, 28, 0x000e);
52static unsigned long frqmr_recalc(struct clk *clk) 58static 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
62static 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
89static long frqmr_round_rate(struct clk *clk, unsigned long rate) 69static 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
128static struct clk_ops frqmr_clk_ops = { 76static 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