diff options
Diffstat (limited to 'drivers/i2c')
| -rw-r--r-- | drivers/i2c/busses/i2c-cadence.c | 28 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-qcom-geni.c | 6 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-rcar.c | 3 | ||||
| -rw-r--r-- | drivers/i2c/i2c-core-slave.c | 7 | 
4 files changed, 23 insertions, 21 deletions
diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c index 4b72398af505..e4b7f2a951ad 100644 --- a/drivers/i2c/busses/i2c-cadence.c +++ b/drivers/i2c/busses/i2c-cadence.c @@ -421,20 +421,21 @@ static irqreturn_t cdns_i2c_master_isr(void *ptr)  		/* Read data if receive data valid is set */  		while (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) &  		       CDNS_I2C_SR_RXDV) { -			/* -			 * Clear hold bit that was set for FIFO control if -			 * RX data left is less than FIFO depth, unless -			 * repeated start is selected. -			 */ -			if ((id->recv_count < CDNS_I2C_FIFO_DEPTH) && -			    !id->bus_hold_flag) -				cdns_i2c_clear_bus_hold(id); -  			if (id->recv_count > 0) {  				*(id->p_recv_buf)++ =  					cdns_i2c_readreg(CDNS_I2C_DATA_OFFSET);  				id->recv_count--;  				id->curr_recv_count--; + +				/* +				 * Clear hold bit that was set for FIFO control +				 * if RX data left is less than or equal to +				 * FIFO DEPTH unless repeated start is selected +				 */ +				if (id->recv_count <= CDNS_I2C_FIFO_DEPTH && +				    !id->bus_hold_flag) +					cdns_i2c_clear_bus_hold(id); +  			} else {  				dev_err(id->adap.dev.parent,  					"xfer_size reg rollover. xfer aborted!\n"); @@ -594,10 +595,8 @@ static void cdns_i2c_mrecv(struct cdns_i2c *id)  	 * Check for the message size against FIFO depth and set the  	 * 'hold bus' bit if it is greater than FIFO depth.  	 */ -	if ((id->recv_count > CDNS_I2C_FIFO_DEPTH)  || id->bus_hold_flag) +	if (id->recv_count > CDNS_I2C_FIFO_DEPTH)  		ctrl_reg |= CDNS_I2C_CR_HOLD; -	else -		ctrl_reg = ctrl_reg & ~CDNS_I2C_CR_HOLD;  	cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET); @@ -654,11 +653,8 @@ static void cdns_i2c_msend(struct cdns_i2c *id)  	 * Check for the message size against FIFO depth and set the  	 * 'hold bus' bit if it is greater than FIFO depth.  	 */ -	if ((id->send_count > CDNS_I2C_FIFO_DEPTH) || id->bus_hold_flag) +	if (id->send_count > CDNS_I2C_FIFO_DEPTH)  		ctrl_reg |= CDNS_I2C_CR_HOLD; -	else -		ctrl_reg = ctrl_reg & ~CDNS_I2C_CR_HOLD; -  	cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET);  	/* Clear the interrupts in interrupt status register. */ diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 18d1e4fd4cf3..7f130829bf01 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -367,7 +367,6 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,  		geni_se_select_mode(se, GENI_SE_FIFO);  	writel_relaxed(len, se->base + SE_I2C_RX_TRANS_LEN); -	geni_se_setup_m_cmd(se, I2C_READ, m_param);  	if (dma_buf && geni_se_rx_dma_prep(se, dma_buf, len, &rx_dma)) {  		geni_se_select_mode(se, GENI_SE_FIFO); @@ -375,6 +374,8 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,  		dma_buf = NULL;  	} +	geni_se_setup_m_cmd(se, I2C_READ, m_param); +  	time_left = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT);  	if (!time_left)  		geni_i2c_abort_xfer(gi2c); @@ -408,7 +409,6 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,  		geni_se_select_mode(se, GENI_SE_FIFO);  	writel_relaxed(len, se->base + SE_I2C_TX_TRANS_LEN); -	geni_se_setup_m_cmd(se, I2C_WRITE, m_param);  	if (dma_buf && geni_se_tx_dma_prep(se, dma_buf, len, &tx_dma)) {  		geni_se_select_mode(se, GENI_SE_FIFO); @@ -416,6 +416,8 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,  		dma_buf = NULL;  	} +	geni_se_setup_m_cmd(se, I2C_WRITE, m_param); +  	if (!dma_buf) /* Get FIFO IRQ */  		writel_relaxed(1, se->base + SE_GENI_TX_WATERMARK_REG); diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index a45c4bf1ec01..2e3e1bb75013 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -868,6 +868,7 @@ static int rcar_unreg_slave(struct i2c_client *slave)  	/* disable irqs and ensure none is running before clearing ptr */  	rcar_i2c_write(priv, ICSIER, 0);  	rcar_i2c_write(priv, ICSCR, 0); +	rcar_i2c_write(priv, ICSAR, 0); /* Gen2: must be 0 if not using slave */  	synchronize_irq(priv->irq);  	priv->slave = NULL; @@ -969,6 +970,8 @@ static int rcar_i2c_probe(struct platform_device *pdev)  	if (ret < 0)  		goto out_pm_put; +	rcar_i2c_write(priv, ICSAR, 0); /* Gen2: must be 0 if not using slave */ +  	if (priv->devtype == I2C_RCAR_GEN3) {  		priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);  		if (!IS_ERR(priv->rstc)) { diff --git a/drivers/i2c/i2c-core-slave.c b/drivers/i2c/i2c-core-slave.c index 5427f047faf0..1589179d5eb9 100644 --- a/drivers/i2c/i2c-core-slave.c +++ b/drivers/i2c/i2c-core-slave.c @@ -18,10 +18,8 @@ int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb)  {  	int ret; -	if (!client || !slave_cb) { -		WARN(1, "insufficient data\n"); +	if (WARN(IS_ERR_OR_NULL(client) || !slave_cb, "insufficient data\n"))  		return -EINVAL; -	}  	if (!(client->flags & I2C_CLIENT_SLAVE))  		dev_warn(&client->dev, "%s: client slave flag not set. You might see address collisions\n", @@ -60,6 +58,9 @@ int i2c_slave_unregister(struct i2c_client *client)  {  	int ret; +	if (IS_ERR_OR_NULL(client)) +		return -EINVAL; +  	if (!client->adapter->algo->unreg_slave) {  		dev_err(&client->dev, "%s: not supported by adapter\n", __func__);  		return -EOPNOTSUPP;  | 
