aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/brcm2708/patches-4.9/950-0110-i2c-bcm2835-Add-support-for-Repeated-Start-Condition.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/brcm2708/patches-4.9/950-0110-i2c-bcm2835-Add-support-for-Repeated-Start-Condition.patch')
-rw-r--r--target/linux/brcm2708/patches-4.9/950-0110-i2c-bcm2835-Add-support-for-Repeated-Start-Condition.patch181
1 files changed, 0 insertions, 181 deletions
diff --git a/target/linux/brcm2708/patches-4.9/950-0110-i2c-bcm2835-Add-support-for-Repeated-Start-Condition.patch b/target/linux/brcm2708/patches-4.9/950-0110-i2c-bcm2835-Add-support-for-Repeated-Start-Condition.patch
deleted file mode 100644
index 9ae16e426a..0000000000
--- a/target/linux/brcm2708/patches-4.9/950-0110-i2c-bcm2835-Add-support-for-Repeated-Start-Condition.patch
+++ /dev/null
@@ -1,181 +0,0 @@
-From db656eb11aebb0d7e4b833f9b452503ddb1351f1 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
-Date: Fri, 23 Sep 2016 04:54:27 +0200
-Subject: [PATCH] i2c: bcm2835: Add support for Repeated Start Condition
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Documentation/i2c/i2c-protocol states that Combined transactions should
-separate messages with a Start bit and end the whole transaction with a
-Stop bit. This patch adds support for issuing only a Start between
-messages instead of a Stop followed by a Start.
-
-This implementation differs from downstream i2c-bcm2708 in 2 respects:
-- it uses an interrupt to detect that the transfer is active instead
- of using polling. There is no interrupt for Transfer Active, but by
- not prefilling the FIFO it's possible to use the TXW interrupt.
-- when resetting/disabling the controller between transfers it writes
- CLEAR to the control register instead of just zero.
- Using just zero gave many errors. This might be the reason why
- downstream had to disable this feature and make it available with a
- module parameter.
-
-I have run thousands of transfers to a DS1307 (rtc), MMA8451 (accel)
-and AT24C32 (eeprom) in parallel without problems.
-
-Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
-Acked-by: Eric Anholt <eric@anholt.net>
----
- drivers/i2c/busses/i2c-bcm2835.c | 101 ++++++++++++++++++++++++---------------
- 1 file changed, 63 insertions(+), 38 deletions(-)
-
---- a/drivers/i2c/busses/i2c-bcm2835.c
-+++ b/drivers/i2c/busses/i2c-bcm2835.c
-@@ -63,6 +63,7 @@ struct bcm2835_i2c_dev {
- struct i2c_adapter adapter;
- struct completion completion;
- struct i2c_msg *curr_msg;
-+ int num_msgs;
- u32 msg_err;
- u8 *msg_buf;
- size_t msg_buf_remaining;
-@@ -110,6 +111,45 @@ static void bcm2835_drain_rxfifo(struct
- }
-
- /*
-+ * Repeated Start Condition (Sr)
-+ * The BCM2835 ARM Peripherals datasheet mentions a way to trigger a Sr when it
-+ * talks about reading from a slave with 10 bit address. This is achieved by
-+ * issuing a write, poll the I2CS.TA flag and wait for it to be set, and then
-+ * issue a read.
-+ * A comment in https://github.com/raspberrypi/linux/issues/254 shows how the
-+ * firmware actually does it using polling and says that it's a workaround for
-+ * a problem in the state machine.
-+ * It turns out that it is possible to use the TXW interrupt to know when the
-+ * transfer is active, provided the FIFO has not been prefilled.
-+ */
-+
-+static void bcm2835_i2c_start_transfer(struct bcm2835_i2c_dev *i2c_dev)
-+{
-+ u32 c = BCM2835_I2C_C_ST | BCM2835_I2C_C_I2CEN;
-+ struct i2c_msg *msg = i2c_dev->curr_msg;
-+ bool last_msg = (i2c_dev->num_msgs == 1);
-+
-+ if (!i2c_dev->num_msgs)
-+ return;
-+
-+ i2c_dev->num_msgs--;
-+ i2c_dev->msg_buf = msg->buf;
-+ i2c_dev->msg_buf_remaining = msg->len;
-+
-+ if (msg->flags & I2C_M_RD)
-+ c |= BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR;
-+ else
-+ c |= BCM2835_I2C_C_INTT;
-+
-+ if (last_msg)
-+ c |= BCM2835_I2C_C_INTD;
-+
-+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr);
-+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len);
-+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c);
-+}
-+
-+/*
- * Note about I2C_C_CLEAR on error:
- * The I2C_C_CLEAR on errors will take some time to resolve -- if you were in
- * non-idle state and I2C_C_READ, it sets an abort_rx flag and runs through
-@@ -153,6 +193,12 @@ static irqreturn_t bcm2835_i2c_isr(int t
- }
-
- bcm2835_fill_txfifo(i2c_dev);
-+
-+ if (i2c_dev->num_msgs && !i2c_dev->msg_buf_remaining) {
-+ i2c_dev->curr_msg++;
-+ bcm2835_i2c_start_transfer(i2c_dev);
-+ }
-+
- return IRQ_HANDLED;
- }
-
-@@ -177,30 +223,25 @@ complete:
- return IRQ_HANDLED;
- }
-
--static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev,
-- struct i2c_msg *msg)
-+static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
-+ int num)
- {
-- u32 c;
-+ struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
- unsigned long time_left;
-+ int i;
-
-- i2c_dev->curr_msg = msg;
-- i2c_dev->msg_buf = msg->buf;
-- i2c_dev->msg_buf_remaining = msg->len;
-- reinit_completion(&i2c_dev->completion);
--
-- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR);
-+ for (i = 0; i < (num - 1); i++)
-+ if (msgs[i].flags & I2C_M_RD) {
-+ dev_warn_once(i2c_dev->dev,
-+ "only one read message supported, has to be last\n");
-+ return -EOPNOTSUPP;
-+ }
-
-- if (msg->flags & I2C_M_RD) {
-- c = BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR;
-- } else {
-- c = BCM2835_I2C_C_INTT;
-- bcm2835_fill_txfifo(i2c_dev);
-- }
-- c |= BCM2835_I2C_C_ST | BCM2835_I2C_C_INTD | BCM2835_I2C_C_I2CEN;
-+ i2c_dev->curr_msg = msgs;
-+ i2c_dev->num_msgs = num;
-+ reinit_completion(&i2c_dev->completion);
-
-- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr);
-- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len);
-- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c);
-+ bcm2835_i2c_start_transfer(i2c_dev);
-
- time_left = wait_for_completion_timeout(&i2c_dev->completion,
- BCM2835_I2C_TIMEOUT);
-@@ -211,31 +252,15 @@ static int bcm2835_i2c_xfer_msg(struct b
- return -ETIMEDOUT;
- }
-
-- if (likely(!i2c_dev->msg_err))
-- return 0;
-+ if (!i2c_dev->msg_err)
-+ return num;
-
- dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err);
-
- if (i2c_dev->msg_err & BCM2835_I2C_S_ERR)
- return -EREMOTEIO;
-- else
-- return -EIO;
--}
--
--static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
-- int num)
--{
-- struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
-- int i;
-- int ret = 0;
--
-- for (i = 0; i < num; i++) {
-- ret = bcm2835_i2c_xfer_msg(i2c_dev, &msgs[i]);
-- if (ret)
-- break;
-- }
-
-- return ret ?: i;
-+ return -EIO;
- }
-
- static u32 bcm2835_i2c_func(struct i2c_adapter *adap)