Received: by 2002:a5b:505:0:0:0:0:0 with SMTP id o5csp2121174ybp; Thu, 10 Oct 2019 02:33:08 -0700 (PDT) X-Google-Smtp-Source: APXvYqwIGMSoyigWT5vnmwFLb2jPsyaQaZGtRwCUp+HI20makP6b4mIosejF0gQoPwVb8+ZaYbZ+ X-Received: by 2002:aa7:cd0f:: with SMTP id b15mr7162155edw.3.1570699988232; Thu, 10 Oct 2019 02:33:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1570699988; cv=none; d=google.com; s=arc-20160816; b=YlV14JnGo0ZqMn70vdioErxwZWNpCiUqNTUmZx7dw211dlYhuddM/zKsqicKAl3a2A 1H/6qU+ZELWMnpTBREkYQqFIxwzCRd2T47gC+1iKOYSdygPw+M9Q2U0HFxd1eGtq9b/S 9Jy8neTTPOSxt6NHYCg+MApTY2AEQTcWjLq/dDv+mgozwF3Pmp4EWaKWU/Lk/S04cgFZ 9n8MDMFHrUnpHHcfcEjZvaKoOVkWZM5YPZNeqCcC4lWO2et4PIK1fm9hsbEhQm5vctnl zd65RtPPUzpTLv6hc2p3ExlYH52Sidl7FDFx0ly+1QnYm/ZmV1Xo+CaDjMxSRKw5kX3p +06A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=C/wkh/GnDCqsZNIodlB9tNbqA2+NzVOROU2ZLiYiw8c=; b=TNQd3iTjstspWUfNI1AdZLElH99r/ZXuvTWqEiFmcXBh+FtPW5dbwq8scScfk83OF6 37s3jVioJIJIhkOlss4nLrZFPhOauqC/Gk6VjX9gPU+29RwvFxzcmSIpWe/z7H7OkboD YWbb6ueqXNfP88V6NPyFQR0mZl9m/MaZHk+4C+0HEs/nX1VqIQOPR6dpvXeRakzp/bAh zoutvYD9dXkrOmxT7RNrk6NBEYR0qK8eOMNG88Xq0y4ivou3feOTg6mW6WSFg/5avcKD 83qHSmJv/OrEB00evHTfHnsMAIlLLYR9UkkkNKKe/huVJwaaGqzTqgRxKIGtFc0CLDIg FVNg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@broadcom.com header.s=google header.b="OSvqdGd/"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=broadcom.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id u6si2872940eds.173.2019.10.10.02.32.44; Thu, 10 Oct 2019 02:33:08 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@broadcom.com header.s=google header.b="OSvqdGd/"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=broadcom.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387652AbfJJJc1 (ORCPT + 99 others); Thu, 10 Oct 2019 05:32:27 -0400 Received: from mail-lf1-f66.google.com ([209.85.167.66]:38214 "EHLO mail-lf1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727320AbfJJJc1 (ORCPT ); Thu, 10 Oct 2019 05:32:27 -0400 Received: by mail-lf1-f66.google.com with SMTP id u28so3842388lfc.5 for ; Thu, 10 Oct 2019 02:32:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=C/wkh/GnDCqsZNIodlB9tNbqA2+NzVOROU2ZLiYiw8c=; b=OSvqdGd/HH6LNxUtzlPkUEUmkHKnfJuBpTU/F2JyAocadOJvBk5t0cXMz76yLL4go6 q8m/7SsAuhyIDIVwgqaReMcIBjgl4nokwNaxHKB3Inyr+4Tdx+9B59EIbEJHwa01MSbo fbIs1WZOlrgRXsMwy4NdS17VYdPXkHiPE3qgk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=C/wkh/GnDCqsZNIodlB9tNbqA2+NzVOROU2ZLiYiw8c=; b=Z+ZPChPo8xbEwPFKkMJ5ngPOIc5cfTmPvOpk3AH8+xGDwqrAZCwX87YZwVbGn4rOh5 WPz7TvnvtUuxv8RMI9Dc1vh4R2lJSjX60e9WUA0+8Mvjv/9a5uzbTh5gj73YKvhRUITE ERyEyJN7+I+kHikoixZQJfunPxrXo4UfSJ5GdIMF34zKIfUCFz2G4S1phx0cMLJKqyG4 4OpEojLm3MWhd/7JHaXKxeDg63mM1hNxn+YKo7YjfEQbJqZ3ETGiRVK8upqP/GMLdTSI M4F/2TadeVPfq9yMp961BiGRvKuyKLMSKrdTqb+33hZXC4GHCaEesbjSYSq4FzudQkTx vW6Q== X-Gm-Message-State: APjAAAUFM06R1ZFW6RFm5QCxTkRSmPE63U0qOWz+i32FwWZbFXUalDi5 2ZU6PREfeQXgP4Of2rfz9lwg6byMVxo6HYwbPoRaLg== X-Received: by 2002:a19:23cc:: with SMTP id j195mr5332104lfj.91.1570699944121; Thu, 10 Oct 2019 02:32:24 -0700 (PDT) MIME-Version: 1.0 References: <1569825869-30640-1-git-send-email-rayagonda.kokatanur@broadcom.com> In-Reply-To: <1569825869-30640-1-git-send-email-rayagonda.kokatanur@broadcom.com> From: Rayagonda Kokatanur Date: Thu, 10 Oct 2019 15:02:13 +0530 Message-ID: Subject: Re: [PATCH v2 1/1] i2c: iproc: Add i2c repeated start capability To: Ray Jui , Scott Branden , BCM Kernel Feedback , Wolfram Sang , Michael Cheng , Shreesha Rajashekar , Lori Hikichi , linux-i2c@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Linux Kernel Mailing List Cc: Icarus Chau , Ray Jui , Shivaraj Shetty Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Wolfram, Did you get a chance to review this patch. Best regards, Rayagonda On Mon, Sep 30, 2019 at 12:19 PM Rayagonda Kokatanur wrote: > > From: Lori Hikichi > > Enable handling of i2c repeated start. The current code > handles a multi msg i2c transfer as separate i2c bus > transactions. This change will now handle this case > using the i2c repeated start protocol. The number of msgs > in a transfer is limited to two, and must be a write > followed by a read. > > Signed-off-by: Lori Hikichi > Signed-off-by: Rayagonda Kokatanur > Signed-off-by: Icarus Chau > Signed-off-by: Ray Jui > Signed-off-by: Shivaraj Shetty > --- > changes from v1: > - Address following review comments from Wolfarm Sang, > Use i2c_8bit_addr_from_msg() api instead of decoding i2c_msg struct and > remove check against number of i2c message as it will be taken care > by core using quirks flags. > > drivers/i2c/busses/i2c-bcm-iproc.c | 63 ++++++++++++++++++++++++++++++-------- > 1 file changed, 50 insertions(+), 13 deletions(-) > > diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c > index d7fd76b..e478db7 100644 > --- a/drivers/i2c/busses/i2c-bcm-iproc.c > +++ b/drivers/i2c/busses/i2c-bcm-iproc.c > @@ -81,6 +81,7 @@ > #define M_CMD_PROTOCOL_MASK 0xf > #define M_CMD_PROTOCOL_BLK_WR 0x7 > #define M_CMD_PROTOCOL_BLK_RD 0x8 > +#define M_CMD_PROTOCOL_PROCESS 0xa > #define M_CMD_PEC_SHIFT 8 > #define M_CMD_RD_CNT_SHIFT 0 > #define M_CMD_RD_CNT_MASK 0xff > @@ -675,13 +676,20 @@ static int bcm_iproc_i2c_xfer_wait(struct bcm_iproc_i2c_dev *iproc_i2c, > return 0; > } > > -static int bcm_iproc_i2c_xfer_single_msg(struct bcm_iproc_i2c_dev *iproc_i2c, > - struct i2c_msg *msg) > +/* > + * If 'process_call' is true, then this is a multi-msg transfer that requires > + * a repeated start between the messages. > + * More specifically, it must be a write (reg) followed by a read (data). > + * The i2c quirks are set to enforce this rule. > + */ > +static int bcm_iproc_i2c_xfer_internal(struct bcm_iproc_i2c_dev *iproc_i2c, > + struct i2c_msg *msgs, bool process_call) > { > int i; > u8 addr; > u32 val, tmp, val_intr_en; > unsigned int tx_bytes; > + struct i2c_msg *msg = &msgs[0]; > > /* check if bus is busy */ > if (!!(iproc_i2c_rd_reg(iproc_i2c, > @@ -707,14 +715,29 @@ static int bcm_iproc_i2c_xfer_single_msg(struct bcm_iproc_i2c_dev *iproc_i2c, > val = msg->buf[i]; > > /* mark the last byte */ > - if (i == msg->len - 1) > - val |= BIT(M_TX_WR_STATUS_SHIFT); > + if (!process_call && (i == msg->len - 1)) > + val |= 1 << M_TX_WR_STATUS_SHIFT; > > iproc_i2c_wr_reg(iproc_i2c, M_TX_OFFSET, val); > } > iproc_i2c->tx_bytes = tx_bytes; > } > > + /* Process the read message if this is process call */ > + if (process_call) { > + msg++; > + iproc_i2c->msg = msg; /* point to second msg */ > + > + /* > + * The last byte to be sent out should be a slave > + * address with read operation > + */ > + addr = i2c_8bit_addr_from_msg(msg); > + /* mark it the last byte out */ > + val = addr | (1 << M_TX_WR_STATUS_SHIFT); > + iproc_i2c_wr_reg(iproc_i2c, M_TX_OFFSET, val); > + } > + > /* mark as incomplete before starting the transaction */ > if (iproc_i2c->irq) > reinit_completion(&iproc_i2c->done); > @@ -733,7 +756,7 @@ static int bcm_iproc_i2c_xfer_single_msg(struct bcm_iproc_i2c_dev *iproc_i2c, > * underrun interrupt, which will be triggerred when the TX FIFO is > * empty. When that happens we can then pump more data into the FIFO > */ > - if (!(msg->flags & I2C_M_RD) && > + if (!process_call && !(msg->flags & I2C_M_RD) && > msg->len > iproc_i2c->tx_bytes) > val_intr_en |= BIT(IE_M_TX_UNDERRUN_SHIFT); > > @@ -743,6 +766,8 @@ static int bcm_iproc_i2c_xfer_single_msg(struct bcm_iproc_i2c_dev *iproc_i2c, > */ > val = BIT(M_CMD_START_BUSY_SHIFT); > if (msg->flags & I2C_M_RD) { > + u32 protocol; > + > iproc_i2c->rx_bytes = 0; > if (msg->len > M_RX_FIFO_MAX_THLD_VALUE) > iproc_i2c->thld_bytes = M_RX_FIFO_THLD_VALUE; > @@ -758,7 +783,10 @@ static int bcm_iproc_i2c_xfer_single_msg(struct bcm_iproc_i2c_dev *iproc_i2c, > /* enable the RX threshold interrupt */ > val_intr_en |= BIT(IE_M_RX_THLD_SHIFT); > > - val |= (M_CMD_PROTOCOL_BLK_RD << M_CMD_PROTOCOL_SHIFT) | > + protocol = process_call ? > + M_CMD_PROTOCOL_PROCESS : M_CMD_PROTOCOL_BLK_RD; > + > + val |= (protocol << M_CMD_PROTOCOL_SHIFT) | > (msg->len << M_CMD_RD_CNT_SHIFT); > } else { > val |= (M_CMD_PROTOCOL_BLK_WR << M_CMD_PROTOCOL_SHIFT); > @@ -774,17 +802,24 @@ static int bcm_iproc_i2c_xfer(struct i2c_adapter *adapter, > struct i2c_msg msgs[], int num) > { > struct bcm_iproc_i2c_dev *iproc_i2c = i2c_get_adapdata(adapter); > - int ret, i; > + bool process_call = false; > + int ret; > > - /* go through all messages */ > - for (i = 0; i < num; i++) { > - ret = bcm_iproc_i2c_xfer_single_msg(iproc_i2c, &msgs[i]); > - if (ret) { > - dev_dbg(iproc_i2c->device, "xfer failed\n"); > - return ret; > + if (num == 2) { > + /* Repeated start, use process call */ > + process_call = true; > + if (msgs[1].flags & I2C_M_NOSTART) { > + dev_err(iproc_i2c->device, "Invalid repeated start\n"); > + return -EOPNOTSUPP; > } > } > > + ret = bcm_iproc_i2c_xfer_internal(iproc_i2c, msgs, process_call); > + if (ret) { > + dev_dbg(iproc_i2c->device, "xfer failed\n"); > + return ret; > + } > + > return num; > } > > @@ -806,6 +841,8 @@ static uint32_t bcm_iproc_i2c_functionality(struct i2c_adapter *adap) > }; > > static struct i2c_adapter_quirks bcm_iproc_i2c_quirks = { > + .flags = I2C_AQ_COMB_WRITE_THEN_READ, > + .max_comb_1st_msg_len = M_TX_RX_FIFO_SIZE, > .max_read_len = M_RX_MAX_READ_LEN, > }; > > -- > 1.9.1 >