From: Vincent Jardin <vjardin@free.fr>
To: "Carlos Song (OSS)" <carlos.song@oss.nxp.com>
Cc: Oleksij Rempel <o.rempel@pengutronix.de>,
Pengutronix Kernel Team <kernel@pengutronix.de>,
Andi Shyti <andi.shyti@kernel.org>, Frank Li <frank.li@nxp.com>,
Sascha Hauer <s.hauer@pengutronix.de>,
Fabio Estevam <festevam@gmail.com>,
"linux-i2c@vger.kernel.org" <linux-i2c@vger.kernel.org>,
"imx@lists.linux.dev" <imx@lists.linux.dev>,
"linux-arm-kernel@lists.infradead.org"
<linux-arm-kernel@lists.infradead.org>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH] i2c: imx: add I2C_M_REV_DIR_ADDR and I2C_M_NOSTART
Date: Wed, 12 Aug 2026 07:47:22 +0200 [thread overview]
Message-ID: <anwI6qnsikPrd80W@L30177.local> (raw)
In-Reply-To: <AM0PR04MB6802658862C4E2ED8628FFA8E8DD2@AM0PR04MB6802.eurprd04.prod.outlook.com>
Hi Carlos,
Thanks a lot for the review, and no problem for the delay.
> This is a such rare i2c frame design in the Realtek RTL8366SE SMI read
> frame, right?
It is rare, but I have been inspired for I2C_M_REV_DIR_ADDR by the source
of two client drivers that use it.
Note that I2C_M_NOSTART is not rare at all. It is what regmap uses for a real
gather write. regmap_i2c_gather_write() opens with
if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_NOSTART))
return -ENOTSUPP;
FYI, some clients that need REV_DIR_ADDR and NOSTART,
drivers/input/joystick/as5011.c
drivers/video/fbdev/matrox/matroxfb_maven.c
both build the identical 2-message pattern,
i2c_check_functionality(adapter,
I2C_FUNC_NOSTART |
I2C_FUNC_PROTOCOL_MANGLING)
I do not have those devices, so I did not check it beside code readings.
Some clients that need NOSTART alone,
drivers/base/regmap/regmap-i2c.c
drivers/infiniband/hw/hfi1/qsfp.c
drivers/gpu/drm/i915/display/dvo_ivch.c
About the i2c masters, that use I2C_M_REV_DIR_ADDR in code,
drivers/i2c/algos/i2c-algo-bit.c
drivers/i2c/algos/i2c-algo-pcf.c
drivers/i2c/busses/i2c-s3c2410.c <- the model I did investigate
drivers/i2c/busses/i2c-tegra-bpmp.c
drivers/media/pci/cobalt/cobalt-i2c.c
So a taxnonomy can be,
adapter REV_DIR impl MANGLING adv NOSTART adv usable
i2c-algo-bit yes yes yes yes
i2c-algo-pcf yes yes no no
i2c-s3c2410 yes yes yes yes
i2c-tegra-bpmp yes yes yes yes
cobalt-i2c yes (private adapter, not exposed)
i2c-brcmstb no yes yes no
i2c-pxa no yes yes no
i2c-tegra no yes yes (cond) no
i2c-imx (this patch) yes yes yes yes
> Is Realtek RTL8366SE SMI driver upstream? Can I found the driver?
Not yet, and I cannot point you at a tree today. It is Realtek's
"Unmanaged Switch" DSA driver, which is not public yet.
What I can share is the message construction, which is the part you
asked about and is not Realtek-specific.
static int as5011_i2c_read(struct i2c_client *client,
uint8_t aregaddr, signed char *value)
{
uint8_t data[2] = { aregaddr };
struct i2c_msg msg_set[2] = {
{
.addr = client->addr,
.flags = I2C_M_REV_DIR_ADDR,
.len = 1,
.buf = (uint8_t *)data
},
{
.addr = client->addr,
.flags = I2C_M_RD | I2C_M_NOSTART,
.len = 1,
.buf = (uint8_t *)data
}
};
int error;
error = i2c_transfer(client->adapter, msg_set, 2);
if (error < 0)
return error;
*value = data[0] & 0x80 ? -1 * (1 + ~data[0]) : data[0];
return 0;
}
And the Realtek accessor, which is the same two messages with a 2-byte
register and 2-byte data instead of 1 and 1:
u8 ra[2] = { reg & 0xff, (reg >> 8) & 0xff };
u8 data[2] = { 0xff, 0xff };
struct i2c_msg msgs[2] = {
{
.addr = client->addr,
.flags = I2C_M_REV_DIR_ADDR,
.len = sizeof(ra),
.buf = ra,
}, {
.addr = client->addr,
.flags = I2C_M_RD | I2C_M_NOSTART,
.len = sizeof(data),
.buf = data,
},
};
ret = i2c_transfer(client->adapter, msgs, 2);
if (ret != 2)
return ret < 0 ? ret : -EIO;
*val = data[0] | (data[1] << 8);
msgs[0] is a write message carrying I2C_M_REV_DIR_ADDR, so the address
byte goes out with the read bit set while the master keeps transmitting
the two register-address bytes. msgs[1] is the read half with
I2C_M_NOSTART, so no repeated start is emitted and the controller simply
turns the bus around. Writes are an ordinary unflagged 4-byte write and
need nothing from this patch.
> ... Have you test this i2c-imx feature in your LS board with RTL8366SE?
Yes, on an LX2160A board carrying four RTL8366SE-CG. Two are strapped to
the chip's 2-wire "EEPROM SMI" mode and hang off hardware i2c-imx
controllers; the other two are on MDIO, for both the same switch registers
are reachable both ways and should answer the same values.
First, the failure on an unpatched kernel, which is reproducible with
nothing but i2ctools and is I think the clearest way to see the problem.
These two commands are byte-identical:
# i2ctransfer -y -f -a 1 w2@0x7c 0x00 0x13 r4@0x7c
0xff 0xff 0x00 0x00
# i2ctransfer -y -f -a 1 r6@0x7c # no preceding write at all
0xff 0xff 0x00 0x00 0x00 0x00
Then, with this patch both chips answer correctly. For testing this patch,
I did use the following that I have just pushed to help, for the record:
https://github.com/vjardin/smi-probe
# smi-probe -t i2c -b /dev/i2c-1 -a 0x7c id
chip_num 0x6980 CHIP_RTL8367E (inside RTL8366SE-CG)
chip_ver 0x0030
svlan_tpid 0x88a8 reset default, as expected
# smi-probe -t i2c -b /dev/i2c-1 -a 0x7c rd 0x1300
reg 0x1300 = 0x6980
# smi-probe -t i2c -b /dev/i2c-1 -a 0x7c rd 0x1202
reg 0x1202 = 0x88a8
# smi-probe -t i2c -b /dev/i2c-2 -a 0x5c rd 0x1202 # U19, IIC3
reg 0x1202 = 0x88a8
# smi-probe -t mdio -b 0x8b97000 -a 0x1a rd 0x1202 # MDIO control
reg 0x1202 = 0x88a8
Then it binds as a DSA switch and enumerates its four user ports:
realtek-US-switch-dsa-i2c 2-005c: RTK DSA unit 0 (EEPROM SMI, addr 0x5c)
I have many other i2c devices on this board, no regression.
Thanks again for your review,
Vincent
next prev parent reply other threads:[~2026-08-12 5:47 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-06 22:37 [PATCH] i2c: imx: add I2C_M_REV_DIR_ADDR and I2C_M_NOSTART Vincent Jardin via B4 Relay
2026-08-06 22:48 ` sashiko-bot
2026-08-07 6:22 ` Vincent Jardin
2026-08-11 10:18 ` Carlos Song (OSS)
2026-08-12 5:47 ` Vincent Jardin [this message]
2026-08-12 9:20 ` Carlos Song (OSS)
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=anwI6qnsikPrd80W@L30177.local \
--to=vjardin@free.fr \
--cc=andi.shyti@kernel.org \
--cc=carlos.song@oss.nxp.com \
--cc=festevam@gmail.com \
--cc=frank.li@nxp.com \
--cc=imx@lists.linux.dev \
--cc=kernel@pengutronix.de \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-i2c@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=o.rempel@pengutronix.de \
--cc=s.hauer@pengutronix.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox