From nobody Sat Sep 13 22:57:10 2025 Received: from dvalin.narfation.org (dvalin.narfation.org [213.160.73.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 83BD81F4CAC; Sun, 3 Aug 2025 16:56:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=213.160.73.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754240171; cv=none; b=mMmfG+cW+CCB6abl4qHZpMALqgfiEYsnXbzM9qGUTLNkH2FTTM6G6L8HybH+RYHCqJiv3hnLK+99Lq8ND7gK6GrAy78tEwyDvh+eSTRC2kCh3rbeSv7QnHAdpHbXrcPErgtpOhC0UP9xprW+quq0eFDLwLVePLW1vXb2bylVoAI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754240171; c=relaxed/simple; bh=6yddMlBi7WZ4YQVI11Ue6hMVOoR7aFNZkS1jLdkvbo4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=BADWj5Q/a2uI6s3lf9gUm1eYAoDHSuRUs+wJivzZV9yaDmFOyHH8jqRic2MNu/4PMj4WQ037ZqGFgK1kpbm7NLKpdd0/G6B6WNd28gI3fFyWS3/ykq0FDyMaFXe1EQk4w+UNzddB7rewX1uBuxcZQZ20Px6OIPY83pZ+6cJds6c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=narfation.org; spf=pass smtp.mailfrom=narfation.org; dkim=pass (1024-bit key) header.d=narfation.org header.i=@narfation.org header.b=ey4TcGwI; arc=none smtp.client-ip=213.160.73.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=narfation.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=narfation.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=narfation.org header.i=@narfation.org header.b="ey4TcGwI" Received: from sven-desktop.home.narfation.org (unknown [IPv6:2a00:1ca0:1d86:99fc::8c24]) by dvalin.narfation.org (Postfix) with UTF8SMTPSA id A918D203A5; Sun, 3 Aug 2025 16:56:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=narfation.org; s=20121; t=1754240167; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cfKmvmHHO7KEEOi9sjrXNREYqdk1dnOlDxfndUQPLNo=; b=ey4TcGwI8FXn9WYZTnbtD8XytvVxXsGMt1xR+lSTYGrCBQuKbonzPIs6Byc8QZmDWU+44w sEHvRZ4lUYCCIOhEiQ/0XQtE8g4vHI16By0NZT6BVLaxU53B/xAHEvuYlzC87a8YwLHrTi VDseOlMYu0KTAT5rWwy3AhhoQxBtYp8= From: Sven Eckelmann Date: Sun, 03 Aug 2025 18:54:41 +0200 Subject: [PATCH v2 4/4] i2c: rtl9300: Implement I2C block read and write Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250803-i2c-rtl9300-multi-byte-v2-4-9b7b759fe2b6@narfation.org> References: <20250803-i2c-rtl9300-multi-byte-v2-0-9b7b759fe2b6@narfation.org> In-Reply-To: <20250803-i2c-rtl9300-multi-byte-v2-0-9b7b759fe2b6@narfation.org> To: Chris Packham , Andi Shyti Cc: linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org, Jonas Jelonek , Harshal Gohel , Simon Wunderlich , Sven Eckelmann X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=3818; i=sven@narfation.org; h=from:subject:message-id; bh=r1VAKLSBt866jA1z22qnHzmaVllA4WduqthhQIIFd7E=; b=owGbwMvMwCXmy1+ufVnk62nG02pJDBn9U/o/aEaeVNliy/nggMpSgX+XhBNU7lxYI912ni/vj PL2p9FXO0pZGMS4GGTFFFn2XMk/v5n9rfznaR+PwsxhZQIZwsDFKQATidzO8N/dSOcmc0Gha5xH V0f1j93/vynniba9uJfc//J/WcnevuOMDE08a0U3t1w96+9eIXFTopxN6c3Sk0+vTFDpayoTP/0 klREA X-Developer-Key: i=sven@narfation.org; a=openpgp; fpr=522D7163831C73A635D12FE5EC371482956781AF From: Harshal Gohel It was noticed that the original implementation of SMBus Block Write in the driver was actually an I2C Block Write. Both differ only in the Count byte before the actual data: S Addr Wr [A] Comm [A] Count [A] Data [A] Data [A] ... [A] Data [A] P The I2C Block Write is just skipping this Count byte and starts directly with the data: S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P The I2C controller of RTL93xx doesn't handle this Count byte special and it is simply another one of (16 possible) data bytes. Adding support for the I2C Block Write therefore only requires to skip the count byte (0) in data->block. It is similar for reads. The SMBUS Block read is having a Count byte before the data: S Addr Wr [A] Comm [A] Sr Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA P And the I2C Block Read is directly starting with the actual data: S Addr Wr [A] Comm [A] Sr Addr Rd [A] [Data] A [Data] A ... A [Data] NA P The I2C controller is also not handling this byte in a special way. It simply provides every byte after the Rd marker + Ack as part of the 16 byte receive buffer (registers). The content of this buffer just has to be copied to the right position in the receive data->block. Signed-off-by: Harshal Gohel Co-developed-by: Sven Eckelmann Signed-off-by: Sven Eckelmann --- drivers/i2c/busses/i2c-rtl9300.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-rtl9300.c b/drivers/i2c/busses/i2c-rtl9= 300.c index 4e0844d97607f64386a6d7a7c4086a81fdd89d6c..cc8c6d680b41976164b49492997= 6bd34d367d4de 100644 --- a/drivers/i2c/busses/i2c-rtl9300.c +++ b/drivers/i2c/busses/i2c-rtl9300.c @@ -186,22 +186,32 @@ static int rtl9300_i2c_execute_xfer(struct rtl9300_i2= c *i2c, char read_write, return -EIO; =20 if (read_write =3D=3D I2C_SMBUS_READ) { - if (size =3D=3D I2C_SMBUS_BYTE || size =3D=3D I2C_SMBUS_BYTE_DATA) { + switch (size) { + case I2C_SMBUS_BYTE: + case I2C_SMBUS_BYTE_DATA: ret =3D regmap_read(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_DATA_WORD0, &val); if (ret) return ret; data->byte =3D val & 0xff; - } else if (size =3D=3D I2C_SMBUS_WORD_DATA) { + break; + case I2C_SMBUS_WORD_DATA: ret =3D regmap_read(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_DATA_WORD0, &val); if (ret) return ret; data->word =3D val & 0xffff; - } else { + break; + case I2C_SMBUS_I2C_BLOCK_DATA: + ret =3D rtl9300_i2c_read(i2c, &data->block[1], len); + if (ret) + return ret; + break; + default: ret =3D rtl9300_i2c_read(i2c, &data->block[0], len); if (ret) return ret; + break; } } =20 @@ -295,6 +305,21 @@ static int rtl9300_i2c_smbus_xfer(struct i2c_adapter *= adap, u16 addr, unsigned s len =3D data->block[0] + 1; break; =20 + case I2C_SMBUS_I2C_BLOCK_DATA: + ret =3D rtl9300_i2c_reg_addr_set(i2c, command, 1); + if (ret) + goto out_unlock; + ret =3D rtl9300_i2c_config_xfer(i2c, chan, addr, data->block[0]); + if (ret) + goto out_unlock; + if (read_write =3D=3D I2C_SMBUS_WRITE) { + ret =3D rtl9300_i2c_write(i2c, &data->block[1], data->block[0]); + if (ret) + goto out_unlock; + } + len =3D data->block[0]; + break; + default: dev_err(&adap->dev, "Unsupported transaction %d\n", size); ret =3D -EOPNOTSUPP; @@ -313,6 +338,7 @@ static u32 rtl9300_i2c_func(struct i2c_adapter *a) { return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_READ_I2C_BLOCK | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK | I2C_FUNC_SMBUS_BLOCK_DATA; } =20 --=20 2.47.2