[Arm-dev] [PATCH 09/11] Add SMBus block read/write support for Designware I2C
Duc Dang
dhdang at apm.com
Fri Nov 11 02:47:51 UTC 2016
The posted upstream patch (v4, https://lkml.org/lkml/2016/11/9/930)
already got an ack by Jarkko Nikula (https://lkml.org/lkml/2016/11/10/193)
Signed-off-by: Duc Dang <dhdang at apm.com>
---
...are-Implement-support-for-SMBus-block-rea.patch | 135 +++++++++++++++++++++
SPECS/kernel-aarch64.spec | 3 +
2 files changed, 138 insertions(+)
create mode 100644 SOURCES/1019-i2c-designware-Implement-support-for-SMBus-block-rea.patch
diff --git a/SOURCES/1019-i2c-designware-Implement-support-for-SMBus-block-rea.patch b/SOURCES/1019-i2c-designware-Implement-support-for-SMBus-block-rea.patch
new file mode 100644
index 0000000..eb732e3
--- /dev/null
+++ b/SOURCES/1019-i2c-designware-Implement-support-for-SMBus-block-rea.patch
@@ -0,0 +1,135 @@
+From 4211222134d5758e53f667c6ebdf1e0c55d9137b Mon Sep 17 00:00:00 2001
+From: Tin Huynh <tnhuynh at apm.com>
+Date: Thu, 10 Nov 2016 17:33:00 -0600
+Subject: [PATCH] i2c: designware: Implement support for SMBus block read and
+ write
+
+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 at apm.com>
+Acked-by: Jarkko Nikula <jarkko.nikula at linux.intel.com>
+
+[Apply from posted v4 patch (already acked-by Jarkko Nikula,
+https://lkml.org/lkml/2016/11/10/193) to CentOS 7.3 AltArch]
+Signed-off-by: Duc Dang <dhdang at apm.com>
+---
+ 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 10fbd6d..927849b 100644
+--- a/drivers/i2c/busses/i2c-designware-core.c
++++ b/drivers/i2c/busses/i2c-designware-core.c
+@@ -470,6 +470,8 @@ i2c_dw_xfer_msg(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
+@@ -515,8 +517,15 @@ i2c_dw_xfer_msg(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) {
+@@ -541,7 +550,12 @@ i2c_dw_xfer_msg(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;
+@@ -562,6 +576,24 @@ i2c_dw_xfer_msg(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)
+ {
+@@ -586,7 +618,15 @@ i2c_dw_read(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 7368be0..13578d9 100644
+--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
++++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
+@@ -78,6 +78,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)
+
+ /* BayTrail HCNT/LCNT/SDA hold time */
+diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
+index 438f1b4..f67aaed 100644
+--- a/drivers/i2c/busses/i2c-designware-platdrv.c
++++ b/drivers/i2c/busses/i2c-designware-platdrv.c
+@@ -210,6 +210,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;
+ if (clk_freq == 100000)
+ dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
+--
+1.8.3.1
+
diff --git a/SPECS/kernel-aarch64.spec b/SPECS/kernel-aarch64.spec
index 4c20b21..de899ca 100644
--- a/SPECS/kernel-aarch64.spec
+++ b/SPECS/kernel-aarch64.spec
@@ -343,6 +343,7 @@ Patch1015: 1015-drivers-net-xgene-fix-Use-GPIO-to-get-link-status.patch
Patch1016: 1016-drivers-net-xgene-fix-Disable-coalescing-on-v1-hardw.patch
Patch1017: 1017-drivers-net-xgene-fix-Coalescing-values-for-v2-hardw.patch
Patch1018: 1018-ACPI-PCI-fix-GIC-irq-model-default-PCI-IRQ-polarity.patch
+Patch1019: 1019-i2c-designware-Implement-support-for-SMBus-block-rea.patch
# QDF2400 Patches
Patch4000: 4000-arm64-Define-Qualcomm-Technologies-ARMv8-CPU.patch
@@ -696,6 +697,7 @@ git am %{PATCH1015}
git am %{PATCH1016}
git am %{PATCH1017}
git am %{PATCH1018}
+git am %{PATCH1019}
# Apply QDF2400 patches
git am %{PATCH4000}
@@ -1475,6 +1477,7 @@ fi
%changelog
* Thu Nov 10 2016 Duc Dang <dhdang at apm.com> [4.5.0-17.el7]
+- Integrated posted patch to support SMBus block read/write for Designware I2C
- Integrate upstream fix for GIC default PCI IRQ polarity
- Integrate upstream updates for X-Gene Enet driver
- Avoid dma_buffer overrun for SlimPRO I2C driver
--
1.8.3.1
More information about the Arm-dev
mailing list