[v3,3/4] i2c: qup: Correct duty cycle for FM and FM+

Message ID 1525968837-13381-4-git-send-email-austinwc@codeaurora.org
State New
Headers show
Series
  • Add Fast Mode Plus and other fixes
Related show

Commit Message

Austin Christ May 10, 2018, 4:13 p.m.
The I2C spec UM10204 Rev. 6 specifies the following timings.

           Standard      Fast Mode     Fast Mode Plus
SCL low    4.7us         1.3us         0.5us
SCL high   4.0us         0.6us         0.26us

This results in a 33%/66% duty cycle as opposed to the 50%/50% duty cycle
used for Standard-mode.

Add High Time Divider settings to correct duty cycle for FM(400kHz) and
FM+(1MHz).

Signed-off-by: Austin Christ <austinwc@codeaurora.org>
Reviewed-by: Sricharan R <sricharan@codeaurora.org>
---
v1:
	- Initial
v2:
	- No changes
v3:
	- No changes
---
 drivers/i2c/busses/i2c-qup.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

Comments

Andy Gross May 25, 2018, 8:30 p.m. | #1
On Thu, May 10, 2018 at 10:13:56AM -0600, Austin Christ wrote:
> The I2C spec UM10204 Rev. 6 specifies the following timings.
> 
>            Standard      Fast Mode     Fast Mode Plus
> SCL low    4.7us         1.3us         0.5us
> SCL high   4.0us         0.6us         0.26us
> 
> This results in a 33%/66% duty cycle as opposed to the 50%/50% duty cycle
> used for Standard-mode.
> 
> Add High Time Divider settings to correct duty cycle for FM(400kHz) and
> FM+(1MHz).
> 
> Signed-off-by: Austin Christ <austinwc@codeaurora.org>
> Reviewed-by: Sricharan R <sricharan@codeaurora.org>
> ---

Looks good to me.

Reviewed-by: Andy Gross <andy.gross@linaro.org>

Patch

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index ce5f215..f87f29f 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -1855,9 +1855,15 @@  static int qup_i2c_probe(struct platform_device *pdev)
 	size = QUP_INPUT_FIFO_SIZE(io_mode);
 	qup->in_fifo_sz = qup->in_blk_sz * (2 << size);
 
-	fs_div = ((src_clk_freq / clk_freq) / 2) - 3;
 	hs_div = 3;
-	qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff);
+	if (clk_freq <= I2C_STANDARD_FREQ) {
+		fs_div = ((src_clk_freq / clk_freq) / 2) - 3;
+		qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff);
+	} else {
+		/* 33%/66% duty cycle */
+		fs_div = ((src_clk_freq / clk_freq) - 6) * 2 / 3;
+		qup->clk_ctl = ((fs_div / 2) << 16) | (hs_div << 8) | (fs_div & 0xff);
+	}
 
 	/*
 	 * Time it takes for a byte to be clocked out on the bus.