From owner-svn-src-stable@freebsd.org Mon Oct 12 11:34:10 2020 Return-Path: Delivered-To: svn-src-stable@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 3FB854346CA; Mon, 12 Oct 2020 11:34:10 +0000 (UTC) (envelope-from avg@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 "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4C8xQp0WVqz45Nj; Mon, 12 Oct 2020 11:34:10 +0000 (UTC) (envelope-from avg@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id EA81DC00B; Mon, 12 Oct 2020 11:34:09 +0000 (UTC) (envelope-from avg@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 09CBY9QG003548; Mon, 12 Oct 2020 11:34:09 GMT (envelope-from avg@FreeBSD.org) Received: (from avg@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 09CBY9cH003547; Mon, 12 Oct 2020 11:34:09 GMT (envelope-from avg@FreeBSD.org) Message-Id: <202010121134.09CBY9cH003547@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: avg set sender to avg@FreeBSD.org using -f From: Andriy Gapon Date: Mon, 12 Oct 2020 11:34:09 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r366645 - stable/12/sys/dev/iicbus/twsi X-SVN-Group: stable-12 X-SVN-Commit-Author: avg X-SVN-Commit-Paths: stable/12/sys/dev/iicbus/twsi X-SVN-Commit-Revision: 366645 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 12 Oct 2020 11:34:10 -0000 Author: avg Date: Mon Oct 12 11:34:09 2020 New Revision: 366645 URL: https://svnweb.freebsd.org/changeset/base/366645 Log: MFC r363021 by manu: twsi: Fix for > Allwinner A20 Every revision of twsi after the A20 have a bug where we need to write again the control register after each interrupts. We also need to add some delay before writing to this register, a simple read of the same register does the job so do that. Also fix the case when we have finish sending all the bytes, it only worked for 1 byte transfer (the same kind that we do for talking to the PMIC on A20 boards). While here add more debug messages and rework some of them. This was tested by talking to a AT23C32 eeprom and a DS3231 RTC from an H3 and A20 board. PR: 247576 Modified: stable/12/sys/dev/iicbus/twsi/twsi.c Directory Properties: stable/12/ (props changed) Modified: stable/12/sys/dev/iicbus/twsi/twsi.c ============================================================================== --- stable/12/sys/dev/iicbus/twsi/twsi.c Mon Oct 12 11:27:08 2020 (r366644) +++ stable/12/sys/dev/iicbus/twsi/twsi.c Mon Oct 12 11:34:09 2020 (r366645) @@ -499,6 +499,10 @@ twsi_transfer(device_t dev, struct iic_msg *msgs, uint sc->msg_idx = 0; sc->transfer = 1; +#ifdef TWSI_DEBUG + for (int i = 0; i < nmsgs; i++) + debugf(sc->dev, "msg %d is %d bytes long\n", i, msgs[i].len); +#endif /* Send start and re-enable interrupts */ sc->control_val = TWSI_CONTROL_TWSIEN | TWSI_CONTROL_INTEN | TWSI_CONTROL_ACK; @@ -535,13 +539,13 @@ twsi_intr(void *arg) debugf(sc->dev, "Got interrupt Current msg=%x\n", sc->msg_idx); status = TWSI_READ(sc, sc->reg_status); - debugf(sc->dev, "initial status=%x\n", status); + debugf(sc->dev, "reg control=%x\n", TWSI_READ(sc, sc->reg_control)); switch (status) { case TWSI_STATUS_START: case TWSI_STATUS_RPTD_START: /* Transmit the address */ - debugf(sc->dev, "Send the address\n"); + debugf(sc->dev, "Send the address (%x)", sc->msgs[sc->msg_idx].slave); if (sc->msgs[sc->msg_idx].flags & IIC_M_RD) TWSI_WRITE(sc, sc->reg_data, @@ -555,8 +559,10 @@ twsi_intr(void *arg) case TWSI_STATUS_ADDR_W_ACK: debugf(sc->dev, "Ack received after transmitting the address (write)\n"); /* Directly send the first byte */ - sc->sent_bytes = 0; - debugf(sc->dev, "Sending byte 0 = %x\n", sc->msgs[sc->msg_idx].buf[0]); + sc->sent_bytes = 1; + debugf(sc->dev, "Sending byte 0 (of %d) = %x\n", + sc->msgs[sc->msg_idx].len, + sc->msgs[sc->msg_idx].buf[0]); TWSI_WRITE(sc, sc->reg_data, sc->msgs[sc->msg_idx].buf[0]); TWSI_WRITE(sc, sc->reg_control, sc->control_val); @@ -580,7 +586,7 @@ twsi_intr(void *arg) case TWSI_STATUS_DATA_WR_ACK: debugf(sc->dev, "Ack received after transmitting data\n"); - if (sc->sent_bytes++ == (sc->msgs[sc->msg_idx].len - 1)) { + if (sc->sent_bytes == sc->msgs[sc->msg_idx].len) { debugf(sc->dev, "Done sending all the bytes for msg %d\n", sc->msg_idx); /* Send stop, no interrupts on stop */ if (!(sc->msgs[sc->msg_idx].flags & IIC_M_NOSTOP)) { @@ -595,30 +601,40 @@ twsi_intr(void *arg) if (sc->msg_idx == sc->nmsgs) { debugf(sc->dev, "transfer_done=1\n"); transfer_done = 1; + sc->error = 0; + } else { + debugf(sc->dev, "Send repeated start\n"); + TWSI_WRITE(sc, sc->reg_control, sc->control_val | TWSI_CONTROL_START); } } else { - debugf(sc->dev, "Sending byte %d = %x\n", + debugf(sc->dev, "Sending byte %d (of %d) = %x\n", sc->sent_bytes, + sc->msgs[sc->msg_idx].len, sc->msgs[sc->msg_idx].buf[sc->sent_bytes]); TWSI_WRITE(sc, sc->reg_data, sc->msgs[sc->msg_idx].buf[sc->sent_bytes]); TWSI_WRITE(sc, sc->reg_control, sc->control_val); + sc->sent_bytes++; } break; case TWSI_STATUS_DATA_RD_ACK: debugf(sc->dev, "Ack received after receiving data\n"); - debugf(sc->dev, "msg_len=%d recv_bytes=%d\n", sc->msgs[sc->msg_idx].len, sc->recv_bytes); sc->msgs[sc->msg_idx].buf[sc->recv_bytes++] = TWSI_READ(sc, sc->reg_data); + debugf(sc->dev, "msg_len=%d recv_bytes=%d\n", sc->msgs[sc->msg_idx].len, sc->recv_bytes); /* If we only have one byte left, disable ACK */ if (sc->msgs[sc->msg_idx].len - sc->recv_bytes == 1) sc->control_val &= ~TWSI_CONTROL_ACK; - if (sc->msgs[sc->msg_idx].len - sc->recv_bytes) { + if (sc->msgs[sc->msg_idx].len == sc->recv_bytes) { + debugf(sc->dev, "Done with msg %d\n", sc->msg_idx); sc->msg_idx++; - if (sc->msg_idx == sc->nmsgs - 1) + if (sc->msg_idx == sc->nmsgs - 1) { + debugf(sc->dev, "No more msgs\n"); transfer_done = 1; + sc->error = 0; + } } TWSI_WRITE(sc, sc->reg_control, sc->control_val); break; @@ -631,12 +647,14 @@ twsi_intr(void *arg) TWSI_WRITE(sc, sc->reg_control, sc->control_val | TWSI_CONTROL_STOP); } else { - debugf(sc->dev, "No ack when receiving data\n"); - sc->error = ENXIO; - sc->control_val = 0; + debugf(sc->dev, "No ack when receiving data, sending stop anyway\n"); + if (!(sc->msgs[sc->msg_idx].flags & IIC_M_NOSTOP)) + TWSI_WRITE(sc, sc->reg_control, + sc->control_val | TWSI_CONTROL_STOP); } sc->transfer = 0; transfer_done = 1; + sc->error = 0; break; default: @@ -647,6 +665,15 @@ twsi_intr(void *arg) wakeup(sc); break; } + debugf(sc->dev, "Refresh reg_control\n"); + + /* + * Fix silicon bug on > Allwinner A20 by doing a read and writing + * again to the control register + */ + status = TWSI_READ(sc, sc->reg_status); + TWSI_WRITE(sc, sc->reg_control, + sc->control_val | TWSI_CONTROL_IFLG); debugf(sc->dev, "Done with interrupts\n\n"); if (transfer_done == 1) {