All of lore.kernel.org
 help / color / mirror / Atom feed
From: Luben Tuikov <luben.tuikov@amd.com>
To: amd-gfx@lists.freedesktop.org
Cc: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com>,
	Lijo Lazar <Lijo.Lazar@amd.com>,
	Luben Tuikov <luben.tuikov@amd.com>,
	Stanley Yang <Stanley.Yang@amd.com>,
	Alexander Deucher <Alexander.Deucher@amd.com>,
	Jean Delvare <jdelvare@suse.de>,
	Hawking Zhang <Hawking.Zhang@amd.com>
Subject: [PATCH 18/40] drm/amdgpu: Fix Vega20 I2C to be agnostic (v2)
Date: Tue,  8 Jun 2021 17:39:32 -0400	[thread overview]
Message-ID: <20210608213954.5517-19-luben.tuikov@amd.com> (raw)
In-Reply-To: <20210608213954.5517-1-luben.tuikov@amd.com>

Teach Vega20 I2C to be agnostic. Allow addressing
different devices while the master holds the bus.
Set STOP as per the controller's specification.

v2: Qualify generating ReSTART before the 1st byte
    of the message, when set by the caller, as
    those functions are separated, as caught by
    Andrey G.

Cc: Jean Delvare <jdelvare@suse.de>
Cc: Alexander Deucher <Alexander.Deucher@amd.com>
Cc: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com>
Cc: Lijo Lazar <Lijo.Lazar@amd.com>
Cc: Stanley Yang <Stanley.Yang@amd.com>
Cc: Hawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: Luben Tuikov <luben.tuikov@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c |   4 +-
 drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c | 105 +++++++++++++--------
 2 files changed, 69 insertions(+), 40 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
index fe0e9b0c4d5a38..d02ea083a6c69b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
@@ -41,10 +41,10 @@ int amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap,
 		},
 		{
 			.addr = slave_addr,
-			.flags = read ? I2C_M_RD: 0,
+			.flags = read ? I2C_M_RD : 0,
 			.len = bytes,
 			.buf = eeprom_buf,
-		}
+		},
 	};
 	int r;
 
diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
index 5a90d9351b22eb..b8d6d308fb06a0 100644
--- a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
+++ b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
@@ -41,9 +41,7 @@
 #define I2C_SW_TIMEOUT        8
 #define I2C_ABORT             0x10
 
-/* I2C transaction flags */
-#define I2C_NO_STOP	1
-#define I2C_RESTART	2
+#define I2C_X_RESTART         BIT(31)
 
 #define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
 
@@ -205,9 +203,6 @@ static uint32_t smu_v11_0_i2c_poll_rx_status(struct i2c_adapter *control)
 	return ret;
 }
 
-
-
-
 /**
  * smu_v11_0_i2c_transmit - Send a block of data over the I2C bus to a slave device.
  *
@@ -252,21 +247,22 @@ static uint32_t smu_v11_0_i2c_transmit(struct i2c_adapter *control,
 		reg = RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_STATUS);
 		if (REG_GET_FIELD(reg, CKSVII2C_IC_STATUS, TFNF)) {
 			do {
-				reg = 0;
-				/*
-				 * Prepare transaction, no need to set RESTART. I2C engine will send
-				 * START as soon as it sees data in TXFIFO
-				 */
-				if (bytes_sent == 0)
-					reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, RESTART,
-							    (i2c_flag & I2C_RESTART) ? 1 : 0);
 				reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, DAT, data[bytes_sent]);
 
-				/* determine if we need to send STOP bit or not */
-				if (numbytes == 1)
-					/* Final transaction, so send stop unless I2C_NO_STOP */
-					reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, STOP,
-							    (i2c_flag & I2C_NO_STOP) ? 0 : 1);
+				/* Final message, final byte, must
+				 * generate a STOP, to release the
+				 * bus, i.e. don't hold SCL low.
+				 */
+				if (numbytes == 1 && i2c_flag & I2C_M_STOP)
+					reg = REG_SET_FIELD(reg,
+							    CKSVII2C_IC_DATA_CMD,
+							    STOP, 1);
+
+				if (bytes_sent == 0 && i2c_flag & I2C_X_RESTART)
+					reg = REG_SET_FIELD(reg,
+							    CKSVII2C_IC_DATA_CMD,
+							    RESTART, 1);
+
 				/* Write */
 				reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, CMD, 0);
 				WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_DATA_CMD, reg);
@@ -341,23 +337,21 @@ static uint32_t smu_v11_0_i2c_receive(struct i2c_adapter *control,
 
 		smu_v11_0_i2c_clear_status(control);
 
-
 		/* Prepare transaction */
-
-		/* Each time we disable I2C, so this is not a restart */
-		if (bytes_received == 0)
-			reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, RESTART,
-					    (i2c_flag & I2C_RESTART) ? 1 : 0);
-
 		reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, DAT, 0);
 		/* Read */
 		reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, CMD, 1);
 
-		/* Transmitting last byte */
-		if (numbytes == 1)
-			/* Final transaction, so send stop if requested */
-			reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD, STOP,
-					    (i2c_flag & I2C_NO_STOP) ? 0 : 1);
+		/* Final message, final byte, must generate a STOP
+		 * to release the bus, i.e. don't hold SCL low.
+		 */
+		if (numbytes == 1 && i2c_flag & I2C_M_STOP)
+			reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD,
+					    STOP, 1);
+
+		if (bytes_received == 0 && i2c_flag & I2C_X_RESTART)
+			reg = REG_SET_FIELD(reg, CKSVII2C_IC_DATA_CMD,
+					    RESTART, 1);
 
 		WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_DATA_CMD, reg);
 
@@ -591,23 +585,59 @@ static const struct i2c_lock_operations smu_v11_0_i2c_i2c_lock_ops = {
 };
 
 static int smu_v11_0_i2c_xfer(struct i2c_adapter *i2c_adap,
-			      struct i2c_msg *msgs, int num)
+			      struct i2c_msg *msg, int num)
 {
 	int i, ret;
+	u16 addr, dir;
 
 	smu_v11_0_i2c_init(i2c_adap);
 
+	/* From the client's point of view, this sequence of
+	 * messages-- the array i2c_msg *msg, is a single transaction
+	 * on the bus, starting with START and ending with STOP.
+	 *
+	 * The client is welcome to send any sequence of messages in
+	 * this array, as processing under this function here is
+	 * striving to be agnostic.
+	 *
+	 * Record the first address and direction we see. If either
+	 * changes for a subsequent message, generate ReSTART. The
+	 * DW_apb_i2c databook, v1.21a, specifies that ReSTART is
+	 * generated when the direction changes, with the default IP
+	 * block parameter settings, but it doesn't specify if ReSTART
+	 * is generated when the address changes (possibly...). We
+	 * don't rely on the default IP block parameter settings as
+	 * the block is shared and they may change.
+	 */
+	if (num > 0) {
+		addr = msg[0].addr;
+		dir  = msg[0].flags & I2C_M_RD;
+	}
+
 	for (i = 0; i < num; i++) {
-		uint32_t i2c_flag = ((msgs[i].flags & I2C_M_NOSTART) ? 0 : I2C_RESTART) ||
-				    (((msgs[i].flags & I2C_M_STOP) ? 0 : I2C_NO_STOP));
+		u32 i2c_flag = 0;
 
-		if (msgs[i].flags & I2C_M_RD)
+		if (msg[i].addr != addr || (msg[i].flags ^ dir) & I2C_M_RD) {
+			addr = msg[i].addr;
+			dir  = msg[i].flags & I2C_M_RD;
+			i2c_flag |= I2C_X_RESTART;
+		}
+
+		if (i == num - 1) {
+			/* Set the STOP bit on the last message, so
+			 * that the IP block generates a STOP after
+			 * the last byte of the message.
+			 */
+			i2c_flag |= I2C_M_STOP;
+		}
+
+		if (msg[i].flags & I2C_M_RD)
 			ret = smu_v11_0_i2c_read_data(i2c_adap,
-						      msgs + i,
+						      msg + i,
 						      i2c_flag);
 		else
 			ret = smu_v11_0_i2c_write_data(i2c_adap,
-						       msgs + i,
+						       msg + i,
 						       i2c_flag);
 
 		if (ret != I2C_OK) {
@@ -625,7 +655,6 @@ static u32 smu_v11_0_i2c_func(struct i2c_adapter *adap)
 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
-
 static const struct i2c_algorithm smu_v11_0_i2c_algo = {
 	.master_xfer = smu_v11_0_i2c_xfer,
 	.functionality = smu_v11_0_i2c_func,
-- 
2.32.0

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

  parent reply	other threads:[~2021-06-08 21:40 UTC|newest]

Thread overview: 75+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-08 21:39 [PATCH 00/40] I2C fixes Luben Tuikov
2021-06-08 21:39 ` [PATCH 01/40] drm/amdgpu: add a mutex for the smu11 i2c bus (v2) Luben Tuikov
2021-06-08 21:39 ` [PATCH 02/40] drm/amdgpu/pm: rework i2c xfers on sienna cichlid (v3) Luben Tuikov
2021-06-08 21:39 ` [PATCH 03/40] drm/amdgpu/pm: rework i2c xfers on arcturus (v3) Luben Tuikov
2021-06-08 21:39 ` [PATCH 04/40] drm/amdgpu/pm: add smu i2c implementation for navi1x (v3) Luben Tuikov
2021-06-08 21:39 ` [PATCH 05/40] drm/amdgpu: add new helper for handling EEPROM i2c transfers Luben Tuikov
2021-06-08 21:39 ` [PATCH 06/40] drm/amdgpu/ras: switch ras eeprom handling to use generic helper Luben Tuikov
2021-06-08 21:39 ` [PATCH 07/40] drm/amdgpu/ras: switch fru eeprom handling to use generic helper (v2) Luben Tuikov
2021-06-08 21:39 ` [PATCH 08/40] drm/amdgpu: i2c subsystem uses 7 bit addresses Luben Tuikov
2021-06-08 21:39 ` [PATCH 09/40] drm/amdgpu: add I2C_CLASS_HWMON to SMU i2c buses Luben Tuikov
2021-06-08 21:39 ` [PATCH 10/40] drm/amdgpu: rework smu11 i2c for generic operation Luben Tuikov
2021-06-08 21:39 ` [PATCH 11/40] drm/amdgpu: only set restart on first cmd of the smu i2c transaction Luben Tuikov
2021-06-08 21:39 ` [PATCH 12/40] drm/amdgpu: Remember to wait 10ms for write buffer flush v2 Luben Tuikov
2021-06-08 21:39 ` [PATCH 13/40] dmr/amdgpu: Add RESTART handling also to smu_v11_0_i2c (VG20) Luben Tuikov
2021-06-10 20:18   ` Alex Deucher
2021-06-08 21:39 ` [PATCH 14/40] drm/amdgpu: Drop i > 0 restriction for issuing RESTART Luben Tuikov
2021-06-10 20:21   ` Alex Deucher
2021-06-08 21:39 ` [PATCH 15/40] drm/amdgpu: Send STOP for the last byte of msg only Luben Tuikov
2021-06-10 20:22   ` Alex Deucher
2021-06-08 21:39 ` [PATCH 16/40] drm/amd/pm: SMU I2C: Return number of messages processed Luben Tuikov
2021-06-10 20:25   ` Alex Deucher
2021-06-08 21:39 ` [PATCH 17/40] drm/amdgpu/pm: ADD I2C quirk adapter table Luben Tuikov
2021-06-10 20:26   ` Alex Deucher
2021-06-08 21:39 ` Luben Tuikov [this message]
2021-06-10 20:43   ` [PATCH 18/40] drm/amdgpu: Fix Vega20 I2C to be agnostic (v2) Alex Deucher
2021-06-08 21:39 ` [PATCH 19/40] drm/amdgpu: Fixes to the AMDGPU EEPROM driver Luben Tuikov
2021-06-10 20:53   ` Alex Deucher
2021-06-08 21:39 ` [PATCH 20/40] drm/amdgpu: EEPROM respects I2C quirks Luben Tuikov
2021-06-11 17:01   ` Alex Deucher
2021-06-11 17:17     ` Luben Tuikov
2021-06-11 17:37       ` Luben Tuikov
2021-06-08 21:39 ` [PATCH 21/40] drm/amdgpu: I2C EEPROM full memory addressing Luben Tuikov
2021-06-10 20:57   ` Alex Deucher
2021-06-08 21:39 ` [PATCH 22/40] drm/amdgpu: RAS and FRU now use 19-bit I2C address Luben Tuikov
2021-06-10 20:59   ` Alex Deucher
2021-06-08 21:39 ` [PATCH 23/40] drm/amdgpu: Fix wrap-around bugs in RAS Luben Tuikov
2021-06-10 21:00   ` Alex Deucher
2021-06-08 21:39 ` [PATCH 24/40] drm/amdgpu: I2C class is HWMON Luben Tuikov
2021-06-10 21:02   ` Alex Deucher
2021-06-08 21:39 ` [PATCH 25/40] drm/amdgpu: RAS: EEPROM --> RAS Luben Tuikov
2021-06-10 21:03   ` Alex Deucher
2021-06-08 21:39 ` [PATCH 26/40] drm/amdgpu: Rename misspelled function Luben Tuikov
2021-06-10 21:04   ` Alex Deucher
2021-06-08 21:39 ` [PATCH 27/40] drm/amdgpu: RAS xfer to read/write Luben Tuikov
2021-06-10 21:05   ` Alex Deucher
2021-06-08 21:39 ` [PATCH 28/40] drm/amdgpu: EEPROM: add explicit read and write Luben Tuikov
2021-06-10 21:06   ` Alex Deucher
2021-06-08 21:39 ` [PATCH 29/40] drm/amd/pm: Extend the I2C quirk table Luben Tuikov
2021-06-10 21:07   ` Alex Deucher
2021-06-08 21:39 ` [PATCH 30/40] drm/amd/pm: Simplify managed I2C transfer functions Luben Tuikov
2021-06-10 21:08   ` Alex Deucher
2021-06-08 21:39 ` [PATCH 31/40] drm/amdgpu: Fix width of I2C address Luben Tuikov
2021-06-10 21:09   ` Alex Deucher
2021-06-08 21:39 ` [PATCH 32/40] drm/amdgpu: Return result fix in RAS Luben Tuikov
2021-06-10 21:11   ` Alex Deucher
2021-06-08 21:39 ` [PATCH 33/40] drm/amd/pm: Fix a bug in i2c_xfer Luben Tuikov
2021-06-10 21:12   ` Alex Deucher
2021-06-10 22:26     ` Luben Tuikov
2021-06-08 21:39 ` [PATCH 34/40] drm/amdgpu: Fix amdgpu_ras_eeprom_init() Luben Tuikov
2021-06-10 21:12   ` Alex Deucher
2021-06-08 21:39 ` [PATCH 35/40] drm/amdgpu: Simplify RAS EEPROM checksum calculations Luben Tuikov
2021-06-11 17:07   ` Alex Deucher
2021-06-08 21:39 ` [PATCH 36/40] drm/amdgpu: Use explicit cardinality for clarity Luben Tuikov
2021-06-10 21:17   ` Alex Deucher
2021-06-08 21:39 ` [PATCH 37/40] drm/amdgpu: Optimizations to EEPROM RAS table I/O Luben Tuikov
2021-06-08 21:39 ` [PATCH 38/40] drm/amdgpu: RAS EEPROM table is now in debugfs Luben Tuikov
2021-06-11 17:16   ` Alex Deucher
2021-06-11 17:30     ` Luben Tuikov
2021-06-11 17:51       ` Alex Deucher
2021-06-11 18:06         ` Luben Tuikov
2021-06-08 21:39 ` [PATCH 39/40] drm/amdgpu: Fix koops when accessing RAS EEPROM Luben Tuikov
2021-06-10 21:23   ` Alex Deucher
2021-06-08 21:39 ` [PATCH 40/40] drm/amdgpu: Use a single loop Luben Tuikov
2021-06-10 21:25   ` Alex Deucher
2021-06-14 17:45 [PATCH 00/40] I2C fixes (revision 1) Luben Tuikov
2021-06-14 17:46 ` [PATCH 18/40] drm/amdgpu: Fix Vega20 I2C to be agnostic (v2) Luben Tuikov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210608213954.5517-19-luben.tuikov@amd.com \
    --to=luben.tuikov@amd.com \
    --cc=Alexander.Deucher@amd.com \
    --cc=Andrey.Grodzovsky@amd.com \
    --cc=Hawking.Zhang@amd.com \
    --cc=Lijo.Lazar@amd.com \
    --cc=Stanley.Yang@amd.com \
    --cc=amd-gfx@lists.freedesktop.org \
    --cc=jdelvare@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.