aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorWolfram Sang <wsa+renesas@sang-engineering.com>2014-05-02 15:15:15 -0400
committerWolfram Sang <wsa@the-dreams.de>2014-05-22 04:09:24 -0400
commit7663ebefca8079ef0fd2fff1047d3d10af654c78 (patch)
treee9de9c4476c82e08bb29f58c8ccdf9fbfaeb4161 /drivers/i2c
parent6ed7053c2255c34886297b995c6a18607b36d668 (diff)
i2c: sh_mobile: check timing parameters for valid range
Due to misconfiguration, it can happen that the calculated timing parameters are out of range. Bail out if that happens. We can also simplify some logic later because of the verified value. Also, make the printouts of the values more precise by adding the hex-prefixes. Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-sh_mobile.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
index 9f02013eaeeb..b1d399e3e5fc 100644
--- a/drivers/i2c/busses/i2c-sh_mobile.c
+++ b/drivers/i2c/busses/i2c-sh_mobile.c
@@ -232,6 +232,7 @@ static int sh_mobile_i2c_init(struct sh_mobile_i2c_data *pd)
232{ 232{
233 unsigned long i2c_clk_khz; 233 unsigned long i2c_clk_khz;
234 u32 tHIGH, tLOW, tf; 234 u32 tHIGH, tLOW, tf;
235 uint16_t max_val;
235 236
236 /* Get clock rate after clock is enabled */ 237 /* Get clock rate after clock is enabled */
237 clk_prepare_enable(pd->clk); 238 clk_prepare_enable(pd->clk);
@@ -254,15 +255,23 @@ static int sh_mobile_i2c_init(struct sh_mobile_i2c_data *pd)
254 } 255 }
255 256
256 pd->iccl = sh_mobile_i2c_iccl(i2c_clk_khz, tLOW, tf); 257 pd->iccl = sh_mobile_i2c_iccl(i2c_clk_khz, tLOW, tf);
258 pd->icch = sh_mobile_i2c_icch(i2c_clk_khz, tHIGH, tf);
259
260 max_val = pd->flags & IIC_FLAG_HAS_ICIC67 ? 0x1ff : 0xff;
261 if (pd->iccl > max_val || pd->icch > max_val) {
262 dev_err(pd->dev, "timing values out of range: L/H=0x%x/0x%x\n",
263 pd->iccl, pd->icch);
264 return -EINVAL;
265 }
266
257 /* one more bit of ICCL in ICIC */ 267 /* one more bit of ICCL in ICIC */
258 if ((pd->iccl > 0xff) && (pd->flags & IIC_FLAG_HAS_ICIC67)) 268 if (pd->iccl & 0x100)
259 pd->icic |= ICIC_ICCLB8; 269 pd->icic |= ICIC_ICCLB8;
260 else 270 else
261 pd->icic &= ~ICIC_ICCLB8; 271 pd->icic &= ~ICIC_ICCLB8;
262 272
263 pd->icch = sh_mobile_i2c_icch(i2c_clk_khz, tHIGH, tf);
264 /* one more bit of ICCH in ICIC */ 273 /* one more bit of ICCH in ICIC */
265 if ((pd->icch > 0xff) && (pd->flags & IIC_FLAG_HAS_ICIC67)) 274 if (pd->icch & 0x100)
266 pd->icic |= ICIC_ICCHB8; 275 pd->icic |= ICIC_ICCHB8;
267 else 276 else
268 pd->icic &= ~ICIC_ICCHB8; 277 pd->icic &= ~ICIC_ICCHB8;
@@ -717,7 +726,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
717 } 726 }
718 727
719 dev_info(&dev->dev, 728 dev_info(&dev->dev,
720 "I2C adapter %d with bus speed %lu Hz (L/H=%x/%x)\n", 729 "I2C adapter %d with bus speed %lu Hz (L/H=0x%x/0x%x)\n",
721 adap->nr, pd->bus_speed, pd->iccl, pd->icch); 730 adap->nr, pd->bus_speed, pd->iccl, pd->icch);
722 731
723 return 0; 732 return 0;