]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - drivers/i2c/busses/i2c-octeon.c
i2c: octeon: Move set-clock and init-lowlevel upward
[mirror_ubuntu-artful-kernel.git] / drivers / i2c / busses / i2c-octeon.c
index 46fb6c42934f227ebf5151d37e3f23c0ee10ee10..f647667a3a474447371aec1fc60098eb21cda01d 100644 (file)
@@ -214,6 +214,69 @@ static int octeon_i2c_wait(struct octeon_i2c *i2c)
        return 0;
 }
 
+/* calculate and set clock divisors */
+static void octeon_i2c_set_clock(struct octeon_i2c *i2c)
+{
+       int tclk, thp_base, inc, thp_idx, mdiv_idx, ndiv_idx, foscl, diff;
+       int thp = 0x18, mdiv = 2, ndiv = 0, delta_hz = 1000000;
+
+       for (ndiv_idx = 0; ndiv_idx < 8 && delta_hz != 0; ndiv_idx++) {
+               /*
+                * An mdiv value of less than 2 seems to not work well
+                * with ds1337 RTCs, so we constrain it to larger values.
+                */
+               for (mdiv_idx = 15; mdiv_idx >= 2 && delta_hz != 0; mdiv_idx--) {
+                       /*
+                        * For given ndiv and mdiv values check the
+                        * two closest thp values.
+                        */
+                       tclk = i2c->twsi_freq * (mdiv_idx + 1) * 10;
+                       tclk *= (1 << ndiv_idx);
+                       thp_base = (i2c->sys_freq / (tclk * 2)) - 1;
+
+                       for (inc = 0; inc <= 1; inc++) {
+                               thp_idx = thp_base + inc;
+                               if (thp_idx < 5 || thp_idx > 0xff)
+                                       continue;
+
+                               foscl = i2c->sys_freq / (2 * (thp_idx + 1));
+                               foscl = foscl / (1 << ndiv_idx);
+                               foscl = foscl / (mdiv_idx + 1) / 10;
+                               diff = abs(foscl - i2c->twsi_freq);
+                               if (diff < delta_hz) {
+                                       delta_hz = diff;
+                                       thp = thp_idx;
+                                       mdiv = mdiv_idx;
+                                       ndiv = ndiv_idx;
+                               }
+                       }
+               }
+       }
+       octeon_i2c_write_sw(i2c, SW_TWSI_OP_TWSI_CLK, thp);
+       octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CLKCTL, (mdiv << 3) | ndiv);
+}
+
+static int octeon_i2c_init_lowlevel(struct octeon_i2c *i2c)
+{
+       u8 status;
+       int tries;
+
+       /* disable high level controller, enable bus access */
+       octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB);
+
+       /* reset controller */
+       octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_RST, 0);
+
+       for (tries = 10; tries; tries--) {
+               udelay(1);
+               status = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT);
+               if (status == STAT_IDLE)
+                       return 0;
+       }
+       dev_err(i2c->dev, "%s: TWSI_RST failed! (0x%x)\n", __func__, status);
+       return -EIO;
+}
+
 /**
  * octeon_i2c_start - send START to the bus
  * @i2c: The struct octeon_i2c
@@ -426,72 +489,8 @@ static struct i2c_adapter octeon_i2c_ops = {
        .owner = THIS_MODULE,
        .name = "OCTEON adapter",
        .algo = &octeon_i2c_algo,
-       .timeout = HZ / 50,
 };
 
-/* calculate and set clock divisors */
-static void octeon_i2c_set_clock(struct octeon_i2c *i2c)
-{
-       int tclk, thp_base, inc, thp_idx, mdiv_idx, ndiv_idx, foscl, diff;
-       int thp = 0x18, mdiv = 2, ndiv = 0, delta_hz = 1000000;
-
-       for (ndiv_idx = 0; ndiv_idx < 8 && delta_hz != 0; ndiv_idx++) {
-               /*
-                * An mdiv value of less than 2 seems to not work well
-                * with ds1337 RTCs, so we constrain it to larger values.
-                */
-               for (mdiv_idx = 15; mdiv_idx >= 2 && delta_hz != 0; mdiv_idx--) {
-                       /*
-                        * For given ndiv and mdiv values check the
-                        * two closest thp values.
-                        */
-                       tclk = i2c->twsi_freq * (mdiv_idx + 1) * 10;
-                       tclk *= (1 << ndiv_idx);
-                       thp_base = (i2c->sys_freq / (tclk * 2)) - 1;
-
-                       for (inc = 0; inc <= 1; inc++) {
-                               thp_idx = thp_base + inc;
-                               if (thp_idx < 5 || thp_idx > 0xff)
-                                       continue;
-
-                               foscl = i2c->sys_freq / (2 * (thp_idx + 1));
-                               foscl = foscl / (1 << ndiv_idx);
-                               foscl = foscl / (mdiv_idx + 1) / 10;
-                               diff = abs(foscl - i2c->twsi_freq);
-                               if (diff < delta_hz) {
-                                       delta_hz = diff;
-                                       thp = thp_idx;
-                                       mdiv = mdiv_idx;
-                                       ndiv = ndiv_idx;
-                               }
-                       }
-               }
-       }
-       octeon_i2c_write_sw(i2c, SW_TWSI_OP_TWSI_CLK, thp);
-       octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CLKCTL, (mdiv << 3) | ndiv);
-}
-
-static int octeon_i2c_init_lowlevel(struct octeon_i2c *i2c)
-{
-       u8 status;
-       int tries;
-
-       /* disable high level controller, enable bus access */
-       octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB);
-
-       /* reset controller */
-       octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_RST, 0);
-
-       for (tries = 10; tries; tries--) {
-               udelay(1);
-               status = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT);
-               if (status == STAT_IDLE)
-                       return 0;
-       }
-       dev_err(i2c->dev, "%s: TWSI_RST failed! (0x%x)\n", __func__, status);
-       return -EIO;
-}
-
 static int octeon_i2c_probe(struct platform_device *pdev)
 {
        struct device_node *node = pdev->dev.of_node;
@@ -553,6 +552,8 @@ static int octeon_i2c_probe(struct platform_device *pdev)
        octeon_i2c_set_clock(i2c);
 
        i2c->adap = octeon_i2c_ops;
+       i2c->adap.timeout = msecs_to_jiffies(2);
+       i2c->adap.retries = 5;
        i2c->adap.dev.parent = &pdev->dev;
        i2c->adap.dev.of_node = node;
        i2c_set_adapdata(&i2c->adap, i2c);