aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/sh/clk.c66
-rw-r--r--include/linux/sh_clk.h1
2 files changed, 53 insertions, 14 deletions
diff --git a/drivers/sh/clk.c b/drivers/sh/clk.c
index 813d97cdad49..3ac6fa0005b9 100644
--- a/drivers/sh/clk.c
+++ b/drivers/sh/clk.c
@@ -45,6 +45,8 @@ void clk_rate_table_build(struct clk *clk,
45 unsigned long freq; 45 unsigned long freq;
46 int i; 46 int i;
47 47
48 clk->nr_freqs = nr_freqs;
49
48 for (i = 0; i < nr_freqs; i++) { 50 for (i = 0; i < nr_freqs; i++) {
49 div = 1; 51 div = 1;
50 mult = 1; 52 mult = 1;
@@ -69,30 +71,39 @@ void clk_rate_table_build(struct clk *clk,
69 freq_table[i].frequency = CPUFREQ_TABLE_END; 71 freq_table[i].frequency = CPUFREQ_TABLE_END;
70} 72}
71 73
72long clk_rate_table_round(struct clk *clk, 74struct clk_rate_round_data;
73 struct cpufreq_frequency_table *freq_table, 75
74 unsigned long rate) 76struct clk_rate_round_data {
77 unsigned long rate;
78 unsigned int min, max;
79 long (*func)(unsigned int pos, struct clk_rate_round_data *arg);
80 void *arg;
81};
82
83#define for_each_frequency(pos, r, freq) \
84 for (pos = r->min, freq = r->func(pos, r->arg); \
85 pos < r->max; pos++, freq = r->func(pos, r)) \
86 if (unlikely(freq == 0)) \
87 ; \
88 else
89
90static long clk_rate_round_helper(struct clk_rate_round_data *rounder)
75{ 91{
76 unsigned long rate_error, rate_error_prev = ~0UL; 92 unsigned long rate_error, rate_error_prev = ~0UL;
77 unsigned long rate_best_fit = rate; 93 unsigned long rate_best_fit = rounder->rate;
78 unsigned long highest, lowest; 94 unsigned long highest, lowest, freq;
79 int i; 95 int i;
80 96
81 highest = 0; 97 highest = 0;
82 lowest = ~0UL; 98 lowest = ~0UL;
83 99
84 for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { 100 for_each_frequency(i, rounder, freq) {
85 unsigned long freq = freq_table[i].frequency;
86
87 if (freq == CPUFREQ_ENTRY_INVALID)
88 continue;
89
90 if (freq > highest) 101 if (freq > highest)
91 highest = freq; 102 highest = freq;
92 if (freq < lowest) 103 if (freq < lowest)
93 lowest = freq; 104 lowest = freq;
94 105
95 rate_error = abs(freq - rate); 106 rate_error = abs(freq - rounder->rate);
96 if (rate_error < rate_error_prev) { 107 if (rate_error < rate_error_prev) {
97 rate_best_fit = freq; 108 rate_best_fit = freq;
98 rate_error_prev = rate_error; 109 rate_error_prev = rate_error;
@@ -102,14 +113,41 @@ long clk_rate_table_round(struct clk *clk,
102 break; 113 break;
103 } 114 }
104 115
105 if (rate >= highest) 116 if (rounder->rate >= highest)
106 rate_best_fit = highest; 117 rate_best_fit = highest;
107 if (rate <= lowest) 118 if (rounder->rate <= lowest)
108 rate_best_fit = lowest; 119 rate_best_fit = lowest;
109 120
110 return rate_best_fit; 121 return rate_best_fit;
111} 122}
112 123
124static long clk_rate_table_iter(unsigned int pos,
125 struct clk_rate_round_data *rounder)
126{
127 struct cpufreq_frequency_table *freq_table = rounder->arg;
128 unsigned long freq = freq_table[pos].frequency;
129
130 if (freq == CPUFREQ_ENTRY_INVALID)
131 freq = 0;
132
133 return freq;
134}
135
136long clk_rate_table_round(struct clk *clk,
137 struct cpufreq_frequency_table *freq_table,
138 unsigned long rate)
139{
140 struct clk_rate_round_data table_round = {
141 .min = 0,
142 .max = clk->nr_freqs,
143 .func = clk_rate_table_iter,
144 .arg = freq_table,
145 .rate = rate,
146 };
147
148 return clk_rate_round_helper(&table_round);
149}
150
113int clk_rate_table_find(struct clk *clk, 151int clk_rate_table_find(struct clk *clk,
114 struct cpufreq_frequency_table *freq_table, 152 struct cpufreq_frequency_table *freq_table,
115 unsigned long rate) 153 unsigned long rate)
diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h
index 8ae37707a4a4..49f6e9b6eda2 100644
--- a/include/linux/sh_clk.h
+++ b/include/linux/sh_clk.h
@@ -53,6 +53,7 @@ struct clk {
53 struct dentry *dentry; 53 struct dentry *dentry;
54 struct clk_mapping *mapping; 54 struct clk_mapping *mapping;
55 struct cpufreq_frequency_table *freq_table; 55 struct cpufreq_frequency_table *freq_table;
56 unsigned int nr_freqs;
56}; 57};
57 58
58#define CLK_ENABLE_ON_INIT (1 << 0) 59#define CLK_ENABLE_ON_INIT (1 << 0)