Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[firefly-linux-kernel-4.4.55.git] / drivers / i2c / busses / i2c-sh_mobile.c
index 8110ca45f3420f56bb3549bfcd8a2393fb0879d7..b6e7a83a8296e719870efb35f8c456c7caf5f94f 100644 (file)
@@ -120,11 +120,12 @@ struct sh_mobile_i2c_data {
        void __iomem *reg;
        struct i2c_adapter adap;
        unsigned long bus_speed;
+       unsigned int clks_per_count;
        struct clk *clk;
        u_int8_t icic;
-       u_int8_t iccl;
-       u_int8_t icch;
        u_int8_t flags;
+       u_int16_t iccl;
+       u_int16_t icch;
 
        spinlock_t lock;
        wait_queue_head_t wait;
@@ -135,7 +136,8 @@ struct sh_mobile_i2c_data {
 
 #define IIC_FLAG_HAS_ICIC67    (1 << 0)
 
-#define NORMAL_SPEED           100000 /* FAST_SPEED 400000 */
+#define STANDARD_MODE          100000
+#define FAST_MODE              400000
 
 /* Register offsets */
 #define ICDR                   0x00
@@ -187,57 +189,90 @@ static void iic_set_clr(struct sh_mobile_i2c_data *pd, int offs,
        iic_wr(pd, offs, (iic_rd(pd, offs) | set) & ~clr);
 }
 
-static void activate_ch(struct sh_mobile_i2c_data *pd)
+static u32 sh_mobile_i2c_iccl(unsigned long count_khz, u32 tLOW, u32 tf, int offset)
 {
-       unsigned long i2c_clk;
-       u_int32_t num;
-       u_int32_t denom;
-       u_int32_t tmp;
-
-       /* Wake up device and enable clock */
-       pm_runtime_get_sync(pd->dev);
-       clk_enable(pd->clk);
-
-       /* Get clock rate after clock is enabled */
-       i2c_clk = clk_get_rate(pd->clk);
+       /*
+        * Conditional expression:
+        *   ICCL >= COUNT_CLK * (tLOW + tf)
+        *
+        * SH-Mobile IIC hardware starts counting the LOW period of
+        * the SCL signal (tLOW) as soon as it pulls the SCL line.
+        * In order to meet the tLOW timing spec, we need to take into
+        * account the fall time of SCL signal (tf).  Default tf value
+        * should be 0.3 us, for safety.
+        */
+       return (((count_khz * (tLOW + tf)) + 5000) / 10000) + offset;
+}
 
-       /* Calculate the value for iccl. From the data sheet:
-        * iccl = (p clock / transfer rate) * (L / (L + H))
-        * where L and H are the SCL low/high ratio (5/4 in this case).
-        * We also round off the result.
+static u32 sh_mobile_i2c_icch(unsigned long count_khz, u32 tHIGH, u32 tf, int offset)
+{
+       /*
+        * Conditional expression:
+        *   ICCH >= COUNT_CLK * (tHIGH + tf)
+        *
+        * SH-Mobile IIC hardware is aware of SCL transition period 'tr',
+        * and can ignore it.  SH-Mobile IIC controller starts counting
+        * the HIGH period of the SCL signal (tHIGH) after the SCL input
+        * voltage increases at VIH.
+        *
+        * Afterward it turned out calculating ICCH using only tHIGH spec
+        * will result in violation of the tHD;STA timing spec.  We need
+        * to take into account the fall time of SDA signal (tf) at START
+        * condition, in order to meet both tHIGH and tHD;STA specs.
         */
-       num = i2c_clk * 5;
-       denom = pd->bus_speed * 9;
-       tmp = num * 10 / denom;
-       if (tmp % 10 >= 5)
-               pd->iccl = (u_int8_t)((num/denom) + 1);
-       else
-               pd->iccl = (u_int8_t)(num/denom);
+       return (((count_khz * (tHIGH + tf)) + 5000) / 10000) + offset;
+}
 
-       /* one more bit of ICCL in ICIC */
-       if (pd->flags & IIC_FLAG_HAS_ICIC67) {
-               if ((num/denom) > 0xff)
-                       pd->icic |= ICIC_ICCLB8;
-               else
-                       pd->icic &= ~ICIC_ICCLB8;
+static void sh_mobile_i2c_init(struct sh_mobile_i2c_data *pd)
+{
+       unsigned long i2c_clk_khz;
+       u32 tHIGH, tLOW, tf;
+       int offset;
+
+       /* Get clock rate after clock is enabled */
+       clk_enable(pd->clk);
+       i2c_clk_khz = clk_get_rate(pd->clk) / 1000;
+       i2c_clk_khz /= pd->clks_per_count;
+
+       if (pd->bus_speed == STANDARD_MODE) {
+               tLOW    = 47;   /* tLOW = 4.7 us */
+               tHIGH   = 40;   /* tHD;STA = tHIGH = 4.0 us */
+               tf      = 3;    /* tf = 0.3 us */
+               offset  = 0;    /* No offset */
+       } else if (pd->bus_speed == FAST_MODE) {
+               tLOW    = 13;   /* tLOW = 1.3 us */
+               tHIGH   = 6;    /* tHD;STA = tHIGH = 0.6 us */
+               tf      = 3;    /* tf = 0.3 us */
+               offset  = 0;    /* No offset */
+       } else {
+               dev_err(pd->dev, "unrecognized bus speed %lu Hz\n",
+                       pd->bus_speed);
+               goto out;
        }
 
-       /* Calculate the value for icch. From the data sheet:
-          icch = (p clock / transfer rate) * (H / (L + H)) */
-       num = i2c_clk * 4;
-       tmp = num * 10 / denom;
-       if (tmp % 10 >= 5)
-               pd->icch = (u_int8_t)((num/denom) + 1);
+       pd->iccl = sh_mobile_i2c_iccl(i2c_clk_khz, tLOW, tf, offset);
+       /* one more bit of ICCL in ICIC */
+       if ((pd->iccl > 0xff) && (pd->flags & IIC_FLAG_HAS_ICIC67))
+               pd->icic |= ICIC_ICCLB8;
        else
-               pd->icch = (u_int8_t)(num/denom);
+               pd->icic &= ~ICIC_ICCLB8;
 
+       pd->icch = sh_mobile_i2c_icch(i2c_clk_khz, tHIGH, tf, offset);
        /* one more bit of ICCH in ICIC */
-       if (pd->flags & IIC_FLAG_HAS_ICIC67) {
-               if ((num/denom) > 0xff)
-                       pd->icic |= ICIC_ICCHB8;
-               else
-                       pd->icic &= ~ICIC_ICCHB8;
-       }
+       if ((pd->icch > 0xff) && (pd->flags & IIC_FLAG_HAS_ICIC67))
+               pd->icic |= ICIC_ICCHB8;
+       else
+               pd->icic &= ~ICIC_ICCHB8;
+
+out:
+       clk_disable(pd->clk);
+}
+
+static void activate_ch(struct sh_mobile_i2c_data *pd)
+{
+       /* Wake up device and enable clock */
+       pm_runtime_get_sync(pd->dev);
+       clk_enable(pd->clk);
 
        /* Enable channel and configure rx ack */
        iic_set_clr(pd, ICCR, ICCR_ICE, 0);
@@ -246,8 +281,8 @@ static void activate_ch(struct sh_mobile_i2c_data *pd)
        iic_wr(pd, ICIC, 0);
 
        /* Set the clock */
-       iic_wr(pd, ICCL, pd->iccl);
-       iic_wr(pd, ICCH, pd->icch);
+       iic_wr(pd, ICCL, pd->iccl & 0xff);
+       iic_wr(pd, ICCH, pd->icch & 0xff);
 }
 
 static void deactivate_ch(struct sh_mobile_i2c_data *pd)
@@ -434,6 +469,9 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)
                wake_up(&pd->wait);
        }
 
+       /* defeat write posting to avoid spurious WAIT interrupts */
+       iic_rd(pd, ICSR);
+
        return IRQ_HANDLED;
 }
 
@@ -451,8 +489,8 @@ static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg)
        iic_set_clr(pd, ICCR, ICCR_ICE, 0);
 
        /* Set the clock */
-       iic_wr(pd, ICCL, pd->iccl);
-       iic_wr(pd, ICCH, pd->icch);
+       iic_wr(pd, ICCL, pd->iccl & 0xff);
+       iic_wr(pd, ICCH, pd->icch & 0xff);
 
        pd->msg = usr_msg;
        pd->pos = -1;
@@ -621,10 +659,13 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
                goto err_irq;
        }
 
-       /* Use platformd data bus speed or NORMAL_SPEED */
-       pd->bus_speed = NORMAL_SPEED;
+       /* Use platform data bus speed or STANDARD_MODE */
+       pd->bus_speed = STANDARD_MODE;
        if (pdata && pdata->bus_speed)
                pd->bus_speed = pdata->bus_speed;
+       pd->clks_per_count = 1;
+       if (pdata && pdata->clks_per_count)
+               pd->clks_per_count = pdata->clks_per_count;
 
        /* The IIC blocks on SH-Mobile ARM processors
         * come with two new bits in ICIC.
@@ -632,6 +673,8 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
        if (size > 0x17)
                pd->flags |= IIC_FLAG_HAS_ICIC67;
 
+       sh_mobile_i2c_init(pd);
+
        /* Enable Runtime PM for this device.
         *
         * Also tell the Runtime PM core to ignore children
@@ -667,8 +710,9 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
                goto err_all;
        }
 
-       dev_info(&dev->dev, "I2C adapter %d with bus speed %lu Hz\n",
-                adap->nr, pd->bus_speed);
+       dev_info(&dev->dev,
+                "I2C adapter %d with bus speed %lu Hz (L/H=%x/%x)\n",
+                adap->nr, pd->bus_speed, pd->iccl, pd->icch);
 
        of_i2c_register_devices(adap);
        return 0;
@@ -714,7 +758,7 @@ static const struct dev_pm_ops sh_mobile_i2c_dev_pm_ops = {
        .runtime_resume = sh_mobile_i2c_runtime_nop,
 };
 
-static const struct of_device_id sh_mobile_i2c_dt_ids[] __devinitconst = {
+static const struct of_device_id sh_mobile_i2c_dt_ids[] = {
        { .compatible = "renesas,rmobile-iic", },
        {},
 };