aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/backport-5.4/806-v5.8-i2c-pxa-re-arrange-functions-to-flow-better.patch
diff options
context:
space:
mode:
authorRussell King <linux@armlinux.org.uk>2020-05-21 09:57:27 +0100
committerPetr Štetiar <ynezz@true.cz>2020-05-21 12:55:31 +0200
commit714199ec3461b2b5bac9796d4f5ee79f56d2eb00 (patch)
tree9d02420e261024062d56df1b12776d9594c38658 /target/linux/generic/backport-5.4/806-v5.8-i2c-pxa-re-arrange-functions-to-flow-better.patch
parent72a1d5c3acd5b0bec46612f94bb8a82fe4d56179 (diff)
downloadupstream-714199ec3461b2b5bac9796d4f5ee79f56d2eb00.tar.gz
upstream-714199ec3461b2b5bac9796d4f5ee79f56d2eb00.tar.bz2
upstream-714199ec3461b2b5bac9796d4f5ee79f56d2eb00.zip
kernel: backport v5.8 i2c-pxa updates
Add i2c-pxa updates queued for v5.8, which add bus recovery to this driver; this is needed for the uDPU platform. Signed-off-by: Russell King <linux@armlinux.org.uk>
Diffstat (limited to 'target/linux/generic/backport-5.4/806-v5.8-i2c-pxa-re-arrange-functions-to-flow-better.patch')
-rw-r--r--target/linux/generic/backport-5.4/806-v5.8-i2c-pxa-re-arrange-functions-to-flow-better.patch385
1 files changed, 385 insertions, 0 deletions
diff --git a/target/linux/generic/backport-5.4/806-v5.8-i2c-pxa-re-arrange-functions-to-flow-better.patch b/target/linux/generic/backport-5.4/806-v5.8-i2c-pxa-re-arrange-functions-to-flow-better.patch
new file mode 100644
index 0000000000..efe7071de4
--- /dev/null
+++ b/target/linux/generic/backport-5.4/806-v5.8-i2c-pxa-re-arrange-functions-to-flow-better.patch
@@ -0,0 +1,385 @@
+From: Russell King <rmk+kernel@armlinux.org.uk>
+Bcc: linux@mail.armlinux.org.uk
+Cc: linux-i2c@vger.kernel.org
+Subject: [PATCH 04/17] i2c: pxa: re-arrange functions to flow better
+MIME-Version: 1.0
+Content-Disposition: inline
+Content-Transfer-Encoding: 8bit
+Content-Type: text/plain; charset="utf-8"
+
+Re-arrange the PXA I2C code to avoid forward declarations, and keep
+similar functionality (e.g. the non-IRQ mode support) together. This
+improves code readability.
+
+Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
+---
+ drivers/i2c/busses/i2c-pxa.c | 325 +++++++++++++++++------------------
+ 1 file changed, 162 insertions(+), 163 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
+index ee83d2e46de0..e5f00ae39861 100644
+--- a/drivers/i2c/busses/i2c-pxa.c
++++ b/drivers/i2c/busses/i2c-pxa.c
+@@ -327,7 +327,6 @@ static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why)
+ #endif /* ifdef DEBUG / else */
+
+ static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret);
+-static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id);
+
+ static inline int i2c_pxa_is_slavemode(struct pxa_i2c *i2c)
+ {
+@@ -703,34 +702,6 @@ static inline void i2c_pxa_stop_message(struct pxa_i2c *i2c)
+ writel(icr, _ICR(i2c));
+ }
+
+-static int i2c_pxa_pio_set_master(struct pxa_i2c *i2c)
+-{
+- /* make timeout the same as for interrupt based functions */
+- long timeout = 2 * DEF_TIMEOUT;
+-
+- /*
+- * Wait for the bus to become free.
+- */
+- while (timeout-- && readl(_ISR(i2c)) & (ISR_IBB | ISR_UB)) {
+- udelay(1000);
+- show_state(i2c);
+- }
+-
+- if (timeout < 0) {
+- show_state(i2c);
+- dev_err(&i2c->adap.dev,
+- "i2c_pxa: timeout waiting for bus free\n");
+- return I2C_RETRY;
+- }
+-
+- /*
+- * Set master mode.
+- */
+- writel(readl(_ICR(i2c)) | ICR_SCLE, _ICR(i2c));
+-
+- return 0;
+-}
+-
+ /*
+ * PXA I2C send master code
+ * 1. Load master code to IDBR and send it.
+@@ -759,140 +730,6 @@ static int i2c_pxa_send_mastercode(struct pxa_i2c *i2c)
+ return (timeout == 0) ? I2C_RETRY : 0;
+ }
+
+-static int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c,
+- struct i2c_msg *msg, int num)
+-{
+- unsigned long timeout = 500000; /* 5 seconds */
+- int ret = 0;
+-
+- ret = i2c_pxa_pio_set_master(i2c);
+- if (ret)
+- goto out;
+-
+- i2c->msg = msg;
+- i2c->msg_num = num;
+- i2c->msg_idx = 0;
+- i2c->msg_ptr = 0;
+- i2c->irqlogidx = 0;
+-
+- i2c_pxa_start_message(i2c);
+-
+- while (i2c->msg_num > 0 && --timeout) {
+- i2c_pxa_handler(0, i2c);
+- udelay(10);
+- }
+-
+- i2c_pxa_stop_message(i2c);
+-
+- /*
+- * We place the return code in i2c->msg_idx.
+- */
+- ret = i2c->msg_idx;
+-
+-out:
+- if (timeout == 0) {
+- i2c_pxa_scream_blue_murder(i2c, "timeout");
+- ret = I2C_RETRY;
+- }
+-
+- return ret;
+-}
+-
+-/*
+- * We are protected by the adapter bus mutex.
+- */
+-static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num)
+-{
+- long timeout;
+- int ret;
+-
+- /*
+- * Wait for the bus to become free.
+- */
+- ret = i2c_pxa_wait_bus_not_busy(i2c);
+- if (ret) {
+- dev_err(&i2c->adap.dev, "i2c_pxa: timeout waiting for bus free\n");
+- goto out;
+- }
+-
+- /*
+- * Set master mode.
+- */
+- ret = i2c_pxa_set_master(i2c);
+- if (ret) {
+- dev_err(&i2c->adap.dev, "i2c_pxa_set_master: error %d\n", ret);
+- goto out;
+- }
+-
+- if (i2c->high_mode) {
+- ret = i2c_pxa_send_mastercode(i2c);
+- if (ret) {
+- dev_err(&i2c->adap.dev, "i2c_pxa_send_mastercode timeout\n");
+- goto out;
+- }
+- }
+-
+- spin_lock_irq(&i2c->lock);
+-
+- i2c->msg = msg;
+- i2c->msg_num = num;
+- i2c->msg_idx = 0;
+- i2c->msg_ptr = 0;
+- i2c->irqlogidx = 0;
+-
+- i2c_pxa_start_message(i2c);
+-
+- spin_unlock_irq(&i2c->lock);
+-
+- /*
+- * The rest of the processing occurs in the interrupt handler.
+- */
+- timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
+- i2c_pxa_stop_message(i2c);
+-
+- /*
+- * We place the return code in i2c->msg_idx.
+- */
+- ret = i2c->msg_idx;
+-
+- if (!timeout && i2c->msg_num) {
+- i2c_pxa_scream_blue_murder(i2c, "timeout");
+- ret = I2C_RETRY;
+- }
+-
+- out:
+- return ret;
+-}
+-
+-static int i2c_pxa_pio_xfer(struct i2c_adapter *adap,
+- struct i2c_msg msgs[], int num)
+-{
+- struct pxa_i2c *i2c = adap->algo_data;
+- int ret, i;
+-
+- /* If the I2C controller is disabled we need to reset it
+- (probably due to a suspend/resume destroying state). We do
+- this here as we can then avoid worrying about resuming the
+- controller before its users. */
+- if (!(readl(_ICR(i2c)) & ICR_IUE))
+- i2c_pxa_reset(i2c);
+-
+- for (i = adap->retries; i >= 0; i--) {
+- ret = i2c_pxa_do_pio_xfer(i2c, msgs, num);
+- if (ret != I2C_RETRY)
+- goto out;
+-
+- if (i2c_debug)
+- dev_dbg(&adap->dev, "Retrying transmission\n");
+- udelay(100);
+- }
+- i2c_pxa_scream_blue_murder(i2c, "exhausted retries");
+- ret = -EREMOTEIO;
+- out:
+- i2c_pxa_set_slave(i2c, ret);
+- return ret;
+-}
+-
+ /*
+ * i2c_pxa_master_complete - complete the message and wake up.
+ */
+@@ -1099,6 +936,71 @@ static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id)
+ return IRQ_HANDLED;
+ }
+
++/*
++ * We are protected by the adapter bus mutex.
++ */
++static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num)
++{
++ long timeout;
++ int ret;
++
++ /*
++ * Wait for the bus to become free.
++ */
++ ret = i2c_pxa_wait_bus_not_busy(i2c);
++ if (ret) {
++ dev_err(&i2c->adap.dev, "i2c_pxa: timeout waiting for bus free\n");
++ goto out;
++ }
++
++ /*
++ * Set master mode.
++ */
++ ret = i2c_pxa_set_master(i2c);
++ if (ret) {
++ dev_err(&i2c->adap.dev, "i2c_pxa_set_master: error %d\n", ret);
++ goto out;
++ }
++
++ if (i2c->high_mode) {
++ ret = i2c_pxa_send_mastercode(i2c);
++ if (ret) {
++ dev_err(&i2c->adap.dev, "i2c_pxa_send_mastercode timeout\n");
++ goto out;
++ }
++ }
++
++ spin_lock_irq(&i2c->lock);
++
++ i2c->msg = msg;
++ i2c->msg_num = num;
++ i2c->msg_idx = 0;
++ i2c->msg_ptr = 0;
++ i2c->irqlogidx = 0;
++
++ i2c_pxa_start_message(i2c);
++
++ spin_unlock_irq(&i2c->lock);
++
++ /*
++ * The rest of the processing occurs in the interrupt handler.
++ */
++ timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
++ i2c_pxa_stop_message(i2c);
++
++ /*
++ * We place the return code in i2c->msg_idx.
++ */
++ ret = i2c->msg_idx;
++
++ if (!timeout && i2c->msg_num) {
++ i2c_pxa_scream_blue_murder(i2c, "timeout");
++ ret = I2C_RETRY;
++ }
++
++ out:
++ return ret;
++}
+
+ static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+ {
+@@ -1132,6 +1034,103 @@ static const struct i2c_algorithm i2c_pxa_algorithm = {
+ .functionality = i2c_pxa_functionality,
+ };
+
++/* Non-interrupt mode support */
++static int i2c_pxa_pio_set_master(struct pxa_i2c *i2c)
++{
++ /* make timeout the same as for interrupt based functions */
++ long timeout = 2 * DEF_TIMEOUT;
++
++ /*
++ * Wait for the bus to become free.
++ */
++ while (timeout-- && readl(_ISR(i2c)) & (ISR_IBB | ISR_UB)) {
++ udelay(1000);
++ show_state(i2c);
++ }
++
++ if (timeout < 0) {
++ show_state(i2c);
++ dev_err(&i2c->adap.dev,
++ "i2c_pxa: timeout waiting for bus free\n");
++ return I2C_RETRY;
++ }
++
++ /*
++ * Set master mode.
++ */
++ writel(readl(_ICR(i2c)) | ICR_SCLE, _ICR(i2c));
++
++ return 0;
++}
++
++static int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c,
++ struct i2c_msg *msg, int num)
++{
++ unsigned long timeout = 500000; /* 5 seconds */
++ int ret = 0;
++
++ ret = i2c_pxa_pio_set_master(i2c);
++ if (ret)
++ goto out;
++
++ i2c->msg = msg;
++ i2c->msg_num = num;
++ i2c->msg_idx = 0;
++ i2c->msg_ptr = 0;
++ i2c->irqlogidx = 0;
++
++ i2c_pxa_start_message(i2c);
++
++ while (i2c->msg_num > 0 && --timeout) {
++ i2c_pxa_handler(0, i2c);
++ udelay(10);
++ }
++
++ i2c_pxa_stop_message(i2c);
++
++ /*
++ * We place the return code in i2c->msg_idx.
++ */
++ ret = i2c->msg_idx;
++
++out:
++ if (timeout == 0) {
++ i2c_pxa_scream_blue_murder(i2c, "timeout");
++ ret = I2C_RETRY;
++ }
++
++ return ret;
++}
++
++static int i2c_pxa_pio_xfer(struct i2c_adapter *adap,
++ struct i2c_msg msgs[], int num)
++{
++ struct pxa_i2c *i2c = adap->algo_data;
++ int ret, i;
++
++ /* If the I2C controller is disabled we need to reset it
++ (probably due to a suspend/resume destroying state). We do
++ this here as we can then avoid worrying about resuming the
++ controller before its users. */
++ if (!(readl(_ICR(i2c)) & ICR_IUE))
++ i2c_pxa_reset(i2c);
++
++ for (i = adap->retries; i >= 0; i--) {
++ ret = i2c_pxa_do_pio_xfer(i2c, msgs, num);
++ if (ret != I2C_RETRY)
++ goto out;
++
++ if (i2c_debug)
++ dev_dbg(&adap->dev, "Retrying transmission\n");
++ udelay(100);
++ }
++ i2c_pxa_scream_blue_murder(i2c, "exhausted retries");
++ ret = -EREMOTEIO;
++ out:
++ i2c_pxa_set_slave(i2c, ret);
++ return ret;
++}
++
+ static const struct i2c_algorithm i2c_pxa_pio_algorithm = {
+ .master_xfer = i2c_pxa_pio_xfer,
+ .functionality = i2c_pxa_functionality,
+--
+2.20.1
+