 68d9cb8214
			
		
	
	68d9cb8214
	
	
	
		
			
			Run tested: ath79, ipq40xx Build tested: ath79, ipq40xx Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
		
			
				
	
	
		
			381 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			381 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| 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(-)
 | |
| 
 | |
| --- a/drivers/i2c/busses/i2c-pxa.c
 | |
| +++ b/drivers/i2c/busses/i2c-pxa.c
 | |
| @@ -326,7 +326,6 @@ static void i2c_pxa_scream_blue_murder(s
 | |
|  #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)
 | |
|  {
 | |
| @@ -697,34 +696,6 @@ static inline void i2c_pxa_stop_message(
 | |
|  	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.
 | |
| @@ -753,140 +724,6 @@ static int i2c_pxa_send_mastercode(struc
 | |
|  	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.
 | |
|   */
 | |
| @@ -1093,6 +930,71 @@ static irqreturn_t i2c_pxa_handler(int t
 | |
|  	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)
 | |
|  {
 | |
| @@ -1126,6 +1028,103 @@ static const struct i2c_algorithm i2c_px
 | |
|  	.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,
 |