cpu/allwinner/a10/twi.c: Refactor I²C handler to use i2c_seg API
The coreboot I²C API was completely reworked in commit
* cdb61a6 i2c: Replace the i2c API.
For the allwinner I²C driver, wrappers to the old API were provided
on a "best guess" basis. Replace these wrappers with proper
transaction handling based on the i2c_seg API.
Change-Id: Ibdda3b022ce4876deb2906e17a5a0ca9e939aada
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Reviewed-on: http://review.coreboot.org/8431
Tested-by: build bot (Jenkins)
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
			
			
This commit is contained in:
		@@ -109,29 +109,11 @@ static void i2c_send_stop(struct a1x_twi *twi)
 | 
				
			|||||||
	write32(reg32, &twi->ctl);
 | 
						write32(reg32, &twi->ctl);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int i2c_read(unsigned bus, unsigned chip, unsigned addr,
 | 
					static int i2c_read(struct a1x_twi *twi, uint8_t chip,
 | 
				
			||||||
	     uint8_t *buf, unsigned len)
 | 
								uint8_t *buf, size_t len)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned count = len;
 | 
						unsigned count = len;
 | 
				
			||||||
	enum twi_status expected_status;
 | 
						enum twi_status expected_status;
 | 
				
			||||||
	struct a1x_twi *twi = (void *)TWI_BASE(bus);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (wait_until_idle(twi) != CB_SUCCESS)
 | 
					 | 
				
			||||||
		return CB_ERR;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	i2c_send_start(twi);
 | 
					 | 
				
			||||||
	if (wait_for_status(twi) != TWI_STAT_TX_START)
 | 
					 | 
				
			||||||
		return CB_ERR;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Send chip address */
 | 
					 | 
				
			||||||
	i2c_send_data(twi, chip << 1);
 | 
					 | 
				
			||||||
	if (wait_for_status(twi) != TWI_STAT_TX_AW_ACK)
 | 
					 | 
				
			||||||
		return CB_ERR;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Send data address */
 | 
					 | 
				
			||||||
	i2c_send_data(twi, addr);
 | 
					 | 
				
			||||||
	if (wait_for_status(twi) != TWI_STAT_TXD_ACK)
 | 
					 | 
				
			||||||
		return CB_ERR;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Send restart for read */
 | 
						/* Send restart for read */
 | 
				
			||||||
	i2c_send_start(twi);
 | 
						i2c_send_start(twi);
 | 
				
			||||||
@@ -164,19 +146,13 @@ static int i2c_read(unsigned bus, unsigned chip, unsigned addr,
 | 
				
			|||||||
		count--;
 | 
							count--;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	i2c_send_stop(twi);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return len;
 | 
						return len;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int i2c_write(unsigned bus, unsigned chip, unsigned addr,
 | 
					static int i2c_write(struct a1x_twi *twi, uint8_t chip,
 | 
				
			||||||
	      const uint8_t *buf, unsigned len)
 | 
							     const uint8_t *buf, size_t len)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned count = len;
 | 
						size_t count = len;
 | 
				
			||||||
	struct a1x_twi *twi = (void *)TWI_BASE(bus);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (wait_until_idle(twi) != CB_SUCCESS)
 | 
					 | 
				
			||||||
		return CB_ERR;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	i2c_send_start(twi);
 | 
						i2c_send_start(twi);
 | 
				
			||||||
	if (wait_for_status(twi) != TWI_STAT_TX_START)
 | 
						if (wait_for_status(twi) != TWI_STAT_TX_START)
 | 
				
			||||||
@@ -187,11 +163,6 @@ static int i2c_write(unsigned bus, unsigned chip, unsigned addr,
 | 
				
			|||||||
	if (wait_for_status(twi) != TWI_STAT_TX_AW_ACK)
 | 
						if (wait_for_status(twi) != TWI_STAT_TX_AW_ACK)
 | 
				
			||||||
		return CB_ERR;
 | 
							return CB_ERR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Send data address */
 | 
					 | 
				
			||||||
	i2c_send_data(twi, addr);
 | 
					 | 
				
			||||||
	if (wait_for_status(twi) != TWI_STAT_TXD_ACK)
 | 
					 | 
				
			||||||
		return CB_ERR;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Send data */
 | 
						/* Send data */
 | 
				
			||||||
	while (count > 0) {
 | 
						while (count > 0) {
 | 
				
			||||||
		i2c_send_data(twi, *buf++);
 | 
							i2c_send_data(twi, *buf++);
 | 
				
			||||||
@@ -200,39 +171,35 @@ static int i2c_write(unsigned bus, unsigned chip, unsigned addr,
 | 
				
			|||||||
		count--;
 | 
							count--;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	i2c_send_stop(twi);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return len;
 | 
						return len;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * This transfer function is not complete or correct, but it provides
 | 
					 | 
				
			||||||
 * the basic support that the above read and write functions previously
 | 
					 | 
				
			||||||
 * provided directly. It is extremely limited and not useful for
 | 
					 | 
				
			||||||
 * advanced drivers like TPM.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * TODO: Rewite the i2c_transfer and supporting functions
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int platform_i2c_transfer(unsigned bus, struct i2c_seg *segments, int count)
 | 
					int platform_i2c_transfer(unsigned bus, struct i2c_seg *segments, int count)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						int i, ret = CB_SUCCESS;
 | 
				
			||||||
	struct i2c_seg *seg = segments;
 | 
						struct i2c_seg *seg = segments;
 | 
				
			||||||
 | 
						struct a1x_twi *twi = (void *)TWI_BASE(bus);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (wait_until_idle(twi) != CB_SUCCESS)
 | 
				
			||||||
 | 
							return CB_ERR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < count; i++) {
 | 
				
			||||||
 | 
							seg = segments + i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (seg->read) {
 | 
							if (seg->read) {
 | 
				
			||||||
		/* Read has one buf for the addr and one for the data */
 | 
								ret = i2c_read(twi, seg->chip, seg->buf, seg->len);
 | 
				
			||||||
		if (count !=  2)
 | 
								if (ret < 0)
 | 
				
			||||||
			return -1;
 | 
									break;
 | 
				
			||||||
 | 
					 | 
				
			||||||
		if(i2c_read(bus, seg->chip, *seg->buf, seg[1].buf, seg[1].len) < 0)
 | 
					 | 
				
			||||||
			return -1;
 | 
					 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
		/* Write buf has adder and data. */
 | 
								ret = i2c_write(twi, seg->chip, seg->buf, seg->len);
 | 
				
			||||||
		if (count !=  1)
 | 
								if (ret < 0)
 | 
				
			||||||
			return -1;
 | 
									break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if(i2c_write(bus, seg->chip, *seg->buf, seg->buf+1, seg->len-1) < 0)
 | 
						/* Don't worry about the status. STOP is on a best-effort basis */
 | 
				
			||||||
			return -1;
 | 
						i2c_send_stop(twi);
 | 
				
			||||||
	}
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user