Message ID | 1381244455-3836-1-git-send-email-romainba@abilis.com |
---|---|
State | Changes Requested |
Headers | show |
On Tue, Oct 08, 2013 at 05:00:54PM +0200, Romain Baeriswyl wrote: > static void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable) > @@ -286,6 +287,7 @@ int i2c_dw_init(struct dw_i2c_dev *dev) > u32 input_clock_khz; > u32 hcnt, lcnt; > u32 reg; > + u32 sda_falling_time, scl_falling_time; > > input_clock_khz = dev->get_clk_rate_khz(dev); > > @@ -307,15 +309,25 @@ int i2c_dw_init(struct dw_i2c_dev *dev) > > /* set standard and fast speed deviders for high/low periods */ > > + if (dev->sda_falling_time) > + sda_falling_time = dev->sda_falling_time; > + else > + sda_falling_time = 300; /* ns */ I think this looks better: sda_falling_time = dev->sda_falling_time ? dev->sda_falling_time : 300; > + > + if (dev->scl_falling_time) > + scl_falling_time = dev->scl_falling_time; > + else > + scl_falling_time = 300; /* ns */ Ditto. > + > /* Standard-mode */ > hcnt = i2c_dw_scl_hcnt(input_clock_khz, > - 40, /* tHD;STA = tHIGH = 4.0 us */ > - 3, /* tf = 0.3 us */ > + 4000, /* tHD;STA = tHIGH = 4.0 us */ > + sda_falling_time, > 0, /* 0: DW default, 1: Ideal */ > 0); /* No offset */ > lcnt = i2c_dw_scl_lcnt(input_clock_khz, > - 47, /* tLOW = 4.7 us */ > - 3, /* tf = 0.3 us */ > + 4700, /* tLOW = 4.7 us */ > + scl_falling_time, > 0); /* No offset */ > > /* Allow platforms to specify the ideal HCNT and LCNT values */ -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 09/10/13 18:55, Mika Westerberg wrote: > On Tue, Oct 08, 2013 at 05:00:54PM +0200, Romain Baeriswyl wrote: >> static void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable) >> @@ -286,6 +287,7 @@ int i2c_dw_init(struct dw_i2c_dev *dev) >> u32 input_clock_khz; >> u32 hcnt, lcnt; >> u32 reg; >> + u32 sda_falling_time, scl_falling_time; >> >> input_clock_khz = dev->get_clk_rate_khz(dev); >> >> @@ -307,15 +309,25 @@ int i2c_dw_init(struct dw_i2c_dev *dev) >> >> /* set standard and fast speed deviders for high/low periods */ >> >> + if (dev->sda_falling_time) >> + sda_falling_time = dev->sda_falling_time; >> + else >> + sda_falling_time = 300; /* ns */ > > I think this looks better: > > sda_falling_time = dev->sda_falling_time ? dev->sda_falling_time : 300; You can also use the gcc-ism, which is a bit more concise: sda_falling_time = dev->sda_falling_time ?: 300; ~Ryan -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 10/10/13 9:54 AM, Ryan Mallon wrote: > On 09/10/13 18:55, Mika Westerberg wrote: >> On Tue, Oct 08, 2013 at 05:00:54PM +0200, Romain Baeriswyl wrote: >>> @@ -307,15 +309,25 @@ int i2c_dw_init(struct dw_i2c_dev *dev) >>> >>> /* set standard and fast speed deviders for high/low periods */ >>> >>> + if (dev->sda_falling_time) >>> + sda_falling_time = dev->sda_falling_time; >>> + else >>> + sda_falling_time = 300; /* ns */ >> >> I think this looks better: >> >> sda_falling_time = dev->sda_falling_time ? dev->sda_falling_time : 300; > > You can also use the gcc-ism, which is a bit more concise: > > sda_falling_time = dev->sda_falling_time ?: 300; +1 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
> >You can also use the gcc-ism, which is a bit more concise: > > > > sda_falling_time = dev->sda_falling_time ?: 300; > > +1 ditto
diff --git a/Documentation/devicetree/bindings/i2c/i2c-designware.txt b/Documentation/devicetree/bindings/i2c/i2c-designware.txt index 7fd7fa2..5199b0c 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-designware.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-designware.txt @@ -14,6 +14,12 @@ Optional properties : - i2c-sda-hold-time-ns : should contain the SDA hold time in nanoseconds. This option is only supported in hardware blocks version 1.11a or newer. + - i2c-scl-falling-time : should contain the SCL falling time in nanoseconds. + This value which is by default 300ns is used to compute the tLOW period. + + - i2c-sda-falling-time : should contain the SDA falling time in nanoseconds. + This value which is by default 300ns is used to compute the tHIGH period. + Example : i2c@f0000 { @@ -34,4 +40,6 @@ Example : interrupts = <12 1>; clock-frequency = <400000>; i2c-sda-hold-time-ns = <300>; + i2c-sda-falling-time-ns = <300>; + i2c-scl-falling-time-ns = <300>; }; diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index 3525fc7..50c35f9 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -217,7 +217,7 @@ i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset) * * If your hardware is free from tHD;STA issue, try this one. */ - return (ic_clk * tSYMBOL + 5000) / 10000 - 8 + offset; + return (ic_clk * tSYMBOL + 500000) / 1000000 - 8 + offset; else /* * Conditional expression: @@ -233,7 +233,8 @@ i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset) * The reason why we need to take into account "tf" here, * is the same as described in i2c_dw_scl_lcnt(). */ - return (ic_clk * (tSYMBOL + tf) + 5000) / 10000 - 3 + offset; + return (ic_clk * (tSYMBOL + tf) + 500000) / 1000000 + - 3 + offset; } static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset) @@ -249,7 +250,7 @@ static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset) * account the fall time of SCL signal (tf). Default tf value * should be 0.3 us, for safety. */ - return ((ic_clk * (tLOW + tf) + 5000) / 10000) - 1 + offset; + return ((ic_clk * (tLOW + tf) + 500000) / 1000000) - 1 + offset; } static void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable) @@ -286,6 +287,7 @@ int i2c_dw_init(struct dw_i2c_dev *dev) u32 input_clock_khz; u32 hcnt, lcnt; u32 reg; + u32 sda_falling_time, scl_falling_time; input_clock_khz = dev->get_clk_rate_khz(dev); @@ -307,15 +309,25 @@ int i2c_dw_init(struct dw_i2c_dev *dev) /* set standard and fast speed deviders for high/low periods */ + if (dev->sda_falling_time) + sda_falling_time = dev->sda_falling_time; + else + sda_falling_time = 300; /* ns */ + + if (dev->scl_falling_time) + scl_falling_time = dev->scl_falling_time; + else + scl_falling_time = 300; /* ns */ + /* Standard-mode */ hcnt = i2c_dw_scl_hcnt(input_clock_khz, - 40, /* tHD;STA = tHIGH = 4.0 us */ - 3, /* tf = 0.3 us */ + 4000, /* tHD;STA = tHIGH = 4.0 us */ + sda_falling_time, 0, /* 0: DW default, 1: Ideal */ 0); /* No offset */ lcnt = i2c_dw_scl_lcnt(input_clock_khz, - 47, /* tLOW = 4.7 us */ - 3, /* tf = 0.3 us */ + 4700, /* tLOW = 4.7 us */ + scl_falling_time, 0); /* No offset */ /* Allow platforms to specify the ideal HCNT and LCNT values */ @@ -323,13 +335,13 @@ int i2c_dw_init(struct dw_i2c_dev *dev) /* Fast-mode */ hcnt = i2c_dw_scl_hcnt(input_clock_khz, - 6, /* tHD;STA = tHIGH = 0.6 us */ - 3, /* tf = 0.3 us */ + 600, /* tHD;STA = tHIGH = 0.6 us */ + sda_falling_time, 0, /* 0: DW default, 1: Ideal */ 0); /* No offset */ lcnt = i2c_dw_scl_lcnt(input_clock_khz, - 13, /* tLOW = 1.3 us */ - 3, /* tf = 0.3 us */ + 1300, /* tLOW = 1.3 us */ + scl_falling_time, 0); /* No offset */ if (dev->fs_hcnt && dev->fs_lcnt) { diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index 912aa22..8b9397e 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -91,6 +91,8 @@ struct dw_i2c_dev { unsigned int rx_fifo_depth; int rx_outstanding; u32 sda_hold_time; + u32 sda_falling_time; + u32 scl_falling_time; u16 ss_hcnt; u16 ss_lcnt; u16 fs_hcnt; diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 8b9d3f1..0d6fe47 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -129,6 +129,13 @@ static int dw_i2c_probe(struct platform_device *pdev) "i2c-sda-hold-time-ns", &ht); dev->sda_hold_time = div_u64((u64)ic_clk * ht + 500000, 1000000); + + of_property_read_u32(pdev->dev.of_node, + "i2c-sda-falling-time-ns", + &dev->sda_falling_time); + of_property_read_u32(pdev->dev.of_node, + "i2c-scl-falling-time-ns", + &dev->scl_falling_time); } dev->functionality =