aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/clk/renesas/rcar-gen3-cpg.c46
1 files changed, 20 insertions, 26 deletions
diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c
index 71b8a986bd48..d4d27cf6110d 100644
--- a/drivers/clk/renesas/rcar-gen3-cpg.c
+++ b/drivers/clk/renesas/rcar-gen3-cpg.c
@@ -60,6 +60,7 @@ struct sd_clock {
60 unsigned int div_num; 60 unsigned int div_num;
61 unsigned int div_min; 61 unsigned int div_min;
62 unsigned int div_max; 62 unsigned int div_max;
63 unsigned int cur_div_idx;
63}; 64};
64 65
65/* SDn divider 66/* SDn divider
@@ -96,21 +97,10 @@ static const struct sd_div_table cpg_sd_div_table[] = {
96static int cpg_sd_clock_enable(struct clk_hw *hw) 97static int cpg_sd_clock_enable(struct clk_hw *hw)
97{ 98{
98 struct sd_clock *clock = to_sd_clock(hw); 99 struct sd_clock *clock = to_sd_clock(hw);
99 u32 val, sd_fc; 100 u32 val = readl(clock->reg);
100 unsigned int i;
101
102 val = readl(clock->reg);
103
104 sd_fc = val & CPG_SD_FC_MASK;
105 for (i = 0; i < clock->div_num; i++)
106 if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK))
107 break;
108
109 if (i >= clock->div_num)
110 return -EINVAL;
111 101
112 val &= ~(CPG_SD_STP_MASK); 102 val &= ~(CPG_SD_STP_MASK);
113 val |= clock->div_table[i].val & CPG_SD_STP_MASK; 103 val |= clock->div_table[clock->cur_div_idx].val & CPG_SD_STP_MASK;
114 104
115 writel(val, clock->reg); 105 writel(val, clock->reg);
116 106
@@ -135,20 +125,9 @@ static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw,
135 unsigned long parent_rate) 125 unsigned long parent_rate)
136{ 126{
137 struct sd_clock *clock = to_sd_clock(hw); 127 struct sd_clock *clock = to_sd_clock(hw);
138 u32 val, sd_fc;
139 unsigned int i;
140
141 val = readl(clock->reg);
142
143 sd_fc = val & CPG_SD_FC_MASK;
144 for (i = 0; i < clock->div_num; i++)
145 if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK))
146 break;
147
148 if (i >= clock->div_num)
149 return -EINVAL;
150 128
151 return DIV_ROUND_CLOSEST(parent_rate, clock->div_table[i].div); 129 return DIV_ROUND_CLOSEST(parent_rate,
130 clock->div_table[clock->cur_div_idx].div);
152} 131}
153 132
154static unsigned int cpg_sd_clock_calc_div(struct sd_clock *clock, 133static unsigned int cpg_sd_clock_calc_div(struct sd_clock *clock,
@@ -189,6 +168,8 @@ static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate,
189 if (i >= clock->div_num) 168 if (i >= clock->div_num)
190 return -EINVAL; 169 return -EINVAL;
191 170
171 clock->cur_div_idx = i;
172
192 val = readl(clock->reg); 173 val = readl(clock->reg);
193 val &= ~(CPG_SD_STP_MASK | CPG_SD_FC_MASK); 174 val &= ~(CPG_SD_STP_MASK | CPG_SD_FC_MASK);
194 val |= clock->div_table[i].val & (CPG_SD_STP_MASK | CPG_SD_FC_MASK); 175 val |= clock->div_table[i].val & (CPG_SD_STP_MASK | CPG_SD_FC_MASK);
@@ -214,6 +195,7 @@ static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core,
214 struct sd_clock *clock; 195 struct sd_clock *clock;
215 struct clk *clk; 196 struct clk *clk;
216 unsigned int i; 197 unsigned int i;
198 u32 sd_fc;
217 199
218 clock = kzalloc(sizeof(*clock), GFP_KERNEL); 200 clock = kzalloc(sizeof(*clock), GFP_KERNEL);
219 if (!clock) 201 if (!clock)
@@ -230,6 +212,18 @@ static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core,
230 clock->div_table = cpg_sd_div_table; 212 clock->div_table = cpg_sd_div_table;
231 clock->div_num = ARRAY_SIZE(cpg_sd_div_table); 213 clock->div_num = ARRAY_SIZE(cpg_sd_div_table);
232 214
215 sd_fc = readl(clock->reg) & CPG_SD_FC_MASK;
216 for (i = 0; i < clock->div_num; i++)
217 if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK))
218 break;
219
220 if (WARN_ON(i >= clock->div_num)) {
221 kfree(clock);
222 return ERR_PTR(-EINVAL);
223 }
224
225 clock->cur_div_idx = i;
226
233 clock->div_max = clock->div_table[0].div; 227 clock->div_max = clock->div_table[0].div;
234 clock->div_min = clock->div_max; 228 clock->div_min = clock->div_max;
235 for (i = 1; i < clock->div_num; i++) { 229 for (i = 1; i < clock->div_num; i++) {