Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1518657
| Path | csiph.com!news.redatomik.org!enother.net!enother.net!enother.net!news.unit0.net!news.panservice.it!bofh.it!news.nic.it!robomod |
|---|---|
| From | tnhuynh@apm.com |
| Newsgroups | linux.kernel |
| Subject | [PATCH v4] i2c: designware: Implement support for SMBus block read and write |
| Date | Thu, 10 Nov 2016 04:00:06 +0100 |
| Message-ID | <sBNKS-7To-5@gated-at.bofh.it> (permalink) |
| X-Original-To | Jarkko Nikula <jarkko.nikula@linux.intel.com>, Andy Shevchenko <andriy.shevchenko@linux.intel.com>, Mika Westerberg <mika.westerberg@linux.intel.com>, Wolfram Sang <wsa@the-dreams.de>, linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org |
| Dkim-Signature | v=1; a=rsa-sha256; c=relaxed/relaxed; d=apm.com; s=apm; h=from:to:cc:subject:date:message-id; bh=xISNSfnAFNKEkPJx7viRfLyIzw9xlgDk2CpmHTywJ6s=; b=iy5B6pXN4EnzCrBFDEQzxrfvrg5370ETzOXwgZYIK5PKMzj6VqbNpwYiZPxZ2RKnN6 u1q2qXWWjLvC7Xh9cD8+7Xe38bM3kBHwxFObJwJ4Eeel4HyYvwQMfQC5SX7M/Lpz4Kei bc4zj0sI0hpGadg+fFXdpa6bNW9Nkx7TWzK/o= |
| X-Google-Dkim-Signature | v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=xISNSfnAFNKEkPJx7viRfLyIzw9xlgDk2CpmHTywJ6s=; b=PL1QJdmb6B2O1FsS67uSDzCtAZXTUq6eMXrN4XLmL4QGbl2BX/ukO1L8nfd5Vnr9WK kEVl50HScLY8911PfojuZU3cmor4Uc/MfFXbyhj3LbV8YJ82PUuLu5mQq5o6UUtqKGjG qthdzvZWJCgxmQQAWR/e8yzxciGgtWN/GeSMk+fwJkoqxrNVkHDccwLnQeDdhTfSRhCn iitmAUSwv3ML/VHu9Hc0leasTOnY1g/FBUXKiqdH4Kl6R4HemX3mkFcKJaNtqh7/ql6n LnBAVeMkIgudQVqArMbmda/rNmQ6OF6HN//jsY6+armOxX4xPU3SF7o3mtRt1bIG2RW0 I+fg== |
| X-Gm-Message-State | ABUngvfSlCauulPFW91iKix43ltaU2B/InP1jIfBPqc1MLFU9bY+19326MqNOGHRhmrqlvZX |
| X-Received | by 10.98.38.199 with SMTP id m190mr5431100pfm.45.1478746607876; Wed, 09 Nov 2016 18:56:47 -0800 (PST) |
| X-Mailer | git-send-email 1.7.1 |
| Sender | robomod@news.nic.it |
| List-ID | <linux-kernel.vger.kernel.org> |
| X-Mailing-List | linux-kernel@vger.kernel.org |
| Approved | robomod@news.nic.it |
| Lines | 138 |
| Organization | linux.* mail to news gateway |
| X-Original-Cc | Loc Ho <lho@apm.com>, Thang Nguyen <tqnguyen@apm.com>, Phong Vo <pvo@apm.com>, patches@apm.com, Tin Huynh <tnhuynh@apm.com> |
| X-Original-Date | Thu, 10 Nov 2016 09:56:33 +0700 |
| X-Original-Message-ID | <1478746593-10905-1-git-send-email-tnhuynh@apm.com> |
| X-Original-Sender | linux-kernel-owner@vger.kernel.org |
| Xref | csiph.com linux.kernel:1518657 |
Show key headers only | View raw
From: Tin Huynh <tnhuynh@apm.com>
Free and Open IPMI use SMBUS BLOCK Read/Write to support SSIF protocol.
However, I2C Designware Core Driver doesn't handle the case at the moment.
The below patch supports this feature.
Signed-off-by: Tin Huynh <tnhuynh@apm.com>
---
Change from V3:
- Correct coding conventions
- Make clean
Change from V2:
- Change subject of email
- Add a helper function to handle
length byte receiving
Change from V1:
- Remove empty lines
- Add flags variable to make clean code
- Change DW_DEFAULT_FUNCTIONALITY
in i2c-designware-pcidrv.c
---
drivers/i2c/busses/i2c-designware-core.c | 46 +++++++++++++++++++++++++--
drivers/i2c/busses/i2c-designware-pcidrv.c | 1 +
drivers/i2c/busses/i2c-designware-platdrv.c | 1 +
3 files changed, 45 insertions(+), 3 deletions(-)
diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
index 1fe93c4..c91d1b4 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -543,6 +543,8 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
intr_mask = DW_IC_INTR_DEFAULT_MASK;
for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) {
+ u32 flags = msgs[dev->msg_write_idx].flags;
+
/*
* if target address has changed, we need to
* reprogram the target address in the i2c
@@ -588,8 +590,15 @@ 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 sets 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 && !(flags & I2C_M_RECV_LEN))
cmd |= BIT(9);
if (need_restart) {
@@ -614,7 +623,12 @@ 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 transaction here.
+ */
+ if (buf_len > 0 || flags & I2C_M_RECV_LEN) {
/* more bytes to be written */
dev->status |= STATUS_WRITE_IN_PROGRESS;
break;
@@ -635,6 +649,24 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
dw_writel(dev, intr_mask, DW_IC_INTR_MASK);
}
+static u8
+i2c_dw_recv_len(struct dw_i2c_dev *dev, u8 len)
+{
+ struct i2c_msg *msgs = dev->msgs;
+ u32 flags = msgs[dev->msg_read_idx].flags;
+
+ /*
+ * Adjust the buffer length and mask the flag
+ * after receiving the first byte.
+ */
+ len += (flags & I2C_CLIENT_PEC) ? 2 : 1;
+ dev->tx_buf_len = len - min_t(u8, len, dev->rx_outstanding);
+ msgs[dev->msg_read_idx].len = len;
+ msgs[dev->msg_read_idx].flags &= ~I2C_M_RECV_LEN;
+
+ return len;
+}
+
static void
i2c_dw_read(struct dw_i2c_dev *dev)
{
@@ -659,7 +691,15 @@ 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);
+ u32 flags = msgs[dev->msg_read_idx].flags;
+
+ *buf = dw_readl(dev, DW_IC_DATA_CMD);
+ /* Ensure length byte is a valid value */
+ if (flags & I2C_M_RECV_LEN &&
+ *buf <= I2C_SMBUS_BLOCK_MAX && *buf > 0) {
+ len = i2c_dw_recv_len(dev, *buf);
+ }
+ buf++;
dev->rx_outstanding--;
}
diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c
index 96f8230..8ffe2da 100644
--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
+++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
@@ -75,6 +75,7 @@ struct dw_pci_controller {
I2C_FUNC_SMBUS_BYTE | \
I2C_FUNC_SMBUS_BYTE_DATA | \
I2C_FUNC_SMBUS_WORD_DATA | \
+ I2C_FUNC_SMBUS_BLOCK_DATA | \
I2C_FUNC_SMBUS_I2C_BLOCK)
/* Merrifield HCNT/LCNT/SDA hold time */
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 |
--
1.7.1
Back to linux.kernel | Previous | Next — Next in thread | Find similar | Unroll thread
[PATCH v4] i2c: designware: Implement support for SMBus block read and write tnhuynh@apm.com - 2016-11-10 04:00 +0100 Re: [PATCH v4] i2c: designware: Implement support for SMBus block read and write Jarkko Nikula <jarkko.nikula@linux.intel.com> - 2016-11-10 12:10 +0100 Re: [PATCH v4] i2c: designware: Implement support for SMBus block read and write Mika Westerberg <mika.westerberg@linux.intel.com> - 2016-11-11 12:10 +0100
csiph-web