Linux-Tegra Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH 1/7] i2c: tegra: remove dead code
@ 2020-07-23 12:18 Krishna Yarlagadda
  2020-07-23 12:18 ` [PATCH 2/7] i2c: tegra: Fix setting of controller ID Krishna Yarlagadda
                   ` (4 more replies)
  0 siblings, 5 replies; 13+ messages in thread
From: Krishna Yarlagadda @ 2020-07-23 12:18 UTC (permalink / raw)
  To: digetx-Re5JQEeQqe8AvxtiuMwx3w, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	thierry.reding-Re5JQEeQqe8AvxtiuMwx3w
  Cc: jonathanh-DDmLM1+adcrQT0dZR+AlfA,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	ldewangan-DDmLM1+adcrQT0dZR+AlfA,
	smohammed-DDmLM1+adcrQT0dZR+AlfA,
	rgumasta-DDmLM1+adcrQT0dZR+AlfA, Krishna Yarlagadda

From: Shardar Shariff Md <smohammed-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>

When I2C_HEADER_CONT_ON_NAK bit in IO header is set then “No ACK
from slave” error is not reported (NACK is considered as ACK
and transfer is continued). So if I2C_ERR_NO_ACK is set, it would
imply I2C_M_IGNORE_NAK is not set and hence this code will never
execute. When I2C_HEADER_CONT_ON_NAK bit in IO header is set then
“No ACK from slave” error is not reported.
Condition (msg->flags & I2C_M_IGNORE_NAK) will never be hit

Signed-off-by: Shardar Shariff Md <smohammed-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Krishna Yarlagadda <kyarlagadda-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/i2c/busses/i2c-tegra.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 1577296..c6c870c 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -1336,11 +1336,8 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 		return -EAGAIN;
 	}
 
-	if (i2c_dev->msg_err == I2C_ERR_NO_ACK) {
-		if (msg->flags & I2C_M_IGNORE_NAK)
-			return 0;
+	if (i2c_dev->msg_err == I2C_ERR_NO_ACK)
 		return -EREMOTEIO;
-	}
 
 	return -EIO;
 }
-- 
2.7.4

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 2/7] i2c: tegra: Fix setting of controller ID
  2020-07-23 12:18 [PATCH 1/7] i2c: tegra: remove dead code Krishna Yarlagadda
@ 2020-07-23 12:18 ` Krishna Yarlagadda
  2020-07-23 12:18 ` [PATCH 4/7] i2c: tegra: add high speed mode support Krishna Yarlagadda
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 13+ messages in thread
From: Krishna Yarlagadda @ 2020-07-23 12:18 UTC (permalink / raw)
  To: digetx, linux-i2c, thierry.reding
  Cc: jonathanh, linux-tegra, linux-kernel, ldewangan, smohammed,
	rgumasta, Krishna Yarlagadda

From: Shardar Shariff Md <smohammed@nvidia.com>

Assign controller id with adapter number as it (cont_id) is passed
through DT(through alias). Mask with controller id mask to avoid
overflow other fields when single device is present and id is -1.

Signed-off-by: Shardar Shariff Md <smohammed@nvidia.com>
Signed-off-by: Krishna Yarlagadda <kyarlagadda@nvidia.com>
---
 drivers/i2c/busses/i2c-tegra.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index c6c870c..a841d6c 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -83,6 +83,7 @@
 #define PACKET_HEADER0_CONT_ID			GENMASK(15, 12)
 #define PACKET_HEADER0_PROTOCOL			GENMASK(7, 4)
 #define PACKET_HEADER0_PROTOCOL_I2C		1
+#define PACKET_HEADER0_CONT_ID_MASK		0xF
 
 #define I2C_HEADER_CONT_ON_NAK			BIT(21)
 #define I2C_HEADER_READ				BIT(19)
@@ -1669,7 +1670,6 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 	i2c_dev->adapter.retries = 1;
 	i2c_dev->adapter.timeout = 6 * HZ;
 	i2c_dev->irq = irq;
-	i2c_dev->cont_id = pdev->id;
 	i2c_dev->dev = &pdev->dev;
 
 	i2c_dev->rst = devm_reset_control_get_exclusive(&pdev->dev, "i2c");
@@ -1807,6 +1807,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 	if (ret)
 		goto release_dma;
 
+	i2c_dev->cont_id = i2c_dev->adapter.nr & PACKET_HEADER0_CONT_ID_MASK;
 	pm_runtime_put(&pdev->dev);
 
 	return 0;
-- 
2.7.4

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 3/7] i2c: tegra: add flag for register write buffering
       [not found] ` <1595506733-10307-1-git-send-email-kyarlagadda-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2020-07-23 12:18   ` Krishna Yarlagadda
  2020-07-23 13:17     ` Dmitry Osipenko
  2020-07-23 12:18   ` [PATCH 7/7] i2c: tegra: dump I2C registers on timeout Krishna Yarlagadda
  1 sibling, 1 reply; 13+ messages in thread
From: Krishna Yarlagadda @ 2020-07-23 12:18 UTC (permalink / raw)
  To: digetx-Re5JQEeQqe8AvxtiuMwx3w, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	thierry.reding-Re5JQEeQqe8AvxtiuMwx3w
  Cc: jonathanh-DDmLM1+adcrQT0dZR+AlfA,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	ldewangan-DDmLM1+adcrQT0dZR+AlfA,
	smohammed-DDmLM1+adcrQT0dZR+AlfA,
	rgumasta-DDmLM1+adcrQT0dZR+AlfA, Krishna Yarlagadda

In chips earlier to Tegra186, register write gets buffered. So to make
sure register writes are completed, there is need to readback the
register. Adding flag to disable this readback for Tegra186 and later
chips.

Signed-off-by: Krishna Yarlagadda <kyarlagadda-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/i2c/busses/i2c-tegra.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index a841d6c..bdbbca0 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -220,6 +220,7 @@ struct tegra_i2c_hw_feature {
 	bool has_mst_fifo;
 	const struct i2c_adapter_quirks *quirks;
 	bool supports_bus_clear;
+	bool has_reg_write_buffering;
 	bool has_apb_dma;
 	u8 tlow_std_mode;
 	u8 thigh_std_mode;
@@ -325,8 +326,11 @@ static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val,
 	writel_relaxed(val, i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
 
 	/* Read back register to make sure that register writes completed */
-	if (reg != I2C_TX_FIFO)
-		readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
+	if (i2c_dev->hw->has_reg_write_buffering) {
+		if (reg != I2C_TX_FIFO)
+			readl_relaxed(i2c_dev->base +
+				      tegra_i2c_reg_addr(i2c_dev, reg));
+	}
 }
 
 static u32 i2c_readl(struct tegra_i2c_dev *i2c_dev, unsigned long reg)
@@ -1450,6 +1454,7 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
 	.has_mst_fifo = false,
 	.quirks = &tegra_i2c_quirks,
 	.supports_bus_clear = false,
+	.has_reg_write_buffering = true,
 	.has_apb_dma = true,
 	.tlow_std_mode = 0x4,
 	.thigh_std_mode = 0x2,
@@ -1475,6 +1480,7 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
 	.has_mst_fifo = false,
 	.quirks = &tegra_i2c_quirks,
 	.supports_bus_clear = false,
+	.has_reg_write_buffering = true,
 	.has_apb_dma = true,
 	.tlow_std_mode = 0x4,
 	.thigh_std_mode = 0x2,
@@ -1500,6 +1506,7 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
 	.has_mst_fifo = false,
 	.quirks = &tegra_i2c_quirks,
 	.supports_bus_clear = true,
+	.has_reg_write_buffering = true,
 	.has_apb_dma = true,
 	.tlow_std_mode = 0x4,
 	.thigh_std_mode = 0x2,
@@ -1525,6 +1532,7 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
 	.has_mst_fifo = false,
 	.quirks = &tegra_i2c_quirks,
 	.supports_bus_clear = true,
+	.has_reg_write_buffering = true,
 	.has_apb_dma = true,
 	.tlow_std_mode = 0x4,
 	.thigh_std_mode = 0x2,
@@ -1550,6 +1558,7 @@ static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
 	.has_mst_fifo = false,
 	.quirks = &tegra_i2c_quirks,
 	.supports_bus_clear = true,
+	.has_reg_write_buffering = true,
 	.has_apb_dma = true,
 	.tlow_std_mode = 0x4,
 	.thigh_std_mode = 0x2,
@@ -1575,6 +1584,7 @@ static const struct tegra_i2c_hw_feature tegra186_i2c_hw = {
 	.has_mst_fifo = false,
 	.quirks = &tegra_i2c_quirks,
 	.supports_bus_clear = true,
+	.has_reg_write_buffering = false,
 	.has_apb_dma = false,
 	.tlow_std_mode = 0x4,
 	.thigh_std_mode = 0x3,
@@ -1600,6 +1610,7 @@ static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
 	.has_mst_fifo = true,
 	.quirks = &tegra194_i2c_quirks,
 	.supports_bus_clear = true,
+	.has_reg_write_buffering = false,
 	.has_apb_dma = false,
 	.tlow_std_mode = 0x8,
 	.thigh_std_mode = 0x7,
-- 
2.7.4

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 4/7] i2c: tegra: add high speed mode support
  2020-07-23 12:18 [PATCH 1/7] i2c: tegra: remove dead code Krishna Yarlagadda
  2020-07-23 12:18 ` [PATCH 2/7] i2c: tegra: Fix setting of controller ID Krishna Yarlagadda
@ 2020-07-23 12:18 ` Krishna Yarlagadda
       [not found]   ` <1595506733-10307-4-git-send-email-kyarlagadda-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  2020-07-25 11:26   ` Michał Mirosław
  2020-07-23 12:18 ` [PATCH 5/7] i2c: tegra: enable second level clock gating Krishna Yarlagadda
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 13+ messages in thread
From: Krishna Yarlagadda @ 2020-07-23 12:18 UTC (permalink / raw)
  To: digetx, linux-i2c, thierry.reding
  Cc: jonathanh, linux-tegra, linux-kernel, ldewangan, smohammed,
	rgumasta, Krishna Yarlagadda

From: Shardar Shariff Md <smohammed@nvidia.com>

Add high speed mode support

Signed-off-by: Shardar Shariff Md <smohammed@nvidia.com>
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Signed-off-by: Krishna Yarlagadda <kyarlagadda@nvidia.com>
---
 drivers/i2c/busses/i2c-tegra.c | 64 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 56 insertions(+), 8 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index bdbbca0..2f654ed 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -85,12 +85,14 @@
 #define PACKET_HEADER0_PROTOCOL_I2C		1
 #define PACKET_HEADER0_CONT_ID_MASK		0xF
 
+#define I2C_HEADER_HIGHSPEED_MODE		BIT(22)
 #define I2C_HEADER_CONT_ON_NAK			BIT(21)
 #define I2C_HEADER_READ				BIT(19)
 #define I2C_HEADER_10BIT_ADDR			BIT(18)
 #define I2C_HEADER_IE_ENABLE			BIT(17)
 #define I2C_HEADER_REPEAT_START			BIT(16)
 #define I2C_HEADER_CONTINUE_XFER		BIT(15)
+#define I2C_HEADER_MASTER_ADDR_SHIFT		12
 #define I2C_HEADER_SLAVE_ADDR_SHIFT		1
 
 #define I2C_BUS_CLEAR_CNFG			0x084
@@ -136,6 +138,7 @@
 
 /* configuration load timeout in microseconds */
 #define I2C_CONFIG_LOAD_TIMEOUT			1000000
+#define I2C_HS_MODE				3500000
 
 /* Packet header size in bytes */
 #define I2C_PACKET_HEADER_SIZE			12
@@ -215,12 +218,14 @@ struct tegra_i2c_hw_feature {
 	int clk_divisor_std_mode;
 	int clk_divisor_fast_mode;
 	u16 clk_divisor_fast_plus_mode;
+	int clk_multiplier_hs_mode;
 	bool has_multi_master_mode;
 	bool has_slcg_override_reg;
 	bool has_mst_fifo;
 	const struct i2c_adapter_quirks *quirks;
 	bool supports_bus_clear;
 	bool has_reg_write_buffering;
+	bool has_hs_mode_support;
 	bool has_apb_dma;
 	u8 tlow_std_mode;
 	u8 thigh_std_mode;
@@ -293,6 +298,7 @@ struct tegra_i2c_dev {
 	bool is_curr_dma_xfer;
 	struct completion dma_complete;
 	bool is_curr_atomic_xfer;
+	int clk_divisor_hs_mode;
 };
 
 static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val,
@@ -778,8 +784,9 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit)
 	if (i2c_dev->is_dvc)
 		tegra_dvc_init(i2c_dev);
 
-	val = I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN |
-	      FIELD_PREP(I2C_CNFG_DEBOUNCE_CNT, 2);
+	val = I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN;
+	if (i2c_dev->bus_clk_rate != I2C_HS_MODE)
+		val |= FIELD_PREP(I2C_CNFG_DEBOUNCE_CNT, 0x2);
 
 	if (i2c_dev->hw->has_multi_master_mode)
 		val |= I2C_CNFG_MULTI_MASTER_MODE;
@@ -791,6 +798,13 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit)
 		tegra_i2c_vi_init(i2c_dev);
 
 	/* Make sure clock divisor programmed correctly */
+	if (i2c_dev->bus_clk_rate == I2C_HS_MODE) {
+		i2c_dev->clk_divisor_hs_mode = i2c_dev->hw->clk_divisor_hs_mode;
+	} else {
+		val = i2c_readl(i2c_dev, I2C_CLK_DIVISOR);
+		i2c_dev->clk_divisor_hs_mode = FIELD_PREP(I2C_CLK_DIVISOR_HSMODE, val);
+	}
+
 	clk_divisor = FIELD_PREP(I2C_CLK_DIVISOR_HSMODE,
 				 i2c_dev->hw->clk_divisor_hs_mode) |
 		      FIELD_PREP(I2C_CLK_DIVISOR_STD_FAST_MODE,
@@ -822,8 +836,13 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit)
 		i2c_writel(i2c_dev, tsu_thd, I2C_INTERFACE_TIMING_1);
 
 	if (!clk_reinit) {
-		clk_multiplier = (tlow + thigh + 2);
-		clk_multiplier *= (i2c_dev->clk_divisor_non_hs_mode + 1);
+		if (i2c_dev->bus_clk_rate == I2C_HS_MODE) {
+			clk_multiplier = i2c_dev->hw->clk_multiplier_hs_mode;
+			clk_multiplier *= (i2c_dev->clk_divisor_hs_mode + 1);
+		} else {
+			clk_multiplier = (tlow + thigh + 2);
+			clk_multiplier *= (i2c_dev->clk_divisor_non_hs_mode + 1);
+		}
 		err = clk_set_rate(i2c_dev->div_clk,
 				   i2c_dev->bus_clk_rate * clk_multiplier);
 		if (err) {
@@ -1244,6 +1263,8 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 		packet_header |= I2C_HEADER_CONT_ON_NAK;
 	if (msg->flags & I2C_M_RD)
 		packet_header |= I2C_HEADER_READ;
+	if (i2c_dev->bus_clk_rate == I2C_HS_MODE)
+		packet_header |= I2C_HEADER_HIGHSPEED_MODE;
 	if (dma && !i2c_dev->msg_read)
 		*buffer++ = packet_header;
 	else
@@ -1448,6 +1469,7 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
 	.clk_divisor_std_mode = 0,
 	.clk_divisor_fast_mode = 0,
 	.clk_divisor_fast_plus_mode = 0,
+	.clk_multiplier_hs_mode = 12,
 	.has_config_load_reg = false,
 	.has_multi_master_mode = false,
 	.has_slcg_override_reg = false,
@@ -1455,6 +1477,7 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
 	.quirks = &tegra_i2c_quirks,
 	.supports_bus_clear = false,
 	.has_reg_write_buffering = true,
+	.has_hs_mode_support = false,
 	.has_apb_dma = true,
 	.tlow_std_mode = 0x4,
 	.thigh_std_mode = 0x2,
@@ -1474,6 +1497,7 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
 	.clk_divisor_std_mode = 0,
 	.clk_divisor_fast_mode = 0,
 	.clk_divisor_fast_plus_mode = 0,
+	.clk_multiplier_hs_mode = 12,
 	.has_config_load_reg = false,
 	.has_multi_master_mode = false,
 	.has_slcg_override_reg = false,
@@ -1481,6 +1505,7 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
 	.quirks = &tegra_i2c_quirks,
 	.supports_bus_clear = false,
 	.has_reg_write_buffering = true,
+	.has_hs_mode_support = false,
 	.has_apb_dma = true,
 	.tlow_std_mode = 0x4,
 	.thigh_std_mode = 0x2,
@@ -1500,6 +1525,7 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
 	.clk_divisor_std_mode = 0x19,
 	.clk_divisor_fast_mode = 0x19,
 	.clk_divisor_fast_plus_mode = 0x10,
+	.clk_multiplier_hs_mode = 3,
 	.has_config_load_reg = false,
 	.has_multi_master_mode = false,
 	.has_slcg_override_reg = false,
@@ -1507,6 +1533,7 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
 	.quirks = &tegra_i2c_quirks,
 	.supports_bus_clear = true,
 	.has_reg_write_buffering = true,
+	.has_hs_mode_support = false,
 	.has_apb_dma = true,
 	.tlow_std_mode = 0x4,
 	.thigh_std_mode = 0x2,
@@ -1522,10 +1549,11 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
 	.has_continue_xfer_support = true,
 	.has_per_pkt_xfer_complete_irq = true,
 	.has_single_clk_source = true,
-	.clk_divisor_hs_mode = 1,
+	.clk_divisor_hs_mode = 2,
 	.clk_divisor_std_mode = 0x19,
 	.clk_divisor_fast_mode = 0x19,
 	.clk_divisor_fast_plus_mode = 0x10,
+	.clk_multiplier_hs_mode = 13,
 	.has_config_load_reg = true,
 	.has_multi_master_mode = false,
 	.has_slcg_override_reg = true,
@@ -1533,6 +1561,7 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
 	.quirks = &tegra_i2c_quirks,
 	.supports_bus_clear = true,
 	.has_reg_write_buffering = true,
+	.has_hs_mode_support = false,
 	.has_apb_dma = true,
 	.tlow_std_mode = 0x4,
 	.thigh_std_mode = 0x2,
@@ -1548,10 +1577,11 @@ static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
 	.has_continue_xfer_support = true,
 	.has_per_pkt_xfer_complete_irq = true,
 	.has_single_clk_source = true,
-	.clk_divisor_hs_mode = 1,
+	.clk_divisor_hs_mode = 2,
 	.clk_divisor_std_mode = 0x19,
 	.clk_divisor_fast_mode = 0x19,
 	.clk_divisor_fast_plus_mode = 0x10,
+	.clk_multiplier_hs_mode = 13,
 	.has_config_load_reg = true,
 	.has_multi_master_mode = false,
 	.has_slcg_override_reg = true,
@@ -1559,6 +1589,7 @@ static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
 	.quirks = &tegra_i2c_quirks,
 	.supports_bus_clear = true,
 	.has_reg_write_buffering = true,
+	.has_hs_mode_support = false,
 	.has_apb_dma = true,
 	.tlow_std_mode = 0x4,
 	.thigh_std_mode = 0x2,
@@ -1574,10 +1605,11 @@ static const struct tegra_i2c_hw_feature tegra186_i2c_hw = {
 	.has_continue_xfer_support = true,
 	.has_per_pkt_xfer_complete_irq = true,
 	.has_single_clk_source = true,
-	.clk_divisor_hs_mode = 1,
+	.clk_divisor_hs_mode = 2,
 	.clk_divisor_std_mode = 0x16,
 	.clk_divisor_fast_mode = 0x19,
 	.clk_divisor_fast_plus_mode = 0x10,
+	.clk_multiplier_hs_mode = 13,
 	.has_config_load_reg = true,
 	.has_multi_master_mode = false,
 	.has_slcg_override_reg = true,
@@ -1585,6 +1617,7 @@ static const struct tegra_i2c_hw_feature tegra186_i2c_hw = {
 	.quirks = &tegra_i2c_quirks,
 	.supports_bus_clear = true,
 	.has_reg_write_buffering = false,
+	.has_hs_mode_support = false,
 	.has_apb_dma = false,
 	.tlow_std_mode = 0x4,
 	.thigh_std_mode = 0x3,
@@ -1600,10 +1633,11 @@ static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
 	.has_continue_xfer_support = true,
 	.has_per_pkt_xfer_complete_irq = true,
 	.has_single_clk_source = true,
-	.clk_divisor_hs_mode = 1,
+	.clk_divisor_hs_mode = 2,
 	.clk_divisor_std_mode = 0x4f,
 	.clk_divisor_fast_mode = 0x3c,
 	.clk_divisor_fast_plus_mode = 0x16,
+	.clk_multiplier_hs_mode = 13,
 	.has_config_load_reg = true,
 	.has_multi_master_mode = true,
 	.has_slcg_override_reg = true,
@@ -1611,6 +1645,7 @@ static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
 	.quirks = &tegra194_i2c_quirks,
 	.supports_bus_clear = true,
 	.has_reg_write_buffering = false,
+	.has_hs_mode_support = true,
 	.has_apb_dma = false,
 	.tlow_std_mode = 0x8,
 	.thigh_std_mode = 0x7,
@@ -1694,8 +1729,21 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 	i2c_dev->hw = of_device_get_match_data(&pdev->dev);
 	i2c_dev->is_dvc = of_device_is_compatible(pdev->dev.of_node,
 						  "nvidia,tegra20-i2c-dvc");
+
+	i2c_dev->hw = of_device_get_match_data(&pdev->dev);
 	i2c_dev->is_vi = of_device_is_compatible(dev->of_node,
 						 "nvidia,tegra210-i2c-vi");
+	if (i2c_dev->bus_clk_rate == I2C_HS_MODE &&
+	    !i2c_dev->hw->has_hs_mode_support) {
+		dev_info(i2c_dev->dev, "HS mode not supported\n");
+		i2c_dev->bus_clk_rate = 100000; /* default clock rate */
+	}
+
+	if (i2c_dev->is_multimaster_mode &&
+	    !i2c_dev->hw->has_multi_master_mode) {
+		dev_info(i2c_dev->dev, "multi-master mode not supported\n");
+		i2c_dev->is_multimaster_mode = false;
+	}
 	i2c_dev->adapter.quirks = i2c_dev->hw->quirks;
 	i2c_dev->dma_buf_size = i2c_dev->adapter.quirks->max_write_len +
 				I2C_PACKET_HEADER_SIZE;
-- 
2.7.4

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 5/7] i2c: tegra: enable second level clock gating
  2020-07-23 12:18 [PATCH 1/7] i2c: tegra: remove dead code Krishna Yarlagadda
  2020-07-23 12:18 ` [PATCH 2/7] i2c: tegra: Fix setting of controller ID Krishna Yarlagadda
  2020-07-23 12:18 ` [PATCH 4/7] i2c: tegra: add high speed mode support Krishna Yarlagadda
@ 2020-07-23 12:18 ` Krishna Yarlagadda
  2020-07-23 14:01   ` Dmitry Osipenko
  2020-07-23 12:18 ` [PATCH 6/7] i2c: tegra: DMA support for t186 and t194 Krishna Yarlagadda
       [not found] ` <1595506733-10307-1-git-send-email-kyarlagadda-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  4 siblings, 1 reply; 13+ messages in thread
From: Krishna Yarlagadda @ 2020-07-23 12:18 UTC (permalink / raw)
  To: digetx, linux-i2c, thierry.reding
  Cc: jonathanh, linux-tegra, linux-kernel, ldewangan, smohammed,
	rgumasta, Krishna Yarlagadda

Enable Second Level Clock Gating feature for supported chips.
With SLCG enabled, software need not control clocks anymore
and leave clocks enabled always on.

Signed-off-by: Shardar Shariff Md <smohammed@nvidia.com>
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Signed-off-by: Krishna Yarlagadda <kyarlagadda@nvidia.com>
---
 drivers/i2c/busses/i2c-tegra.c | 32 ++++++++++++++++++++++++++++----
 1 file changed, 28 insertions(+), 4 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 2f654ed..8ab968e 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -235,6 +235,7 @@ struct tegra_i2c_hw_feature {
 	u32 setup_hold_time_fast_fast_plus_mode;
 	u32 setup_hold_time_hs_mode;
 	bool has_interface_timing_reg;
+	bool has_slcg_support;
 };
 
 /**
@@ -299,6 +300,7 @@ struct tegra_i2c_dev {
 	struct completion dma_complete;
 	bool is_curr_atomic_xfer;
 	int clk_divisor_hs_mode;
+	bool is_clkon_always;
 };
 
 static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val,
@@ -1478,6 +1480,7 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
 	.supports_bus_clear = false,
 	.has_reg_write_buffering = true,
 	.has_hs_mode_support = false,
+	.has_slcg_support = false,
 	.has_apb_dma = true,
 	.tlow_std_mode = 0x4,
 	.thigh_std_mode = 0x2,
@@ -1506,6 +1509,7 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
 	.supports_bus_clear = false,
 	.has_reg_write_buffering = true,
 	.has_hs_mode_support = false,
+	.has_slcg_support = false,
 	.has_apb_dma = true,
 	.tlow_std_mode = 0x4,
 	.thigh_std_mode = 0x2,
@@ -1534,6 +1538,7 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
 	.supports_bus_clear = true,
 	.has_reg_write_buffering = true,
 	.has_hs_mode_support = false,
+	.has_slcg_support = false,
 	.has_apb_dma = true,
 	.tlow_std_mode = 0x4,
 	.thigh_std_mode = 0x2,
@@ -1562,6 +1567,7 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
 	.supports_bus_clear = true,
 	.has_reg_write_buffering = true,
 	.has_hs_mode_support = false,
+	.has_slcg_support = false,
 	.has_apb_dma = true,
 	.tlow_std_mode = 0x4,
 	.thigh_std_mode = 0x2,
@@ -1590,6 +1596,7 @@ static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
 	.supports_bus_clear = true,
 	.has_reg_write_buffering = true,
 	.has_hs_mode_support = false,
+	.has_slcg_support = false,
 	.has_apb_dma = true,
 	.tlow_std_mode = 0x4,
 	.thigh_std_mode = 0x2,
@@ -1618,6 +1625,7 @@ static const struct tegra_i2c_hw_feature tegra186_i2c_hw = {
 	.supports_bus_clear = true,
 	.has_reg_write_buffering = false,
 	.has_hs_mode_support = false,
+	.has_slcg_support = true,
 	.has_apb_dma = false,
 	.tlow_std_mode = 0x4,
 	.thigh_std_mode = 0x3,
@@ -1646,6 +1654,7 @@ static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
 	.supports_bus_clear = true,
 	.has_reg_write_buffering = false,
 	.has_hs_mode_support = true,
+	.has_slcg_support = true,
 	.has_apb_dma = false,
 	.tlow_std_mode = 0x8,
 	.thigh_std_mode = 0x7,
@@ -1822,7 +1831,12 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 		}
 	}
 
-	if (i2c_dev->is_multimaster_mode) {
+	if (i2c_dev->is_multimaster_mode || i2c_dev->hw->has_slcg_support)
+		i2c_dev->is_clkon_always = true;
+	else
+		i2c_dev->is_clkon_always = false;
+
+	if (i2c_dev->is_clkon_always) {
 		ret = clk_enable(i2c_dev->div_clk);
 		if (ret < 0) {
 			dev_err(i2c_dev->dev, "div_clk enable failed %d\n",
@@ -1875,7 +1889,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 	tegra_i2c_release_dma(i2c_dev);
 
 disable_div_clk:
-	if (i2c_dev->is_multimaster_mode)
+	if (i2c_dev->is_clkon_always)
 		clk_disable(i2c_dev->div_clk);
 
 put_rpm:
@@ -1908,7 +1922,7 @@ static int tegra_i2c_remove(struct platform_device *pdev)
 
 	i2c_del_adapter(&i2c_dev->adapter);
 
-	if (i2c_dev->is_multimaster_mode)
+	if (i2c_dev->is_clkon_always)
 		clk_disable(i2c_dev->div_clk);
 
 	pm_runtime_disable(&pdev->dev);
@@ -1932,7 +1946,8 @@ static int __maybe_unused tegra_i2c_suspend(struct device *dev)
 	struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
 	int err = 0;
 
-	i2c_mark_adapter_suspended(&i2c_dev->adapter);
+	if (i2c_dev->is_clkon_always)
+		clk_disable(i2c_dev->div_clk);
 
 	if (!pm_runtime_status_suspended(dev))
 		err = tegra_i2c_runtime_suspend(dev);
@@ -1968,6 +1983,15 @@ static int __maybe_unused tegra_i2c_resume(struct device *dev)
 			return err;
 	}
 
+	if (i2c_dev->is_clkon_always) {
+		err = clk_enable(i2c_dev->div_clk);
+		if (err < 0) {
+			dev_err(i2c_dev->dev, "clock enable failed %d\n",
+				err);
+			return err;
+		}
+	}
+
 	i2c_mark_adapter_resumed(&i2c_dev->adapter);
 
 	return 0;
-- 
2.7.4

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 6/7] i2c: tegra: DMA support for t186 and t194
  2020-07-23 12:18 [PATCH 1/7] i2c: tegra: remove dead code Krishna Yarlagadda
                   ` (2 preceding siblings ...)
  2020-07-23 12:18 ` [PATCH 5/7] i2c: tegra: enable second level clock gating Krishna Yarlagadda
@ 2020-07-23 12:18 ` Krishna Yarlagadda
       [not found]   ` <1595506733-10307-6-git-send-email-kyarlagadda-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
       [not found] ` <1595506733-10307-1-git-send-email-kyarlagadda-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  4 siblings, 1 reply; 13+ messages in thread
From: Krishna Yarlagadda @ 2020-07-23 12:18 UTC (permalink / raw)
  To: digetx, linux-i2c, thierry.reding
  Cc: jonathanh, linux-tegra, linux-kernel, ldewangan, smohammed,
	rgumasta, Krishna Yarlagadda

Enable GPC DMA support for Tegra186 and Tegra194

Signed-off-by: Rajesh Gumasta <rgumasta@nvidia.com>
Signed-off-by: Krishna Yarlagadda <kyarlagadda@nvidia.com>
---
 drivers/i2c/busses/i2c-tegra.c | 25 ++++++++++++++++++++-----
 1 file changed, 20 insertions(+), 5 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 8ab968e..77198fc 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -236,6 +236,7 @@ struct tegra_i2c_hw_feature {
 	u32 setup_hold_time_hs_mode;
 	bool has_interface_timing_reg;
 	bool has_slcg_support;
+	bool has_gpc_dma;
 };
 
 /**
@@ -432,11 +433,18 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev)
 	dma_addr_t dma_phys;
 	int err;
 
-	if (!i2c_dev->hw->has_apb_dma)
-		return 0;
-
-	if (!IS_ENABLED(CONFIG_TEGRA20_APB_DMA)) {
-		dev_dbg(i2c_dev->dev, "Support for APB DMA not enabled!\n");
+	if (i2c_dev->hw->has_gpc_dma) {
+		if (!IS_ENABLED(CONFIG_TEGRA_GPC_DMA)) {
+			dev_dbg(i2c_dev->dev, "Support for GPC DMA not enabled!\n");
+			return 0;
+		}
+	} else if (i2c_dev->hw->has_apb_dma) {
+		if (!IS_ENABLED(CONFIG_TEGRA20_APB_DMA)) {
+			dev_dbg(i2c_dev->dev, "Support for APB DMA not enabled!\n");
+			return 0;
+		}
+	} else {
+		dev_dbg(i2c_dev->dev, "DMA is not enabled!\n");
 		return 0;
 	}
 
@@ -1490,6 +1498,7 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
 	.setup_hold_time_fast_fast_plus_mode = 0x0,
 	.setup_hold_time_hs_mode = 0x0,
 	.has_interface_timing_reg = false,
+	.has_gpc_dma = false,
 };
 
 static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
@@ -1519,6 +1528,7 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
 	.setup_hold_time_fast_fast_plus_mode = 0x0,
 	.setup_hold_time_hs_mode = 0x0,
 	.has_interface_timing_reg = false,
+	.has_gpc_dma = false,
 };
 
 static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
@@ -1548,6 +1558,7 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
 	.setup_hold_time_fast_fast_plus_mode = 0x0,
 	.setup_hold_time_hs_mode = 0x0,
 	.has_interface_timing_reg = false,
+	.has_gpc_dma = false,
 };
 
 static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
@@ -1577,6 +1588,7 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
 	.setup_hold_time_fast_fast_plus_mode = 0x0,
 	.setup_hold_time_hs_mode = 0x0,
 	.has_interface_timing_reg = true,
+	.has_gpc_dma = false,
 };
 
 static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
@@ -1606,6 +1618,7 @@ static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
 	.setup_hold_time_fast_fast_plus_mode = 0,
 	.setup_hold_time_hs_mode = 0,
 	.has_interface_timing_reg = true,
+	.has_gpc_dma = true,
 };
 
 static const struct tegra_i2c_hw_feature tegra186_i2c_hw = {
@@ -1635,6 +1648,7 @@ static const struct tegra_i2c_hw_feature tegra186_i2c_hw = {
 	.setup_hold_time_fast_fast_plus_mode = 0,
 	.setup_hold_time_hs_mode = 0,
 	.has_interface_timing_reg = true,
+	.has_gpc_dma = true,
 };
 
 static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
@@ -1664,6 +1678,7 @@ static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
 	.setup_hold_time_fast_fast_plus_mode = 0x02020202,
 	.setup_hold_time_hs_mode = 0x090909,
 	.has_interface_timing_reg = true,
+	.has_gpc_dma = true,
 };
 
 /* Match table for of_platform binding */
-- 
2.7.4

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 7/7] i2c: tegra: dump I2C registers on timeout
       [not found] ` <1595506733-10307-1-git-send-email-kyarlagadda-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  2020-07-23 12:18   ` [PATCH 3/7] i2c: tegra: add flag for register write buffering Krishna Yarlagadda
@ 2020-07-23 12:18   ` Krishna Yarlagadda
  1 sibling, 0 replies; 13+ messages in thread
From: Krishna Yarlagadda @ 2020-07-23 12:18 UTC (permalink / raw)
  To: digetx-Re5JQEeQqe8AvxtiuMwx3w, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	thierry.reding-Re5JQEeQqe8AvxtiuMwx3w
  Cc: jonathanh-DDmLM1+adcrQT0dZR+AlfA,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	ldewangan-DDmLM1+adcrQT0dZR+AlfA,
	smohammed-DDmLM1+adcrQT0dZR+AlfA,
	rgumasta-DDmLM1+adcrQT0dZR+AlfA, Krishna Yarlagadda

From: Rajesh Gumasta <rgumasta-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>

Dump I2C regsiters for debug when transfer timeout occurs.

Signed-off-by: Rajesh Gumasta <rgumasta-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Krishna Yarlagadda <kyarlagadda-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/i2c/busses/i2c-tegra.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 77198fc..cdc8664 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -126,6 +126,8 @@
 #define  I2C_HS_INTERFACE_TIMING_THD_STA	GENMASK(13, 8)
 #define  I2C_HS_INTERFACE_TIMING_TSU_STA	GENMASK(5, 0)
 
+#define I2C_MST_PACKET_TRANSFER_CNT_STATUS	0x0b0
+
 #define I2C_MST_FIFO_CONTROL			0x0b4
 #define I2C_MST_FIFO_CONTROL_RX_FLUSH		BIT(0)
 #define I2C_MST_FIFO_CONTROL_TX_FLUSH		BIT(1)
@@ -1178,6 +1180,33 @@ static int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap)
 	return -EAGAIN;
 }
 
+static void tegra_i2c_reg_dump(struct tegra_i2c_dev *i2c_dev)
+{
+	dev_dbg(i2c_dev->dev, "--- register dump for debugging ----\n");
+	dev_dbg(i2c_dev->dev, "I2C_CNFG - 0x%x\n",
+		i2c_readl(i2c_dev, I2C_CNFG));
+	dev_dbg(i2c_dev->dev, "I2C_PACKET_TRANSFER_STATUS - 0x%x\n",
+		i2c_readl(i2c_dev, I2C_PACKET_TRANSFER_STATUS));
+	dev_dbg(i2c_dev->dev, "I2C_FIFO_CONTROL - 0x%x\n",
+		i2c_readl(i2c_dev, I2C_FIFO_CONTROL));
+	dev_dbg(i2c_dev->dev, "I2C_FIFO_STATUS - 0x%x\n",
+		i2c_readl(i2c_dev, I2C_FIFO_STATUS));
+
+	if (i2c_dev->hw->has_mst_fifo) {
+		dev_dbg(i2c_dev->dev, "I2C_MST_FIFO_CONTROL - 0x%x\n",
+			i2c_readl(i2c_dev, I2C_MST_FIFO_CONTROL));
+		dev_dbg(i2c_dev->dev, "I2C_MST_FIFO_STATUS - 0x%x\n",
+			i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS));
+		dev_dbg(i2c_dev->dev, "I2C_MST_PACKET_TRANSFER_CNT - 0x%x\n",
+			i2c_readl(i2c_dev,
+				  I2C_MST_PACKET_TRANSFER_CNT_STATUS));
+	}
+	dev_dbg(i2c_dev->dev, "I2C_INT_MASK - 0x%x\n",
+		i2c_readl(i2c_dev, I2C_INT_MASK));
+	dev_dbg(i2c_dev->dev, "I2C_INT_STATUS - 0x%x\n",
+		i2c_readl(i2c_dev, I2C_INT_STATUS));
+}
+
 static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 			      struct i2c_msg *msg,
 			      enum msg_end_type end_state)
@@ -1331,6 +1360,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 
 		if (!time_left && !completion_done(&i2c_dev->dma_complete)) {
 			dev_err(i2c_dev->dev, "DMA transfer timeout\n");
+			tegra_i2c_reg_dump(i2c_dev);
 			tegra_i2c_init(i2c_dev, true);
 			return -ETIMEDOUT;
 		}
@@ -1352,6 +1382,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 
 	if (time_left == 0) {
 		dev_err(i2c_dev->dev, "i2c transfer timed out\n");
+		tegra_i2c_reg_dump(i2c_dev);
 		tegra_i2c_init(i2c_dev, true);
 		return -ETIMEDOUT;
 	}
-- 
2.7.4

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 6/7] i2c: tegra: DMA support for t186 and t194
       [not found]   ` <1595506733-10307-6-git-send-email-kyarlagadda-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2020-07-23 13:16     ` Dmitry Osipenko
  2020-07-23 13:38     ` Dmitry Osipenko
  1 sibling, 0 replies; 13+ messages in thread
From: Dmitry Osipenko @ 2020-07-23 13:16 UTC (permalink / raw)
  To: Krishna Yarlagadda, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	thierry.reding-Re5JQEeQqe8AvxtiuMwx3w
  Cc: jonathanh-DDmLM1+adcrQT0dZR+AlfA,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	ldewangan-DDmLM1+adcrQT0dZR+AlfA,
	smohammed-DDmLM1+adcrQT0dZR+AlfA,
	rgumasta-DDmLM1+adcrQT0dZR+AlfA

Hello Krishna,

23.07.2020 15:18, Krishna Yarlagadda пишет:
...
>  static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
> @@ -1606,6 +1618,7 @@ static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
>  	.setup_hold_time_fast_fast_plus_mode = 0,
>  	.setup_hold_time_hs_mode = 0,
>  	.has_interface_timing_reg = true,
> +	.has_gpc_dma = true,

false

>  };

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 3/7] i2c: tegra: add flag for register write buffering
  2020-07-23 12:18   ` [PATCH 3/7] i2c: tegra: add flag for register write buffering Krishna Yarlagadda
@ 2020-07-23 13:17     ` Dmitry Osipenko
  0 siblings, 0 replies; 13+ messages in thread
From: Dmitry Osipenko @ 2020-07-23 13:17 UTC (permalink / raw)
  To: Krishna Yarlagadda, linux-i2c, thierry.reding
  Cc: jonathanh, linux-tegra, linux-kernel, ldewangan, smohammed, rgumasta

23.07.2020 15:18, Krishna Yarlagadda пишет:
> In chips earlier to Tegra186, register write gets buffered. So to make
> sure register writes are completed, there is need to readback the
> register. Adding flag to disable this readback for Tegra186 and later
> chips.
> 
> Signed-off-by: Krishna Yarlagadda <kyarlagadda@nvidia.com>
> ---
>  drivers/i2c/busses/i2c-tegra.c | 15 +++++++++++++--
>  1 file changed, 13 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
> index a841d6c..bdbbca0 100644
> --- a/drivers/i2c/busses/i2c-tegra.c
> +++ b/drivers/i2c/busses/i2c-tegra.c
> @@ -220,6 +220,7 @@ struct tegra_i2c_hw_feature {
>  	bool has_mst_fifo;
>  	const struct i2c_adapter_quirks *quirks;
>  	bool supports_bus_clear;
> +	bool has_reg_write_buffering;
>  	bool has_apb_dma;
>  	u8 tlow_std_mode;
>  	u8 thigh_std_mode;
> @@ -325,8 +326,11 @@ static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val,
>  	writel_relaxed(val, i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
>  
>  	/* Read back register to make sure that register writes completed */
> -	if (reg != I2C_TX_FIFO)
> -		readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
> +	if (i2c_dev->hw->has_reg_write_buffering) {
> +		if (reg != I2C_TX_FIFO)

Should be single line.

What problem does this solve? If there is no visible effect, then please
drop this patch.

> +			readl_relaxed(i2c_dev->base +
> +				      tegra_i2c_reg_addr(i2c_dev, reg));
> +	}

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 4/7] i2c: tegra: add high speed mode support
       [not found]   ` <1595506733-10307-4-git-send-email-kyarlagadda-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2020-07-23 13:27     ` Dmitry Osipenko
  0 siblings, 0 replies; 13+ messages in thread
From: Dmitry Osipenko @ 2020-07-23 13:27 UTC (permalink / raw)
  To: Krishna Yarlagadda, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	thierry.reding-Re5JQEeQqe8AvxtiuMwx3w
  Cc: jonathanh-DDmLM1+adcrQT0dZR+AlfA,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	ldewangan-DDmLM1+adcrQT0dZR+AlfA,
	smohammed-DDmLM1+adcrQT0dZR+AlfA,
	rgumasta-DDmLM1+adcrQT0dZR+AlfA

23.07.2020 15:18, Krishna Yarlagadda пишет:
> From: Shardar Shariff Md <smohammed-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> 
> Add high speed mode support
> 
> Signed-off-by: Shardar Shariff Md <smohammed-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> Signed-off-by: Laxman Dewangan <ldewangan-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> Signed-off-by: Krishna Yarlagadda <kyarlagadda-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> ---
>  drivers/i2c/busses/i2c-tegra.c | 64 ++++++++++++++++++++++++++++++++++++------
>  1 file changed, 56 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
> index bdbbca0..2f654ed 100644
> --- a/drivers/i2c/busses/i2c-tegra.c
> +++ b/drivers/i2c/busses/i2c-tegra.c
> @@ -85,12 +85,14 @@
>  #define PACKET_HEADER0_PROTOCOL_I2C		1
>  #define PACKET_HEADER0_CONT_ID_MASK		0xF
>  
> +#define I2C_HEADER_HIGHSPEED_MODE		BIT(22)
>  #define I2C_HEADER_CONT_ON_NAK			BIT(21)
>  #define I2C_HEADER_READ				BIT(19)
>  #define I2C_HEADER_10BIT_ADDR			BIT(18)
>  #define I2C_HEADER_IE_ENABLE			BIT(17)
>  #define I2C_HEADER_REPEAT_START			BIT(16)
>  #define I2C_HEADER_CONTINUE_XFER		BIT(15)
> +#define I2C_HEADER_MASTER_ADDR_SHIFT		12
>  #define I2C_HEADER_SLAVE_ADDR_SHIFT		1
>  
>  #define I2C_BUS_CLEAR_CNFG			0x084
> @@ -136,6 +138,7 @@
>  
>  /* configuration load timeout in microseconds */
>  #define I2C_CONFIG_LOAD_TIMEOUT			1000000
> +#define I2C_HS_MODE				3500000

The I2C_MAX_HIGH_SPEED_MODE_FREQ is 3400000, what is 3500000 then?

https://elixir.bootlin.com/linux/v5.8-rc4/source/include/linux/i2c.h#L42

>  /* Packet header size in bytes */
>  #define I2C_PACKET_HEADER_SIZE			12
> @@ -215,12 +218,14 @@ struct tegra_i2c_hw_feature {
>  	int clk_divisor_std_mode;
>  	int clk_divisor_fast_mode;
>  	u16 clk_divisor_fast_plus_mode;
> +	int clk_multiplier_hs_mode;
>  	bool has_multi_master_mode;
>  	bool has_slcg_override_reg;
>  	bool has_mst_fifo;
>  	const struct i2c_adapter_quirks *quirks;
>  	bool supports_bus_clear;
>  	bool has_reg_write_buffering;
> +	bool has_hs_mode_support;
>  	bool has_apb_dma;
>  	u8 tlow_std_mode;
>  	u8 thigh_std_mode;
> @@ -293,6 +298,7 @@ struct tegra_i2c_dev {
>  	bool is_curr_dma_xfer;
>  	struct completion dma_complete;
>  	bool is_curr_atomic_xfer;
> +	int clk_divisor_hs_mode;
>  };
>  
>  static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val,
> @@ -778,8 +784,9 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit)
>  	if (i2c_dev->is_dvc)
>  		tegra_dvc_init(i2c_dev);
>  
> -	val = I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN |
> -	      FIELD_PREP(I2C_CNFG_DEBOUNCE_CNT, 2);
> +	val = I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN;
> +	if (i2c_dev->bus_clk_rate != I2C_HS_MODE)
> +		val |= FIELD_PREP(I2C_CNFG_DEBOUNCE_CNT, 0x2);
>  
>  	if (i2c_dev->hw->has_multi_master_mode)
>  		val |= I2C_CNFG_MULTI_MASTER_MODE;
> @@ -791,6 +798,13 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit)
>  		tegra_i2c_vi_init(i2c_dev);
>  
>  	/* Make sure clock divisor programmed correctly */
> +	if (i2c_dev->bus_clk_rate == I2C_HS_MODE) {
> +		i2c_dev->clk_divisor_hs_mode = i2c_dev->hw->clk_divisor_hs_mode;
> +	} else {
> +		val = i2c_readl(i2c_dev, I2C_CLK_DIVISOR);
> +		i2c_dev->clk_divisor_hs_mode = FIELD_PREP(I2C_CLK_DIVISOR_HSMODE, val);

FIELD_PREP?

clk_divisor_hs_mode should be a local variable and I don't think its
value needs to be read out from hardware.

> +	}
> +
>  	clk_divisor = FIELD_PREP(I2C_CLK_DIVISOR_HSMODE,
>  				 i2c_dev->hw->clk_divisor_hs_mode) |
>  		      FIELD_PREP(I2C_CLK_DIVISOR_STD_FAST_MODE,
> @@ -822,8 +836,13 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit)
>  		i2c_writel(i2c_dev, tsu_thd, I2C_INTERFACE_TIMING_1);
>  
>  	if (!clk_reinit) {
> -		clk_multiplier = (tlow + thigh + 2);
> -		clk_multiplier *= (i2c_dev->clk_divisor_non_hs_mode + 1);
> +		if (i2c_dev->bus_clk_rate == I2C_HS_MODE) {
> +			clk_multiplier = i2c_dev->hw->clk_multiplier_hs_mode;
> +			clk_multiplier *= (i2c_dev->clk_divisor_hs_mode + 1);

Actually, clk_divisor_hs_mode variable shouldn't be needed at all, use
hw->clk_divisor_hs_mode directly.

> +		} else {
> +			clk_multiplier = (tlow + thigh + 2);
> +			clk_multiplier *= (i2c_dev->clk_divisor_non_hs_mode + 1);
> +		}
>  		err = clk_set_rate(i2c_dev->div_clk,
>  				   i2c_dev->bus_clk_rate * clk_multiplier);
>  		if (err) {
> @@ -1244,6 +1263,8 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
>  		packet_header |= I2C_HEADER_CONT_ON_NAK;
>  	if (msg->flags & I2C_M_RD)
>  		packet_header |= I2C_HEADER_READ;
> +	if (i2c_dev->bus_clk_rate == I2C_HS_MODE)
> +		packet_header |= I2C_HEADER_HIGHSPEED_MODE;
>  	if (dma && !i2c_dev->msg_read)
>  		*buffer++ = packet_header;
>  	else
> @@ -1448,6 +1469,7 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
>  	.clk_divisor_std_mode = 0,
>  	.clk_divisor_fast_mode = 0,
>  	.clk_divisor_fast_plus_mode = 0,
> +	.clk_multiplier_hs_mode = 12,
>  	.has_config_load_reg = false,
>  	.has_multi_master_mode = false,
>  	.has_slcg_override_reg = false,
> @@ -1455,6 +1477,7 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
>  	.quirks = &tegra_i2c_quirks,
>  	.supports_bus_clear = false,
>  	.has_reg_write_buffering = true,
> +	.has_hs_mode_support = false,
>  	.has_apb_dma = true,
>  	.tlow_std_mode = 0x4,
>  	.thigh_std_mode = 0x2,
> @@ -1474,6 +1497,7 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
>  	.clk_divisor_std_mode = 0,
>  	.clk_divisor_fast_mode = 0,
>  	.clk_divisor_fast_plus_mode = 0,
> +	.clk_multiplier_hs_mode = 12,
>  	.has_config_load_reg = false,
>  	.has_multi_master_mode = false,
>  	.has_slcg_override_reg = false,
> @@ -1481,6 +1505,7 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
>  	.quirks = &tegra_i2c_quirks,
>  	.supports_bus_clear = false,
>  	.has_reg_write_buffering = true,
> +	.has_hs_mode_support = false,
>  	.has_apb_dma = true,
>  	.tlow_std_mode = 0x4,
>  	.thigh_std_mode = 0x2,
> @@ -1500,6 +1525,7 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
>  	.clk_divisor_std_mode = 0x19,
>  	.clk_divisor_fast_mode = 0x19,
>  	.clk_divisor_fast_plus_mode = 0x10,
> +	.clk_multiplier_hs_mode = 3,

3?

>  	.has_config_load_reg = false,
>  	.has_multi_master_mode = false,
>  	.has_slcg_override_reg = false,
> @@ -1507,6 +1533,7 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
>  	.quirks = &tegra_i2c_quirks,
>  	.supports_bus_clear = true,
>  	.has_reg_write_buffering = true,
> +	.has_hs_mode_support = false,
>  	.has_apb_dma = true,
>  	.tlow_std_mode = 0x4,
>  	.thigh_std_mode = 0x2,
> @@ -1522,10 +1549,11 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
>  	.has_continue_xfer_support = true,
>  	.has_per_pkt_xfer_complete_irq = true,
>  	.has_single_clk_source = true,
> -	.clk_divisor_hs_mode = 1,
> +	.clk_divisor_hs_mode = 2,

Why are you changing this?


...
> +	if (i2c_dev->bus_clk_rate == I2C_HS_MODE &&
> +	    !i2c_dev->hw->has_hs_mode_support) {
> +		dev_info(i2c_dev->dev, "HS mode not supported\n");
> +		i2c_dev->bus_clk_rate = 100000; /* default clock rate */

 I2C_MAX_STANDARD_MODE_FREQ

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 6/7] i2c: tegra: DMA support for t186 and t194
       [not found]   ` <1595506733-10307-6-git-send-email-kyarlagadda-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
  2020-07-23 13:16     ` Dmitry Osipenko
@ 2020-07-23 13:38     ` Dmitry Osipenko
  1 sibling, 0 replies; 13+ messages in thread
From: Dmitry Osipenko @ 2020-07-23 13:38 UTC (permalink / raw)
  To: Krishna Yarlagadda, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	thierry.reding-Re5JQEeQqe8AvxtiuMwx3w
  Cc: jonathanh-DDmLM1+adcrQT0dZR+AlfA,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	ldewangan-DDmLM1+adcrQT0dZR+AlfA,
	smohammed-DDmLM1+adcrQT0dZR+AlfA,
	rgumasta-DDmLM1+adcrQT0dZR+AlfA

23.07.2020 15:18, Krishna Yarlagadda пишет:
> Enable GPC DMA support for Tegra186 and Tegra194
> 
> Signed-off-by: Rajesh Gumasta <rgumasta-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> Signed-off-by: Krishna Yarlagadda <kyarlagadda-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> ---
>  drivers/i2c/busses/i2c-tegra.c | 25 ++++++++++++++++++++-----
>  1 file changed, 20 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
> index 8ab968e..77198fc 100644
> --- a/drivers/i2c/busses/i2c-tegra.c
> +++ b/drivers/i2c/busses/i2c-tegra.c
> @@ -236,6 +236,7 @@ struct tegra_i2c_hw_feature {
>  	u32 setup_hold_time_hs_mode;
>  	bool has_interface_timing_reg;
>  	bool has_slcg_support;
> +	bool has_gpc_dma;
>  };
>  
>  /**
> @@ -432,11 +433,18 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev)
>  	dma_addr_t dma_phys;
>  	int err;
>  
> -	if (!i2c_dev->hw->has_apb_dma)
> -		return 0;
> -
> -	if (!IS_ENABLED(CONFIG_TEGRA20_APB_DMA)) {
> -		dev_dbg(i2c_dev->dev, "Support for APB DMA not enabled!\n");
> +	if (i2c_dev->hw->has_gpc_dma) {
> +		if (!IS_ENABLED(CONFIG_TEGRA_GPC_DMA)) {

Single line, please.

> +			dev_dbg(i2c_dev->dev, "Support for GPC DMA not enabled!\n");
> +			return 0;
> +		}
> +	} else if (i2c_dev->hw->has_apb_dma) {
> +		if (!IS_ENABLED(CONFIG_TEGRA20_APB_DMA)) {

Here too.

> +			dev_dbg(i2c_dev->dev, "Support for APB DMA not enabled!\n");
> +			return 0;
> +		}
> +	} else {
> +		dev_dbg(i2c_dev->dev, "DMA is not enabled!\n");

Also, please drop all the exclamation marks.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 5/7] i2c: tegra: enable second level clock gating
  2020-07-23 12:18 ` [PATCH 5/7] i2c: tegra: enable second level clock gating Krishna Yarlagadda
@ 2020-07-23 14:01   ` Dmitry Osipenko
  0 siblings, 0 replies; 13+ messages in thread
From: Dmitry Osipenko @ 2020-07-23 14:01 UTC (permalink / raw)
  To: Krishna Yarlagadda, linux-i2c, thierry.reding
  Cc: jonathanh, linux-tegra, linux-kernel, ldewangan, smohammed, rgumasta

23.07.2020 15:18, Krishna Yarlagadda пишет:
> Enable Second Level Clock Gating feature for supported chips.
> With SLCG enabled, software need not control clocks anymore
> and leave clocks enabled always on.

What problem is solved by this patch? If there is no real problem, then
I'm not sure that this is a worthwhile patch. Please explain.

...
> @@ -1932,7 +1946,8 @@ static int __maybe_unused tegra_i2c_suspend(struct device *dev)
>  	struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
>  	int err = 0;
>  
> -	i2c_mark_adapter_suspended(&i2c_dev->adapter);

Why i2c_mark_adapter_suspended() is removed?

> +	if (i2c_dev->is_clkon_always)
> +		clk_disable(i2c_dev->div_clk);

Why clk needs to be disabled on suspend?

>  	if (!pm_runtime_status_suspended(dev))
>  		err = tegra_i2c_runtime_suspend(dev);
> @@ -1968,6 +1983,15 @@ static int __maybe_unused tegra_i2c_resume(struct device *dev)
>  			return err;
>  	}
>  
> +	if (i2c_dev->is_clkon_always) {
> +		err = clk_enable(i2c_dev->div_clk);
> +		if (err < 0) {
> +			dev_err(i2c_dev->dev, "clock enable failed %d\n",
> +				err);
> +			return err;
> +		}
> +	}

Would be nice if it all could be wrapped into
tegra_i2c_div_clk_enable/disable() helpers.

>  	i2c_mark_adapter_resumed(&i2c_dev->adapter);
>  
>  	return 0;
> 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 4/7] i2c: tegra: add high speed mode support
  2020-07-23 12:18 ` [PATCH 4/7] i2c: tegra: add high speed mode support Krishna Yarlagadda
       [not found]   ` <1595506733-10307-4-git-send-email-kyarlagadda-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2020-07-25 11:26   ` Michał Mirosław
  1 sibling, 0 replies; 13+ messages in thread
From: Michał Mirosław @ 2020-07-25 11:26 UTC (permalink / raw)
  To: Krishna Yarlagadda
  Cc: digetx, linux-i2c, thierry.reding, jonathanh, linux-tegra,
	linux-kernel, ldewangan, smohammed, rgumasta

On Thu, Jul 23, 2020 at 05:48:50PM +0530, Krishna Yarlagadda wrote:
> From: Shardar Shariff Md <smohammed@nvidia.com>
> 
> Add high speed mode support
[...]
> --- a/drivers/i2c/busses/i2c-tegra.c
> +++ b/drivers/i2c/busses/i2c-tegra.c
[...]
> @@ -215,12 +218,14 @@ struct tegra_i2c_hw_feature {
>  	int clk_divisor_std_mode;
>  	int clk_divisor_fast_mode;
>  	u16 clk_divisor_fast_plus_mode;
> +	int clk_multiplier_hs_mode;
>  	bool has_multi_master_mode;
>  	bool has_slcg_override_reg;
>  	bool has_mst_fifo;
>  	const struct i2c_adapter_quirks *quirks;
>  	bool supports_bus_clear;
>  	bool has_reg_write_buffering;
> +	bool has_hs_mode_support;

This field seems redundant: == !clk_multiplier_hs_mode ?

Best Regards,
Michał Mirosław

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, back to index

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-23 12:18 [PATCH 1/7] i2c: tegra: remove dead code Krishna Yarlagadda
2020-07-23 12:18 ` [PATCH 2/7] i2c: tegra: Fix setting of controller ID Krishna Yarlagadda
2020-07-23 12:18 ` [PATCH 4/7] i2c: tegra: add high speed mode support Krishna Yarlagadda
     [not found]   ` <1595506733-10307-4-git-send-email-kyarlagadda-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2020-07-23 13:27     ` Dmitry Osipenko
2020-07-25 11:26   ` Michał Mirosław
2020-07-23 12:18 ` [PATCH 5/7] i2c: tegra: enable second level clock gating Krishna Yarlagadda
2020-07-23 14:01   ` Dmitry Osipenko
2020-07-23 12:18 ` [PATCH 6/7] i2c: tegra: DMA support for t186 and t194 Krishna Yarlagadda
     [not found]   ` <1595506733-10307-6-git-send-email-kyarlagadda-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2020-07-23 13:16     ` Dmitry Osipenko
2020-07-23 13:38     ` Dmitry Osipenko
     [not found] ` <1595506733-10307-1-git-send-email-kyarlagadda-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2020-07-23 12:18   ` [PATCH 3/7] i2c: tegra: add flag for register write buffering Krishna Yarlagadda
2020-07-23 13:17     ` Dmitry Osipenko
2020-07-23 12:18   ` [PATCH 7/7] i2c: tegra: dump I2C registers on timeout Krishna Yarlagadda

Linux-Tegra Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-tegra/0 linux-tegra/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-tegra linux-tegra/ https://lore.kernel.org/linux-tegra \
		linux-tegra@vger.kernel.org
	public-inbox-index linux-tegra

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-tegra


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git