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:
parent
b8682ec6fb
commit
327bbeb10b
2 changed files with 79 additions and 18 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue