From nobody Mon Apr 01 23:47:34 2024 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4V7nkG6JT9z5FRHZ; Mon, 1 Apr 2024 23:47:34 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4V7nkG41Xcz4QHF; Mon, 1 Apr 2024 23:47:34 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1712015254; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=dWu2nrLRSEzYrvl0Svc8IIYYlAv9WtE/4lDjCgOlw9Y=; b=kgt4XpyjmoJ21pmFfsecAOUSTtGUKB7iHPjAfY/ENNlW4pZPd5bjYg4Q8T+uApzZTzhk6N 64L4L3DZeE6rNvosaCaWfxxI3CEWWTNFuex9F5fNP9Ouke8ZPwzzSw5FeaOJwK73/RLIr1 m6gzaFrZI5APsRF9YadPNjFbpV1fIEoEmSiAnT4KWp1pMDcxzbFwmS3tFHbdF62Q1HUKxj +wcsCX2gVA6HMH9mEVL6TWExzpEzrvpj67qAUBpuW1/VK5IBYQFmuGQCv7e2p9IPFkpfnm 6/3Pk5ELoMYsPvvKqcHcJma6IOuS5Di7d+z4A4o/9NOyD2OABviDQtsDbYBAVA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1712015254; a=rsa-sha256; cv=none; b=n/Z/lzyBIFww8WPpkdduM8vraTxRcVEKirW4a3rYT7w77UyclnZ/RPiAlc65P6UELQx9qJ RTH86kwwKYG1GRVJ0whhQ9W4JCmqftJn0CJI/+LlVr347FVSpX4Mr6igJU732WM7N2ei+3 RGpsHGDY9CM094uMEmBywFlL8nY98qpt81We9xabWH1rrWvgcrCBtJ6iEDk8UEduWVRzSC u0AMnMK/pbTmFSYJDSlhDu9Zew33A3zGRdia6bHdcFW6EBiKcSzNEvte7Oorb4275402fk HE16GK72Q8ROnQUCRI0SrBwd9L387c0nIZWZvveL0NFK30+SHByT1BBsYBfqsA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1712015254; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=dWu2nrLRSEzYrvl0Svc8IIYYlAv9WtE/4lDjCgOlw9Y=; b=hCSzlt1dn1pI7LRVcvtGVnB3Jv/CpzmxUnwvPe0mLcRFXKnmfGrK9ZNOZOCBpBpjiZwT8l AHHIU6HKGsu3RULiEu56HCuUxyRWg/X9wX9LrIVxLfa3X5Tun2Vu+IRTo+XvDuT+/99qXl qrPAZv3xjjtzpi/JrESPehyBkmhmENKOyndX9Ir7sWLc4KDf9RKaPYNN13hoBivuHohjng 086MH3yxxR4kTNra1henu7Fp6U6Y8erNFL/Xtat0K7QObmLLGe1rKyxj2u+0ygmVGATPBj xPHzY51bzt8k2K52MfuTvtMTb0dAeHv/avW2zUgCAnCbNXJCWWFxTdzmA6iCkQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4V7nkG39C6zR70; Mon, 1 Apr 2024 23:47:34 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 431NlYa9084220; Mon, 1 Apr 2024 23:47:34 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 431NlYhq084217; Mon, 1 Apr 2024 23:47:34 GMT (envelope-from git) Date: Mon, 1 Apr 2024 23:47:34 GMT Message-Id: <202404012347.431NlYhq084217@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: "Bjoern A. Zeeb" Subject: git: 4197e21ed39c - stable/14 - vf_i2c: update I2C controller logic List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-branches@freebsd.org X-BeenThere: dev-commits-src-branches@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: bz X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: 4197e21ed39c28d261a9cb08e6cb6fc351902a3a Auto-Submitted: auto-generated The branch stable/14 has been updated by bz: URL: https://cgit.FreeBSD.org/src/commit/?id=4197e21ed39c28d261a9cb08e6cb6fc351902a3a commit 4197e21ed39c28d261a9cb08e6cb6fc351902a3a Author: Pierre-Luc Drouin AuthorDate: 2024-03-22 22:13:04 +0000 Commit: Bjoern A. Zeeb CommitDate: 2024-04-01 23:46:11 +0000 vf_i2c: update I2C controller logic Update the I2C controller logic to be more consistent with the newer version of the controller reference manual. This makes it work better on modern LS/LX platforms and avoids unnecessary delays. Also fixes a lock leak. Tested by: bz (LS1088a FDT), Pierre-Luc Drouin (Honeycomb, ACPI) (cherry picked from commit 44847114bd4c61ed3dfcc879fa0d7deb452e12d3) --- sys/dev/iicbus/controller/vybrid/vf_i2c.c | 148 ++++++++++--------------- sys/dev/iicbus/controller/vybrid/vf_i2c.h | 3 +- sys/dev/iicbus/controller/vybrid/vf_i2c_acpi.c | 3 +- sys/dev/iicbus/controller/vybrid/vf_i2c_fdt.c | 3 +- 4 files changed, 65 insertions(+), 92 deletions(-) diff --git a/sys/dev/iicbus/controller/vybrid/vf_i2c.c b/sys/dev/iicbus/controller/vybrid/vf_i2c.c index 7a6ec3948e13..d3c3664af78c 100644 --- a/sys/dev/iicbus/controller/vybrid/vf_i2c.c +++ b/sys/dev/iicbus/controller/vybrid/vf_i2c.c @@ -28,7 +28,8 @@ /* * Vybrid Family Inter-Integrated Circuit (I2C) - * Chapter 48, Vybrid Reference Manual, Rev. 5, 07/2013 + * Originally based on Chapter 48, Vybrid Reference Manual, Rev. 5, 07/2013 + * Currently based on Chapter 21, LX2160A Reference Manual, Rev. 1, 10/2021 * * The current implementation is based on the original driver by Ruslan Bukin, * later modified by Dawid Górecki, and split into FDT and ACPI drivers by Val @@ -184,6 +185,7 @@ vf_i2c_attach_common(device_t dev) mtx_unlock(&sc->mutex); sc->iicbus = device_add_child(dev, "iicbus", -1); + if (sc->iicbus == NULL) { device_printf(dev, "could not add iicbus child"); mtx_destroy(&sc->mutex); @@ -233,24 +235,6 @@ i2c_detach(device_t dev) return (0); } -/* Wait for transfer interrupt flag */ -static int -wait_for_iif(struct vf_i2c_softc *sc) -{ - int retry; - - retry = 1000; - while (retry --) { - if (READ1(sc, I2C_IBSR) & IBSR_IBIF) { - WRITE1(sc, I2C_IBSR, IBSR_IBIF); - return (IIC_NOERR); - } - DELAY(10); - } - - return (IIC_ETIMEOUT); -} - /* Wait for free bus */ static int wait_for_nibb(struct vf_i2c_softc *sc) @@ -272,14 +256,24 @@ static int wait_for_icf(struct vf_i2c_softc *sc) { int retry; + uint8_t ibsr; + + vf_i2c_dbg(sc, "i2c wait for transfer complete + interrupt flag\n"); retry = 1000; while (retry --) { - if (READ1(sc, I2C_IBSR) & IBSR_TCF) { - if (READ1(sc, I2C_IBSR) & IBSR_IBIF) { - WRITE1(sc, I2C_IBSR, IBSR_IBIF); - return (IIC_NOERR); + ibsr = READ1(sc, I2C_IBSR); + + if (ibsr & IBSR_IBIF) { + WRITE1(sc, I2C_IBSR, IBSR_IBIF); + + if (ibsr & IBSR_IBAL) { + WRITE1(sc, I2C_IBSR, IBSR_IBAL); + return (IIC_EBUSBSY); } + + if (ibsr & IBSR_TCF) + return (IIC_NOERR); } DELAY(10); } @@ -309,30 +303,24 @@ i2c_repeated_start(device_t dev, u_char slave, int timeout) mtx_lock(&sc->mutex); - WRITE1(sc, I2C_IBAD, slave); - if ((READ1(sc, I2C_IBSR) & IBSR_IBB) == 0) { + vf_i2c_dbg(sc, "cant i2c repeat start: bus is no longer busy\n"); mtx_unlock(&sc->mutex); return (IIC_EBUSERR); } - /* Set repeated start condition */ - DELAY(10); - reg = READ1(sc, I2C_IBCR); reg |= (IBCR_RSTA | IBCR_IBIE); WRITE1(sc, I2C_IBCR, reg); - DELAY(10); - /* Write target address - LSB is R/W bit */ WRITE1(sc, I2C_IBDR, slave); - error = wait_for_iif(sc); + error = wait_for_icf(sc); if (!tx_acked(sc)) { - vf_i2c_dbg(sc, - "cant i2c start: missing ACK after slave addres\n"); + mtx_unlock(&sc->mutex); + vf_i2c_dbg(sc, "cant i2c repeat start: missing ACK after slave address\n"); return (IIC_ENOACK); } @@ -357,27 +345,32 @@ i2c_start(device_t dev, u_char slave, int timeout) mtx_lock(&sc->mutex); - WRITE1(sc, I2C_IBAD, slave); + error = wait_for_nibb(sc); - if (READ1(sc, I2C_IBSR) & IBSR_IBB) { + /* Reset controller if bus is still busy. */ + if (error == IIC_ETIMEOUT) { + WRITE1(sc, I2C_IBCR, IBCR_MDIS); + DELAY(1000); + WRITE1(sc, I2C_IBCR, IBCR_NOACK); + error = wait_for_nibb(sc); + } + + if (error != 0) { mtx_unlock(&sc->mutex); - vf_i2c_dbg(sc, "cant i2c start: IIC_EBUSBSY\n"); - return (IIC_EBUSERR); + vf_i2c_dbg(sc, "cant i2c start: %i\n", error); + return (error); } /* Set start condition */ - reg = (IBCR_MSSL | IBCR_NOACK | IBCR_IBIE); + reg = (IBCR_MSSL | IBCR_NOACK | IBCR_IBIE | IBCR_TXRX); WRITE1(sc, I2C_IBCR, reg); - DELAY(100); - - reg |= (IBCR_TXRX); - WRITE1(sc, I2C_IBCR, reg); + WRITE1(sc, I2C_IBSR, IBSR_IBIF); /* Write target address - LSB is R/W bit */ WRITE1(sc, I2C_IBDR, slave); - error = wait_for_iif(sc); + error = wait_for_icf(sc); if (error != 0) { mtx_unlock(&sc->mutex); vf_i2c_dbg(sc, "cant i2c start: iif error\n"); @@ -386,8 +379,7 @@ i2c_start(device_t dev, u_char slave, int timeout) mtx_unlock(&sc->mutex); if (!tx_acked(sc)) { - vf_i2c_dbg(sc, - "cant i2c start: missing QACK after slave addres\n"); + vf_i2c_dbg(sc, "cant i2c start: missing ACK after slave address\n"); return (IIC_ENOACK); } @@ -405,16 +397,9 @@ i2c_stop(device_t dev) mtx_lock(&sc->mutex); - WRITE1(sc, I2C_IBCR, IBCR_NOACK | IBCR_IBIE); - - DELAY(100); + if ((READ1(sc, I2C_IBCR) & IBCR_MSSL) != 0) + WRITE1(sc, I2C_IBCR, IBCR_NOACK | IBCR_IBIE); - /* Reset controller if bus still busy after STOP */ - if (wait_for_nibb(sc) == IIC_ETIMEOUT) { - WRITE1(sc, I2C_IBCR, IBCR_MDIS); - DELAY(1000); - WRITE1(sc, I2C_IBCR, IBCR_NOACK); - } mtx_unlock(&sc->mutex); return (IIC_NOERR); @@ -469,27 +454,14 @@ i2c_reset(device_t dev, u_char speed, u_char addr, u_char *oldadr) div_reg = i2c_get_div_val(dev); vf_i2c_dbg(sc, "i2c reset\n"); - switch (speed) { - case IIC_FAST: - case IIC_SLOW: - case IIC_UNKNOWN: - case IIC_FASTEST: - default: - break; - } - mtx_lock(&sc->mutex); WRITE1(sc, I2C_IBCR, IBCR_MDIS); - DELAY(1000); - if(div_reg != DIV_REG_UNSET) WRITE1(sc, I2C_IBFD, div_reg); WRITE1(sc, I2C_IBCR, 0x0); /* Enable i2c */ - DELAY(1000); - mtx_unlock(&sc->mutex); return (IIC_NOERR); @@ -511,36 +483,34 @@ i2c_read(device_t dev, char *buf, int len, int *read, int last, int delay) if (len) { if (len == 1) - WRITE1(sc, I2C_IBCR, IBCR_IBIE | IBCR_MSSL | \ - IBCR_NOACK); + WRITE1(sc, I2C_IBCR, IBCR_IBIE | IBCR_MSSL | IBCR_NOACK); else WRITE1(sc, I2C_IBCR, IBCR_IBIE | IBCR_MSSL); /* dummy read */ READ1(sc, I2C_IBDR); - DELAY(1000); - } - while (*read < len) { - error = wait_for_icf(sc); - if (error != 0) { - mtx_unlock(&sc->mutex); - return (error); - } + while (*read < len) { + error = wait_for_icf(sc); + if (error != 0) { + mtx_unlock(&sc->mutex); + return (error); + } - if ((*read == len - 2) && last) { - /* NO ACK on last byte */ - WRITE1(sc, I2C_IBCR, IBCR_IBIE | IBCR_MSSL | \ - IBCR_NOACK); - } + if (last) { + if (*read == len - 2) { + /* NO ACK on last byte */ + WRITE1(sc, I2C_IBCR, IBCR_IBIE | IBCR_MSSL | IBCR_NOACK); - if ((*read == len - 1) && last) { - /* Transfer done, remove master bit */ - WRITE1(sc, I2C_IBCR, IBCR_IBIE | IBCR_NOACK); - } + } else if (*read == len - 1) { + /* Transfer done, remove master bit */ + WRITE1(sc, I2C_IBCR, IBCR_IBIE | IBCR_NOACK); + } + } - *buf++ = READ1(sc, I2C_IBDR); - (*read)++; + *buf++ = READ1(sc, I2C_IBDR); + (*read)++; + } } mtx_unlock(&sc->mutex); @@ -563,7 +533,7 @@ i2c_write(device_t dev, const char *buf, int len, int *sent, int timeout) while (*sent < len) { WRITE1(sc, I2C_IBDR, *buf++); - error = wait_for_iif(sc); + error = wait_for_icf(sc); if (error != 0) { mtx_unlock(&sc->mutex); return (error); diff --git a/sys/dev/iicbus/controller/vybrid/vf_i2c.h b/sys/dev/iicbus/controller/vybrid/vf_i2c.h index 8be6e2d86324..7eb9025893ed 100644 --- a/sys/dev/iicbus/controller/vybrid/vf_i2c.h +++ b/sys/dev/iicbus/controller/vybrid/vf_i2c.h @@ -28,7 +28,8 @@ /* * Vybrid Family Inter-Integrated Circuit (I2C) - * Chapter 48, Vybrid Reference Manual, Rev. 5, 07/2013 + * Originally based on Chapter 48, Vybrid Reference Manual, Rev. 5, 07/2013 + * Currently based on Chapter 21, LX2160A Reference Manual, Rev. 1, 10/2021 * * The current implementation is based on the original driver by Ruslan Bukin, * later modified by Dawid Górecki, and split into FDT and ACPI drivers by Val diff --git a/sys/dev/iicbus/controller/vybrid/vf_i2c_acpi.c b/sys/dev/iicbus/controller/vybrid/vf_i2c_acpi.c index 03f5c99a45c6..0b18926ee2df 100644 --- a/sys/dev/iicbus/controller/vybrid/vf_i2c_acpi.c +++ b/sys/dev/iicbus/controller/vybrid/vf_i2c_acpi.c @@ -27,7 +27,8 @@ /* * Vybrid Family Inter-Integrated Circuit (I2C) - * Chapter 48, Vybrid Reference Manual, Rev. 5, 07/2013 + * Originally based on Chapter 48, Vybrid Reference Manual, Rev. 5, 07/2013 + * Currently based on Chapter 21, LX2160A Reference Manual, Rev. 1, 10/2021 * * The current implementation is based on the original driver by Ruslan Bukin, * later modified by Dawid Górecki, and split into FDT and ACPI drivers by Val diff --git a/sys/dev/iicbus/controller/vybrid/vf_i2c_fdt.c b/sys/dev/iicbus/controller/vybrid/vf_i2c_fdt.c index 935f389ab516..def5ce109caf 100644 --- a/sys/dev/iicbus/controller/vybrid/vf_i2c_fdt.c +++ b/sys/dev/iicbus/controller/vybrid/vf_i2c_fdt.c @@ -28,7 +28,8 @@ /* * Vybrid Family Inter-Integrated Circuit (I2C) - * Chapter 48, Vybrid Reference Manual, Rev. 5, 07/2013 + * Originally based on Chapter 48, Vybrid Reference Manual, Rev. 5, 07/2013 + * Currently based on Chapter 21, LX2160A Reference Manual, Rev. 1, 10/2021 * * The current implementation is based on the original driver by Ruslan Bukin, * later modified by Dawid Górecki, and split into FDT and ACPI drivers by Val