Commit c564e6ae6c5aa6e3995ff87ed4a32b4788ad5109

Authored by Daniel Silverstone
Committed by Ben Dooks
1 parent a192f7153b

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 <linux@simtec.co.uk>
Signed-off-by: Daniel Silverstone <dsilvers@simtec.co.uk>
[ben-linux@fluff.org: tidy subject and description]
Signed-off-by: Ben Dooks <ben-linux@fluff.org>

Showing 7 changed files with 37 additions and 65 deletions Side-by-side Diff

arch/arm/mach-s3c2410/mach-bast.c
... ... @@ -409,8 +409,7 @@
409 409 static struct s3c2410_platform_i2c __initdata bast_i2c_info = {
410 410 .flags = 0,
411 411 .slave_addr = 0x10,
412   - .bus_freq = 100*1000,
413   - .max_freq = 130*1000,
  412 + .frequency = 100*1000,
414 413 };
415 414  
416 415 /* Asix AX88796 10/100 ethernet controller */
arch/arm/mach-s3c2410/mach-n30.c
... ... @@ -340,8 +340,7 @@
340 340 static struct s3c2410_platform_i2c n30_i2ccfg = {
341 341 .flags = 0,
342 342 .slave_addr = 0x10,
343   - .bus_freq = 10*1000,
344   - .max_freq = 10*1000,
  343 + .frequency = 10*1000,
345 344 };
346 345  
347 346 /* Lots of hardcoded stuff, but it sets up the hardware in a useful
arch/arm/mach-s3c2412/mach-jive.c
... ... @@ -453,8 +453,7 @@
453 453 /* I2C bus and device configuration. */
454 454  
455 455 static struct s3c2410_platform_i2c jive_i2c_cfg __initdata = {
456   - .max_freq = 80 * 1000,
457   - .bus_freq = 50 * 1000,
  456 + .frequency = 80 * 1000,
458 457 .flags = S3C_IICFLG_FILTER,
459 458 .sda_delay = 2,
460 459 };
arch/arm/plat-s3c/dev-i2c0.c
1 1 /* linux/arch/arm/plat-s3c/dev-i2c0.c
2 2 *
3   - * Copyright 2008 Simtec Electronics
  3 + * Copyright 2008,2009 Simtec Electronics
4 4 * Ben Dooks <ben@simtec.co.uk>
5 5 * http://armlinux.simtec.co.uk/
6 6 *
... ... @@ -50,8 +50,7 @@
50 50 static struct s3c2410_platform_i2c default_i2c_data0 __initdata = {
51 51 .flags = 0,
52 52 .slave_addr = 0x10,
53   - .bus_freq = 100*1000,
54   - .max_freq = 400*1000,
  53 + .frequency = 100*1000,
55 54 .sda_delay = 100,
56 55 };
57 56  
arch/arm/plat-s3c/dev-i2c1.c
1 1 /* linux/arch/arm/plat-s3c/dev-i2c1.c
2 2 *
3   - * Copyright 2008 Simtec Electronics
  3 + * Copyright 2008,2009 Simtec Electronics
4 4 * Ben Dooks <ben@simtec.co.uk>
5 5 * http://armlinux.simtec.co.uk/
6 6 *
... ... @@ -47,8 +47,7 @@
47 47 .flags = 0,
48 48 .bus_num = 1,
49 49 .slave_addr = 0x10,
50   - .bus_freq = 100*1000,
51   - .max_freq = 400*1000,
  50 + .frequency = 100*1000,
52 51 .sda_delay = 100,
53 52 };
54 53  
arch/arm/plat-s3c/include/plat/iic.h
1   -/* arch/arm/mach-s3c2410/include/mach/iic.h
  1 +/* arch/arm/plat-s3c/include/plat/iic.h
2 2 *
3   - * Copyright (c) 2004 Simtec Electronics
  3 + * Copyright 2004,2009 Simtec Electronics
4 4 * Ben Dooks <ben@simtec.co.uk>
5 5 *
6   - * S3C2410 - I2C Controller platfrom_device info
  6 + * S3C - I2C Controller platform_device info
7 7 *
8 8 * This program is free software; you can redistribute it and/or modify
9 9 * it under the terms of the GNU General Public License version 2 as
10 10  
11 11  
... ... @@ -15,19 +15,24 @@
15 15  
16 16 #define S3C_IICFLG_FILTER (1<<0) /* enable s3c2440 filter */
17 17  
18   -/* Notes:
19   - * 1) All frequencies are expressed in Hz
20   - * 2) A value of zero is `do not care`
21   -*/
22   -
  18 +/**
  19 + * struct s3c2410_platform_i2c - Platform data for s3c I2C.
  20 + * @bus_num: The bus number to use (if possible).
  21 + * @flags: Any flags for the I2C bus (E.g. S3C_IICFLK_FILTER).
  22 + * @slave_addr: The I2C address for the slave device (if enabled).
  23 + * @frequency: The desired frequency in Hz of the bus. This is
  24 + * guaranteed to not be exceeded. If the caller does
  25 + * not care, use zero and the driver will select a
  26 + * useful default.
  27 + * @sda_delay: The delay (in ns) applied to SDA edges.
  28 + * @cfg_gpio: A callback to configure the pins for I2C operation.
  29 + */
23 30 struct s3c2410_platform_i2c {
24   - int bus_num; /* bus number to use */
  31 + int bus_num;
25 32 unsigned int flags;
26   - unsigned int slave_addr; /* slave address for controller */
27   - unsigned long bus_freq; /* standard bus frequency */
28   - unsigned long max_freq; /* max frequency for the bus */
29   - unsigned long min_freq; /* min frequency for the bus */
30   - unsigned int sda_delay; /* pclks (s3c2440 only) */
  33 + unsigned int slave_addr;
  34 + unsigned long frequency;
  35 + unsigned int sda_delay;
31 36  
32 37 void (*cfg_gpio)(struct platform_device *dev);
33 38 };
drivers/i2c/busses/i2c-s3c2410.c
1 1 /* linux/drivers/i2c/busses/i2c-s3c2410.c
2 2 *
3   - * Copyright (C) 2004,2005 Simtec Electronics
  3 + * Copyright (C) 2004,2005,2009 Simtec Electronics
4 4 * Ben Dooks <ben@simtec.co.uk>
5 5 *
6 6 * S3C2410 I2C Controller
... ... @@ -590,18 +590,6 @@
590 590 return clkin / (calc_divs * calc_div1);
591 591 }
592 592  
593   -/* freq_acceptable
594   - *
595   - * test wether a frequency is within the acceptable range of error
596   -*/
597   -
598   -static inline int freq_acceptable(unsigned int freq, unsigned int wanted)
599   -{
600   - int diff = freq - wanted;
601   -
602   - return diff >= -2 && diff <= 2;
603   -}
604   -
605 593 /* s3c24xx_i2c_clockrate
606 594 *
607 595 * work out a divisor for the user requested frequency setting,
608 596  
609 597  
610 598  
611 599  
612 600  
613 601  
614 602  
... ... @@ -614,44 +602,28 @@
614 602 struct s3c2410_platform_i2c *pdata = i2c->dev->platform_data;
615 603 unsigned long clkin = clk_get_rate(i2c->clk);
616 604 unsigned int divs, div1;
  605 + unsigned long target_frequency;
617 606 u32 iiccon;
618 607 int freq;
619   - int start, end;
620 608  
621 609 i2c->clkrate = clkin;
622 610 clkin /= 1000; /* clkin now in KHz */
623 611  
624   - dev_dbg(i2c->dev, "pdata %p, freq %lu %lu..%lu\n",
625   - pdata, pdata->bus_freq, pdata->min_freq, pdata->max_freq);
  612 + dev_dbg(i2c->dev, "pdata desired frequency %lu\n", pdata->frequency);
626 613  
627   - if (pdata->bus_freq != 0) {
628   - freq = s3c24xx_i2c_calcdivisor(clkin, pdata->bus_freq/1000,
629   - &div1, &divs);
630   - if (freq_acceptable(freq, pdata->bus_freq/1000))
631   - goto found;
632   - }
  614 + target_frequency = pdata->frequency ? pdata->frequency : 100000;
633 615  
634   - /* ok, we may have to search for something suitable... */
  616 + target_frequency /= 1000; /* Target frequency now in KHz */
635 617  
636   - start = (pdata->max_freq == 0) ? pdata->bus_freq : pdata->max_freq;
637   - end = pdata->min_freq;
  618 + freq = s3c24xx_i2c_calcdivisor(clkin, target_frequency, &div1, &divs);
638 619  
639   - start /= 1000;
640   - end /= 1000;
641   -
642   - /* search loop... */
643   -
644   - for (; start > end; start--) {
645   - freq = s3c24xx_i2c_calcdivisor(clkin, start, &div1, &divs);
646   - if (freq_acceptable(freq, start))
647   - goto found;
  620 + if (freq > target_frequency) {
  621 + dev_err(i2c->dev,
  622 + "Unable to achieve desired frequency %luKHz." \
  623 + " Lowest achievable %dKHz\n", target_frequency, freq);
  624 + return -EINVAL;
648 625 }
649 626  
650   - /* cannot find frequency spec */
651   -
652   - return -EINVAL;
653   -
654   - found:
655 627 *got = freq;
656 628  
657 629 iiccon = readl(i2c->regs + S3C2410_IICCON);