From c564e6ae6c5aa6e3995ff87ed4a32b4788ad5109 Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Fri, 13 Mar 2009 13:53:46 +0000 Subject: i2c-s3c2410: Simplify bus frequency calculation The platform data for the i2c-s3c2410 driver used to allow a min, max and desired frequency for the I2C bus. This patch reduces it to simply a desired frequency ceiling and corrects all the uses of the platform data appropriately. This means, for example, that on a system with a 66MHz fclk, a request for 100KHz will achieve 65KHz which is safe and acceptable, rather than 378KHz which it would have achieved without this change. Signed-off-by: Simtec Linux Team Signed-off-by: Daniel Silverstone [ben-linux@fluff.org: tidy subject and description] Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-s3c2410.c | 50 +++++++++------------------------------- 1 file changed, 11 insertions(+), 39 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 9d79756..e10a59e 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -1,6 +1,6 @@ /* linux/drivers/i2c/busses/i2c-s3c2410.c * - * Copyright (C) 2004,2005 Simtec Electronics + * Copyright (C) 2004,2005,2009 Simtec Electronics * Ben Dooks * * S3C2410 I2C Controller @@ -590,18 +590,6 @@ static int s3c24xx_i2c_calcdivisor(unsigned long clkin, unsigned int wanted, return clkin / (calc_divs * calc_div1); } -/* freq_acceptable - * - * test wether a frequency is within the acceptable range of error -*/ - -static inline int freq_acceptable(unsigned int freq, unsigned int wanted) -{ - int diff = freq - wanted; - - return diff >= -2 && diff <= 2; -} - /* s3c24xx_i2c_clockrate * * work out a divisor for the user requested frequency setting, @@ -614,44 +602,28 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got) struct s3c2410_platform_i2c *pdata = i2c->dev->platform_data; unsigned long clkin = clk_get_rate(i2c->clk); unsigned int divs, div1; + unsigned long target_frequency; u32 iiccon; int freq; - int start, end; i2c->clkrate = clkin; clkin /= 1000; /* clkin now in KHz */ - dev_dbg(i2c->dev, "pdata %p, freq %lu %lu..%lu\n", - pdata, pdata->bus_freq, pdata->min_freq, pdata->max_freq); + dev_dbg(i2c->dev, "pdata desired frequency %lu\n", pdata->frequency); - if (pdata->bus_freq != 0) { - freq = s3c24xx_i2c_calcdivisor(clkin, pdata->bus_freq/1000, - &div1, &divs); - if (freq_acceptable(freq, pdata->bus_freq/1000)) - goto found; - } - - /* ok, we may have to search for something suitable... */ - - start = (pdata->max_freq == 0) ? pdata->bus_freq : pdata->max_freq; - end = pdata->min_freq; + target_frequency = pdata->frequency ? pdata->frequency : 100000; - start /= 1000; - end /= 1000; + target_frequency /= 1000; /* Target frequency now in KHz */ - /* search loop... */ + freq = s3c24xx_i2c_calcdivisor(clkin, target_frequency, &div1, &divs); - for (; start > end; start--) { - freq = s3c24xx_i2c_calcdivisor(clkin, start, &div1, &divs); - if (freq_acceptable(freq, start)) - goto found; + if (freq > target_frequency) { + dev_err(i2c->dev, + "Unable to achieve desired frequency %luKHz." \ + " Lowest achievable %dKHz\n", target_frequency, freq); + return -EINVAL; } - /* cannot find frequency spec */ - - return -EINVAL; - - found: *got = freq; iiccon = readl(i2c->regs + S3C2410_IICCON); -- cgit v1.1