Inter-revision diff: patch 1

Comparing v8 (message) to v9 (message)

--- v8
+++ v9
@@ -1,72 +1,130 @@
-Due to changes in the hardware design of the handshaking signal
-between i2c and dma, it is necessary to reset the handshaking
-signal before each transfer to ensure that the multi-msgs can
-be transferred correctly.
+When clock-div is 0 or greater than 1, the bus speed
+calculated by the old speed calculation formula will be
+larger than the target speed. So we update the formula.
 
 Signed-off-by: Kewei Xu <kewei.xu@mediatek.com>
-Reviewed-by: Qii Wang <qii.wang@mediatek.com>
+Change-Id: Ic0d9b8ab036bcf215d3a5066f2b91c7b8b128ba6
 ---
- drivers/i2c/busses/i2c-mt65xx.c | 26 ++++++++++++++++++++++++++
- 1 file changed, 26 insertions(+)
+ drivers/i2c/busses/i2c-mt65xx.c | 51 +++++++++++++++++++++++++++++++++--------
+ 1 file changed, 41 insertions(+), 10 deletions(-)
 
 diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
-index 72acda59eb39..dad3a85cd499 100644
+index aa4d218..682293e 100644
 --- a/drivers/i2c/busses/i2c-mt65xx.c
 +++ b/drivers/i2c/busses/i2c-mt65xx.c
-@@ -15,6 +15,7 @@
- #include <linux/init.h>
- #include <linux/interrupt.h>
- #include <linux/io.h>
-+#include <linux/iopoll.h>
- #include <linux/kernel.h>
- #include <linux/mm.h>
- #include <linux/module.h>
-@@ -49,6 +50,8 @@
- #define I2C_RD_TRANAC_VALUE		0x0001
- #define I2C_SCL_MIS_COMP_VALUE		0x0000
- #define I2C_CHN_CLR_FLAG		0x0000
-+#define I2C_RELIABILITY		0x0010
-+#define I2C_DMAACK_ENABLE		0x0008
+@@ -67,11 +67,12 @@
  
- #define I2C_DMA_CON_TX			0x0000
- #define I2C_DMA_CON_RX			0x0001
-@@ -851,6 +854,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
- 	u16 restart_flag = 0;
- 	u16 dma_sync = 0;
- 	u32 reg_4g_mode;
-+	u32 reg_dma_reset;
- 	u8 *dma_rd_buf = NULL;
- 	u8 *dma_wr_buf = NULL;
- 	dma_addr_t rpaddr = 0;
-@@ -864,6 +868,28 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
+ #define MAX_SAMPLE_CNT_DIV		8
+ #define MAX_STEP_CNT_DIV		64
+-#define MAX_CLOCK_DIV			256
++#define MAX_CLOCK_DIV_8BITS		256
++#define MAX_CLOCK_DIV_5BITS		32
+ #define MAX_HS_STEP_CNT_DIV		8
+-#define I2C_STANDARD_MODE_BUFFER	(1000 / 2)
+-#define I2C_FAST_MODE_BUFFER		(300 / 2)
+-#define I2C_FAST_MODE_PLUS_BUFFER	(20 / 2)
++#define I2C_STANDARD_MODE_BUFFER	(1000 / 3)
++#define I2C_FAST_MODE_BUFFER		(300 / 3)
++#define I2C_FAST_MODE_PLUS_BUFFER	(20 / 3)
  
- 	reinit_completion(&i2c->msg_complete);
+ #define I2C_CONTROL_RS                  (0x1 << 1)
+ #define I2C_CONTROL_DMA_EN              (0x1 << 2)
+@@ -604,6 +605,31 @@ static int mtk_i2c_max_step_cnt(unsigned int target_speed)
+ 		return MAX_STEP_CNT_DIV;
+ }
  
-+	if (i2c->dev_comp->apdma_sync &&
-+	    i2c->op != I2C_MASTER_WRRD && num > 1) {
-+		mtk_i2c_writew(i2c, 0x00, OFFSET_DEBUGCTRL);
-+		writel(I2C_DMA_HANDSHAKE_RST | I2C_DMA_WARM_RST,
-+		       i2c->pdmabase + OFFSET_RST);
++static int mtk_i2c_get_clk_div_restri(struct mtk_i2c *i2c,
++				      unsigned int sample_cnt)
++{
++	int clk_div_restri = 0;
 +
-+		ret = readw_poll_timeout(i2c->pdmabase + OFFSET_RST,
-+					 reg_dma_reset,
-+					 !(reg_dma_reset & I2C_DMA_WARM_RST),
-+					 0, 100);
-+		if (ret) {
-+			dev_err(i2c->dev, "DMA warm reset timeout\n");
-+			return -ETIMEDOUT;
-+		}
++	if (i2c->dev_comp->ltiming_adjust == 0)
++		return 0;
 +
-+		writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_RST);
-+		mtk_i2c_writew(i2c, I2C_HANDSHAKE_RST, OFFSET_SOFTRESET);
-+		mtk_i2c_writew(i2c, I2C_CHN_CLR_FLAG, OFFSET_SOFTRESET);
-+		mtk_i2c_writew(i2c, I2C_RELIABILITY | I2C_DMAACK_ENABLE,
-+			       OFFSET_DEBUGCTRL);
++	if (sample_cnt == 1) {
++		if (i2c->ac_timing.inter_clk_div == 0)
++			clk_div_restri = 0;
++		else
++			clk_div_restri = 1;
++	} else {
++		if (i2c->ac_timing.inter_clk_div == 0)
++			clk_div_restri = -1;
++		else if (i2c->ac_timing.inter_clk_div == 1)
++			clk_div_restri = 0;
++		else
++			clk_div_restri = 1;
 +	}
 +
- 	control_reg = mtk_i2c_readw(i2c, OFFSET_CONTROL) &
- 			~(I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS);
- 	if ((i2c->speed_hz > I2C_MAX_FAST_MODE_PLUS_FREQ) || (left_num >= 1))
++	return clk_div_restri;
++}
++
+ /*
+  * Check and Calculate i2c ac-timing
+  *
+@@ -732,6 +758,7 @@ static int mtk_i2c_calculate_speed(struct mtk_i2c *i2c, unsigned int clk_src,
+ 	unsigned int best_mul;
+ 	unsigned int cnt_mul;
+ 	int ret = -EINVAL;
++	int clk_div_restri = 0;
+ 
+ 	if (target_speed > I2C_MAX_HIGH_SPEED_MODE_FREQ)
+ 		target_speed = I2C_MAX_HIGH_SPEED_MODE_FREQ;
+@@ -749,7 +776,8 @@ static int mtk_i2c_calculate_speed(struct mtk_i2c *i2c, unsigned int clk_src,
+ 	 * optimizing for sample_cnt * step_cnt being minimal
+ 	 */
+ 	for (sample_cnt = 1; sample_cnt <= MAX_SAMPLE_CNT_DIV; sample_cnt++) {
+-		step_cnt = DIV_ROUND_UP(opt_div, sample_cnt);
++		clk_div_restri = mtk_i2c_get_clk_div_restri(i2c, sample_cnt);
++		step_cnt = DIV_ROUND_UP(opt_div + clk_div_restri, sample_cnt);
+ 		cnt_mul = step_cnt * sample_cnt;
+ 		if (step_cnt > max_step_cnt)
+ 			continue;
+@@ -763,7 +791,7 @@ static int mtk_i2c_calculate_speed(struct mtk_i2c *i2c, unsigned int clk_src,
+ 			best_mul = cnt_mul;
+ 			base_sample_cnt = sample_cnt;
+ 			base_step_cnt = step_cnt;
+-			if (best_mul == opt_div)
++			if (best_mul == (opt_div + clk_div_restri))
+ 				break;
+ 		}
+ 	}
+@@ -774,7 +802,8 @@ static int mtk_i2c_calculate_speed(struct mtk_i2c *i2c, unsigned int clk_src,
+ 	sample_cnt = base_sample_cnt;
+ 	step_cnt = base_step_cnt;
+ 
+-	if ((clk_src / (2 * sample_cnt * step_cnt)) > target_speed) {
++	if ((clk_src / (2 * (sample_cnt * step_cnt - clk_div_restri))) >
++		target_speed) {
+ 		/* In this case, hardware can't support such
+ 		 * low i2c_bus_freq
+ 		 */
+@@ -803,13 +832,16 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int parent_clk)
+ 	target_speed = i2c->speed_hz;
+ 	parent_clk /= i2c->clk_src_div;
+ 
+-	if (i2c->dev_comp->timing_adjust)
+-		max_clk_div = MAX_CLOCK_DIV;
++	if (i2c->dev_comp->timing_adjust && i2c->dev_comp->ltiming_adjust)
++		max_clk_div = MAX_CLOCK_DIV_5BITS;
++	else if (i2c->dev_comp->timing_adjust)
++		max_clk_div = MAX_CLOCK_DIV_8BITS;
+ 	else
+ 		max_clk_div = 1;
+ 
+ 	for (clk_div = 1; clk_div <= max_clk_div; clk_div++) {
+ 		clk_src = parent_clk / clk_div;
++		i2c->ac_timing.inter_clk_div = clk_div - 1;
+ 
+ 		if (target_speed > I2C_MAX_FAST_MODE_PLUS_FREQ) {
+ 			/* Set master code speed register */
+@@ -856,7 +888,6 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int parent_clk)
+ 		break;
+ 	}
+ 
+-	i2c->ac_timing.inter_clk_div = clk_div - 1;
+ 
+ 	return 0;
+ }
 -- 
-2.25.1
+1.9.1
 
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help