git: cf0a73fb48a3 - stable/13 - o Fix i2c read operation for large transfers (more than 32 bytes).
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 22 Dec 2021 07:32:03 UTC
The branch stable/13 has been updated by avg:
URL: https://cgit.FreeBSD.org/src/commit/?id=cf0a73fb48a34d582dd82deaf795c9a24456439a
commit cf0a73fb48a34d582dd82deaf795c9a24456439a
Author: Ruslan Bukin <br@FreeBSD.org>
AuthorDate: 2021-05-26 09:55:23 +0000
Commit: Andriy Gapon <avg@FreeBSD.org>
CommitDate: 2021-12-22 07:30:54 +0000
o Fix i2c read operation for large transfers (more than 32 bytes).
o Fix slave address setting.
This allows to read the EDID from an HDMI monitor.
(cherry picked from commit 38e7025a60b28623b5991622a6efd1b8a329ccb2)
---
sys/arm64/rockchip/rk_i2c.c | 33 ++++++++++++++++++++++++++++-----
1 file changed, 28 insertions(+), 5 deletions(-)
diff --git a/sys/arm64/rockchip/rk_i2c.c b/sys/arm64/rockchip/rk_i2c.c
index 731ae81af661..ffe6f17ee0ac 100644
--- a/sys/arm64/rockchip/rk_i2c.c
+++ b/sys/arm64/rockchip/rk_i2c.c
@@ -297,6 +297,7 @@ static void
rk_i2c_intr_locked(struct rk_i2c_softc *sc)
{
uint32_t reg;
+ int transfer_len;
sc->ipd = RK_I2C_READ(sc, RK_I2C_IPD);
@@ -330,11 +331,16 @@ rk_i2c_intr_locked(struct rk_i2c_softc *sc)
RK_I2C_WRITE(sc, RK_I2C_IEN, RK_I2C_IEN_MBRFIEN |
RK_I2C_IEN_NAKRCVIEN);
- reg = RK_I2C_READ(sc, RK_I2C_CON);
- reg |= RK_I2C_CON_LASTACK;
- RK_I2C_WRITE(sc, RK_I2C_CON, reg);
+ if ((sc->msg->len - sc->cnt) > 32)
+ transfer_len = 32;
+ else {
+ transfer_len = sc->msg->len - sc->cnt;
+ reg = RK_I2C_READ(sc, RK_I2C_CON);
+ reg |= RK_I2C_CON_LASTACK;
+ RK_I2C_WRITE(sc, RK_I2C_CON, reg);
+ }
- RK_I2C_WRITE(sc, RK_I2C_MRXCNT, sc->msg->len);
+ RK_I2C_WRITE(sc, RK_I2C_MRXCNT, transfer_len);
} else {
sc->state = STATE_WRITE;
RK_I2C_WRITE(sc, RK_I2C_IEN, RK_I2C_IEN_MBTFIEN |
@@ -349,6 +355,23 @@ rk_i2c_intr_locked(struct rk_i2c_softc *sc)
if (sc->cnt == sc->msg->len)
rk_i2c_send_stop(sc);
+ else {
+ sc->mode = RK_I2C_CON_MODE_RX;
+ reg = RK_I2C_READ(sc, RK_I2C_CON) & \
+ ~RK_I2C_CON_CTRL_MASK;
+ reg |= sc->mode << RK_I2C_CON_MODE_SHIFT;
+ reg |= RK_I2C_CON_EN;
+
+ if ((sc->msg->len - sc->cnt) > 32)
+ transfer_len = 32;
+ else {
+ transfer_len = sc->msg->len - sc->cnt;
+ reg |= RK_I2C_CON_LASTACK;
+ }
+
+ RK_I2C_WRITE(sc, RK_I2C_CON, reg);
+ RK_I2C_WRITE(sc, RK_I2C_MRXCNT, transfer_len);
+ }
break;
case STATE_WRITE:
@@ -519,7 +542,7 @@ rk_i2c_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
sc->mode = RK_I2C_CON_MODE_RX;
} else {
sc->mode = RK_I2C_CON_MODE_RRX;
- reg = msgs[i].slave & LSB;
+ reg = msgs[i].slave & ~LSB;
reg |= RK_I2C_MRXADDR_VALID(0);
RK_I2C_WRITE(sc, RK_I2C_MRXADDR, reg);
RK_I2C_WRITE(sc, RK_I2C_MRXRADDR, 0);