Hi!

On 17/06/15 20:29, Felipe Balbi wrote:
> -             if (dev->speed > 400 ||
> -                            dev->flags & OMAP_I2C_FLAG_FORCE_19200_INT_CLK)
> -                     internal_clk = 19200;

Let's compare, what it waas before in this case...

> -             else if (dev->speed > 100)
> -                     internal_clk = 9600;
> -             else
> -                     internal_clk = 4000;
> +             if (dev->flags & OMAP_I2C_FLAG_FORCE_19200_INT_CLK ||
> +                             dev->speed > 400) {
> +                     internal_clk = 1920000;

Seems that it should be 19200000? Because...

> +                     internal_clk_period = NSECS_PER_SEC /
> +                             internal_clk; /* ns */

520

> +             } else {
> +                     internal_clk = 12000000;
> +                     internal_clk_period = NSECS_PER_SEC /
> +                             internal_clk; /* ns */
> +             }
> +
>               fclk = clk_get(dev->dev, "fck");
> -             fclk_rate = clk_get_rate(fclk) / 1000;
> +             fclk_rate = clk_get_rate(fclk);
>               clk_put(fclk);
>  
>               /* Compute prescaler divisor */
>               psc = fclk_rate / internal_clk;
>               psc = psc - 1;
>  
> +             /*
> +              * Here's the tricky part, we want to make sure our duty cycle
> +              * is as close to 50% as possible. In order to achieve that, we
> +              * will first figure out what's the period on chosen scl is,
> +              * then divide that by two and calculate SCLL and SCLH based on
> +              * that.
> +              *
> +              * SCLL and SCLH equations are as folows:
> +              *
> +              * SCLL = (tLow / iclk_period) - 7;
> +              * SCLH = (tHigh / iclk_period) - 5;
> +              *
> +              * Where iclk_period is period of Internal Clock.
> +              *
> +              * tLow and tHigh will be basically half of scl_period where
> +              * possible as long as we can match I2C spec's minimum limits
> +              * for them.
> +              */
> +             scl_period = NSECS_PER_SEC / (dev->speed * 1000);
> +
>               /* If configured for High Speed */
>               if (dev->speed > 400) {
> -                     unsigned long scl;
> +                     unsigned long fs_period;
> +
> +                     /*
> +                      * first phase of HS mode is up to
> +                      * 400kHz so we will use that.
> +                      */
> +                     fs_period = NSECS_PER_SEC / 400000;
>  
>                       /* For first phase of HS mode */
> -                     scl = internal_clk / 400;

scl=19200/400=48

> -                     fsscll = scl - (scl / 3) - 7;
fsscll=48-16-7=25
> -                     fssclh = (scl / 3) - 5;
fssclh=16-5=11
> +                     fsscll = DIV_ROUND_UP(fs_period >> 1,
> +                                     internal_clk_period) - 7;
> +                     fssclh = (fs_period >> 1) / internal_clk_period - 5;

And with your patch:
fsscll=ROUND_UP(1250/520)-7=-4
fssclh=1250/520-5=-3

Alex.
--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to