dptx: Made the I2C read function more robust.

- Changed the offset from type u8 to u16.
- In order to accomodate offsets greater than 255, a segment pointer is used.
	- The I2C read funciton is now able to access blocks other than the
	block 0 and 1 at a given address. E.g., EDID extension blocks may now be
	accessed by reading from I2C address 0x50 (raw=0xA0/0xA1) and writing
	the appropriate segment pointer and offset.
		- Input offset=0.
			- EDID block 0: I2C read on offset=0 and segptr=0.
		- Input offset=128.
			- EDID block 1: I2C read on offset=128 and segptr=0.
		- Input offset=256.
			- EDID block 2: I2C read on offset=0 and segptr=1.
		- Input offset=384.
			- EDID block 3: I2C read on offset=128 and segptr=1.
		- etc.
	- Writing to the I2C address 0x30 (raw=0x60/0x61) sets the segment
	pointer.
	- Writing to an I2C address sets the offset that will be read from that
	address. E.g., a read of the EDID, starting at offset 128 would be done
	by writing 128 to 0x50, then reading from 0x50.
	- Offsets that cross a 256-byte boundary requiring increment of the
	segment pointer is also handled. E.g. A 16 byte read on input offset 500
	results in the the returned 16 byte array having the first 11 bytes from
	segptr=1 (bytes 244-255) and the last 5 bytes from segptr=2 (bytes 0-4).

Signed-off-by: Andrei-Liviu Simion <andrei.simion@xilinx.com>
This commit is contained in:
Andrei-Liviu Simion 2014-10-29 13:16:26 -07:00 committed by Suneel Garapati
parent b8682ec6fb
commit 327bbeb10b
2 changed files with 79 additions and 18 deletions

View file

@ -812,40 +812,101 @@ u32 XDptx_AuxWrite(XDptx *InstancePtr, u32 DpcdAddress, u32 BytesToWrite,
* @note None.
*
*******************************************************************************/
u32 XDptx_IicRead(XDptx *InstancePtr, u8 IicAddress, u8 Offset, u8 BytesToRead,
void *ReadData)
u32 XDptx_IicRead(XDptx *InstancePtr, u8 IicAddress, u16 Offset,
u16 BytesToRead, void *ReadData)
{
u32 Status;
XDptx_AuxTransaction Request;
u8 AuxData[2];
u8 SegPtr;
u16 NumBytesLeftInSeg;
u16 BytesLeft;
u8 CurrBytesToRead;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertNonvoid(IicAddress <= 0xFF);
Xil_AssertNonvoid(Offset <= 0xFF);
Xil_AssertNonvoid(BytesToRead <= 0xFF);
Xil_AssertNonvoid(Offset <= 0xFFFF);
Xil_AssertNonvoid(BytesToRead <= 0xFFFF);
Xil_AssertNonvoid(ReadData != NULL);
if (!XDptx_IsConnected(InstancePtr)) {
return XST_DEVICE_NOT_FOUND;
}
/* Setup the I2C-over-AUX read transaction with the address. */
Request.Address = IicAddress;
Request.CmdCode = XDPTX_AUX_CMD_I2C_WRITE_MOT;
Request.NumBytes = 2;
AuxData[0] = Offset;
AuxData[1] = 0;
Request.Data = AuxData;
Status = XDptx_AuxRequest(InstancePtr, &Request);
BytesLeft = BytesToRead;
/* Reposition based on a segment length of 256 bytes. */
SegPtr = 0;
if (Offset >= 255) {
SegPtr += Offset / 256;
Offset %= 256;
}
NumBytesLeftInSeg = 256 - Offset;
/* Set the segment pointer to 0. */
Status = XDptx_IicWrite(InstancePtr, 0x30, 1, &SegPtr);
if (Status != XST_SUCCESS) {
/* The I2C write to set the segment pointer failed. */
return Status;
}
/* Send I2C-over-AUX read transaction. */
Status = XDptx_AuxCommon(InstancePtr, XDPTX_AUX_CMD_I2C_READ,
IicAddress, BytesToRead, (u8 *)ReadData);
/* Send I2C read message in 16 byte chunks. */
while (BytesLeft > 0) {
/* Reposition based on segment boundaries. */
if (NumBytesLeftInSeg >= 16) {
CurrBytesToRead = 16;
}
else if (NumBytesLeftInSeg >= BytesLeft) {
CurrBytesToRead = BytesLeft;
}
else {
CurrBytesToRead = NumBytesLeftInSeg;
}
/* Setup the I2C-over-AUX read transaction with the offset. */
Status = XDptx_IicWrite(InstancePtr, IicAddress, 1, &Offset);
if (Status != XST_SUCCESS) {
return Status;
}
/* Send I2C-over-AUX read transaction. */
Status = XDptx_AuxCommon(InstancePtr, XDPTX_AUX_CMD_I2C_READ,
IicAddress, CurrBytesToRead, (u8 *)ReadData);
if (Status != XST_SUCCESS) {
/* The AUX read transaction failed. */
return Status;
}
/* I2C read of 16 bytes. */
if (BytesLeft > CurrBytesToRead) {
BytesLeft -= CurrBytesToRead;
Offset += CurrBytesToRead;
ReadData += CurrBytesToRead;
NumBytesLeftInSeg -= CurrBytesToRead;
}
/* Last I2C read. */
else {
BytesLeft = 0;
}
/* Increment the segment pointer to access more I2C address
* space, if required. */
if ((NumBytesLeftInSeg == 0) && (BytesLeft > 0)) {
SegPtr++;
Offset %= 256;
NumBytesLeftInSeg = 256;
Status = XDptx_IicWrite(InstancePtr, 0x30, 1, &SegPtr);
if (Status != XST_SUCCESS) {
return Status;
}
}
}
/* Reset the segment pointer to 0. */
SegPtr = 0;
Status = XDptx_IicWrite(InstancePtr, 0x30, 1, &SegPtr);
return Status;
}

View file

@ -761,8 +761,8 @@ u32 XDptx_AuxRead(XDptx *InstancePtr, u32 Address, u32 BytesToRead,
void *ReadData);
u32 XDptx_AuxWrite(XDptx *InstancePtr, u32 Address, u32 BytesToWrite,
void *WriteData);
u32 XDptx_IicRead(XDptx *InstancePtr, u8 IicAddress, u8 Offset, u8 BytesToRead,
void *ReadData);
u32 XDptx_IicRead(XDptx *InstancePtr, u8 IicAddress, u16 Offset,
u16 BytesToRead, void *ReadData);
u32 XDptx_IicWrite(XDptx *InstancePtr, u8 IicAddress, u8 BytesToWrite,
void *WriteData);