diff options
-rw-r--r-- | drivers/i2c/busses/i2c-rcar.c | 20 |
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 | ||
275 | ick_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); |