diff options
-rw-r--r-- | drivers/clk/renesas/rcar-gen3-cpg.c | 46 |
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[] = { | |||
96 | static int cpg_sd_clock_enable(struct clk_hw *hw) | 97 | static 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 | ||
154 | static unsigned int cpg_sd_clock_calc_div(struct sd_clock *clock, | 133 | static 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++) { |