From patchwork Tue Oct 25 04:35:13 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: tnhuynh@apm.com X-Patchwork-Id: 686309 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3t30hK2nJKz9t2Y for ; Tue, 25 Oct 2016 15:35:43 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=apm.com header.i=@apm.com header.b=n1phq6u5; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754747AbcJYEfk (ORCPT ); Tue, 25 Oct 2016 00:35:40 -0400 Received: from mail-pf0-f169.google.com ([209.85.192.169]:33111 "EHLO mail-pf0-f169.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754020AbcJYEfk (ORCPT ); Tue, 25 Oct 2016 00:35:40 -0400 Received: by mail-pf0-f169.google.com with SMTP id 128so111856314pfz.0 for ; Mon, 24 Oct 2016 21:35:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=apm.com; s=apm; h=mime-version:from:to:cc:subject:date:message-id; bh=jwPd/4C81hROr7zdDh5wZzzzCZ0EhLl6Sd6HedW3xWA=; b=n1phq6u50TgEvysAQH4y6s10WQz7kgLIvzEg1Y7p6LDjAdNDZjKGiiv6pOkxcnnglw lieYQWRH/nILSm+42kWuW8altTey7GpO9mkkUVDIAJTH3Xrsp+Qo501tjUf31vciQjGF X0Hp2wnbZ5ng0av+tjMU+/Z3FK3Staadyv7xo= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:from:to:cc:subject:date:message-id; bh=jwPd/4C81hROr7zdDh5wZzzzCZ0EhLl6Sd6HedW3xWA=; b=Cyvs03fFas2WS7dfWStYk+FEAXhy/uMueQ6oIFE9ecC2MZLMm5Lxb2LSdgI+UtqSFh nJEry5WTnGaqmIuDlKlzmkeL7dTTUS+qxRuEFm3ZneCCZLwJhiSGe8c6/TYK+l3Diax8 QLQEONr7VTCVtP1EdQcaTsDslxN1FFuKmY64YxWnVHsuwLTrZHnQrJTXh5OEw9F4Is97 Z2B5hOsFSkzmk6QDvljYgF26s8F8Yggf5zi34L45kWSlaiSSMSmfMy7na/0UngJ06MNs kbw+55rz3t981RNG289K/optfL4MCX7IPBsu3I9of5q+z+9+CUH5boKK1B0u2sEYRgxM 662A== X-Gm-Message-State: ABUngvfunnVmVud+XAH3PaXDZXBicyRdTk3MermV60qbgG/qdy8LSF97nX1f1QEGRHAKj3jR0fLMe7QKAmsKOWm6CLO5EhENURGvxaIk/HKnba0Eesd7YmXdlhnEKecrnq+mKig= MIME-Version: 1.0 X-Received: by 10.99.43.8 with SMTP id r8mr29447193pgr.165.1477370139039; Mon, 24 Oct 2016 21:35:39 -0700 (PDT) Received: from localhost.localdomain ([118.69.219.197]) by smtp.gmail.com with ESMTPSA id i123sm28857692pfg.30.2016.10.24.21.35.32 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 24 Oct 2016 21:35:38 -0700 (PDT) From: tnhuynh@apm.com To: Jarkko Nikula , Andy Shevchenko , Mika Westerberg , Wolfram Sang , linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Loc Ho , Thang Nguyen , Phong Vo , patches@apm.com, Tin Huynh Subject: [PATCH v1] I2C Designware Core Supports SMBUS BLOCK Date: Tue, 25 Oct 2016 11:35:13 +0700 Message-Id: <1477370113-15145-1-git-send-email-tnhuynh@apm.com> X-Mailer: git-send-email 1.7.1 Sender: linux-i2c-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org From: Tin Huynh Free and Open IPMI use SMBUS BLOCK Read/Write to support SSIF protocol. However, I2C Designwave Core Driver doesn't handle the case at the moment. The below patch supports this feature. Signed-off-by: Tin Huynh --- drivers/i2c/busses/i2c-designware-core.c | 42 +++++++++++++++++++++++++-- drivers/i2c/busses/i2c-designware-platdrv.c | 1 + 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index 1fe93c4..3abf0e5 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -588,8 +588,17 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) * detected from the registers so we set it always * when writing/reading the last byte. */ + + /* + * i2c-core.c always set the buffer length of + * I2C_FUNC_SMBUS_BLOCK_DATA to 1. The length will + * be adjusted when receiving the first byte. + * Thus we can't stop the transaction here. + */ + if (dev->msg_write_idx == dev->msgs_num - 1 && - buf_len == 1) + buf_len == 1 && + !(msgs[dev->msg_write_idx].flags & I2C_M_RECV_LEN)) cmd |= BIT(9); if (need_restart) { @@ -614,7 +623,14 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) dev->tx_buf = buf; dev->tx_buf_len = buf_len; - if (buf_len > 0) { + /* + * Because we don't know the buffer length in the + * I2C_FUNC_SMBUS_BLOCK_DATA case, we can't stop + * the transcation here. + */ + + if (buf_len > 0 || + msgs[dev->msg_write_idx].flags & I2C_M_RECV_LEN) { /* more bytes to be written */ dev->status |= STATUS_WRITE_IN_PROGRESS; break; @@ -659,7 +675,27 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) rx_valid = dw_readl(dev, DW_IC_RXFLR); for (; len > 0 && rx_valid > 0; len--, rx_valid--) { - *buf++ = dw_readl(dev, DW_IC_DATA_CMD); + *buf = dw_readl(dev, DW_IC_DATA_CMD); + /* ensure length byte is a valid value */ + if (msgs[dev->msg_read_idx].flags & I2C_M_RECV_LEN + && *buf <= I2C_SMBUS_BLOCK_MAX && *buf > 0) { + /* + * Adjust the buffer length and mask the flag + * after receiving the first byte + */ + msgs[dev->msg_read_idx].flags &= + ~I2C_M_RECV_LEN; + len = *buf + 1; + /* Increase one with PEC flag */ + if (msgs[dev->msg_read_idx].flags & + I2C_CLIENT_PEC) + len++; + + dev->tx_buf_len = len > dev->rx_outstanding ? + len - dev->rx_outstanding : 0; + msgs[dev->msg_read_idx].len = len; + } + buf++; dev->rx_outstanding--; } diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 0b42a12..886fb62 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -220,6 +220,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_I2C_BLOCK; dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |