diff options
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.patch | 385 |
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 + |