aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/i2c/busses/i2c-rcar.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index 15eef94927e7..9325db49b4df 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -231,6 +231,7 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
231 u32 round, ick; 231 u32 round, ick;
232 u32 scl; 232 u32 scl;
233 u32 cdf_width; 233 u32 cdf_width;
234 unsigned long rate;
234 235
235 if (!clkp) { 236 if (!clkp) {
236 dev_err(dev, "there is no peripheral_clk\n"); 237 dev_err(dev, "there is no peripheral_clk\n");
@@ -264,15 +265,14 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
264 * clkp : peripheral_clk 265 * clkp : peripheral_clk
265 * F[] : integer up-valuation 266 * F[] : integer up-valuation
266 */ 267 */
267 for (cdf = 0; cdf < (1 << cdf_width); cdf++) { 268 rate = clk_get_rate(clkp);
268 ick = clk_get_rate(clkp) / (1 + cdf); 269 cdf = rate / 20000000;
269 if (ick < 20000000) 270 if (cdf >= 1 << cdf_width) {
270 goto ick_find; 271 dev_err(dev, "Input clock %lu too high\n", rate);
272 return -EIO;
271 } 273 }
272 dev_err(dev, "there is no best CDF\n"); 274 ick = rate / (cdf + 1);
273 return -EIO;
274 275
275ick_find:
276 /* 276 /*
277 * it is impossible to calculate large scale 277 * it is impossible to calculate large scale
278 * number on u32. separate it 278 * number on u32. separate it
@@ -290,6 +290,12 @@ ick_find:
290 * 290 *
291 * Calculation result (= SCL) should be less than 291 * Calculation result (= SCL) should be less than
292 * bus_speed for hardware safety 292 * bus_speed for hardware safety
293 *
294 * We could use something along the lines of
295 * div = ick / (bus_speed + 1) + 1;
296 * scgd = (div - 20 - round + 7) / 8;
297 * scl = ick / (20 + (scgd * 8) + round);
298 * (not fully verified) but that would get pretty involved
293 */ 299 */
294 for (scgd = 0; scgd < 0x40; scgd++) { 300 for (scgd = 0; scgd < 0x40; scgd++) {
295 scl = ick / (20 + (scgd * 8) + round); 301 scl = ick / (20 + (scgd * 8) + round);