mirror of
https://github.com/libretro/Mu.git
synced 2026-09-23 23:25:04 +00:00
Lots of I2C bugs
Still need to fix more
This commit is contained in:
@@ -23,7 +23,6 @@ uint8_t pxa260I2cBuffer;
|
||||
uint16_t pxa260I2cIcr;
|
||||
uint16_t pxa260I2cIsr;
|
||||
uint8_t pxa260I2cIsar;
|
||||
bool pxa260I2cUnitBusy;
|
||||
|
||||
|
||||
static void pxa260I2cUpdateInterrupt(void){
|
||||
@@ -39,7 +38,6 @@ void pxa260I2cReset(void){
|
||||
pxa260I2cIcr = 0x0000;
|
||||
pxa260I2cIsr = 0x0000;
|
||||
pxa260I2cIsar = 0x00;
|
||||
pxa260I2cUnitBusy = false;
|
||||
}
|
||||
|
||||
uint32_t pxa260I2cReadWord(uint32_t address){
|
||||
@@ -47,16 +45,20 @@ uint32_t pxa260I2cReadWord(uint32_t address){
|
||||
|
||||
switch(address){
|
||||
case IBMR:
|
||||
debugLog("PXA260 direct I2C bus read\n");
|
||||
return pxa260I2cBus & 0x03;
|
||||
|
||||
case IDBR:
|
||||
//debugLog("PXA260 I2C IDBR read, PC:0x%08X\n", pxa260GetPc());
|
||||
return pxa260I2cBuffer;
|
||||
|
||||
case ICR:
|
||||
//debugLog("PXA260 I2C ICR read, PC:0x%08X\n", pxa260GetPc());
|
||||
return pxa260I2cIcr;
|
||||
|
||||
case ISR:
|
||||
debugLog("I2C ISR is currently unimplemented\n");
|
||||
//TODO: not fully implemeted but the rest seems to be slave mode
|
||||
//debugLog("PXA260 I2C ISR read, PC:0x%08X\n", pxa260GetPc());
|
||||
return pxa260I2cIsr;
|
||||
|
||||
case ISAR:
|
||||
@@ -73,63 +75,62 @@ void pxa260I2cWriteWord(uint32_t address, uint32_t value){
|
||||
|
||||
switch(address){
|
||||
case IDBR:
|
||||
debugLog("PXA260 I2C IDBR write:0x%02X, PC:0x%08X\n", value & 0xFF, pxa260GetPc());
|
||||
pxa260I2cBuffer = value & 0xFF;
|
||||
return;
|
||||
|
||||
case ICR:
|
||||
//TODO: this is incomplete
|
||||
//debugLog("PXA260 ICR write 0x%04X, PC:0x%08X\n", value & 0xFFFF, pxa260GetPc());
|
||||
|
||||
pxa260I2cIcr = value & 0xFFFF;
|
||||
if(!(pxa260I2cIcr & 0x0008) && value & 0x0040){
|
||||
//I2C unit enabled and not transfering right now, its ok to start a transfer
|
||||
if(value & 0x0001){
|
||||
tps65010I2cExchange(I2C_START);
|
||||
|
||||
if(value & 0x0001)
|
||||
tps65010I2cExchange(I2C_START);
|
||||
if(value & 0x0008){
|
||||
if(pxa260I2cIsr & 0x0001){
|
||||
//receive
|
||||
uint8_t index;
|
||||
//add unit busy bit
|
||||
pxa260I2cIsr |= 0x0004;
|
||||
}
|
||||
if(value & 0x0008){
|
||||
if(pxa260I2cIsr & 0x0001){
|
||||
//receive
|
||||
uint8_t index;
|
||||
|
||||
debugLog("I2C transfer(receive) attempted\n");
|
||||
debugLog("I2C transfer(receive) attempted\n");
|
||||
|
||||
for(index = 0; index < 8; index++){
|
||||
pxa260I2cBuffer <<= 1;
|
||||
pxa260I2cBuffer |= !!(tps65010I2cExchange(I2C_FLOATING_BUS) & I2C_1);
|
||||
for(index = 0; index < 8; index++){
|
||||
pxa260I2cBuffer <<= 1;
|
||||
pxa260I2cBuffer |= !!(tps65010I2cExchange(I2C_FLOATING_BUS) & I2C_1);
|
||||
}
|
||||
|
||||
pxa260TimingTriggerEvent(PXA260_TIMING_CALLBACK_I2C_RECEIVE_FULL, PXA260_I2C_TRANSFER_DURATION);
|
||||
}
|
||||
else{
|
||||
//send
|
||||
uint8_t index;
|
||||
|
||||
pxa260I2cUnitBusy = true;
|
||||
pxa260TimingTriggerEvent(PXA260_TIMING_CALLBACK_I2C_RECEIVE_FULL, PXA260_I2C_TRANSFER_DURATION);
|
||||
}
|
||||
else{
|
||||
//send
|
||||
uint8_t index;
|
||||
|
||||
debugLog("I2C transfer(send) attempted\n");
|
||||
|
||||
for(index = 0; index < 8; index++)
|
||||
tps65010I2cExchange((pxa260I2cBuffer & 1 << 7 - index) ? I2C_1 : I2C_0);
|
||||
|
||||
pxa260I2cUnitBusy = true;
|
||||
pxa260TimingTriggerEvent(PXA260_TIMING_CALLBACK_I2C_TRANSMIT_EMPTY, PXA260_I2C_TRANSFER_DURATION);
|
||||
debugLog("I2C transfer(send) attempted: 0x%02X\n", pxa260I2cBuffer);
|
||||
|
||||
for(index = 0; index < 8; index++)
|
||||
tps65010I2cExchange((pxa260I2cBuffer & 1 << 7 - index) ? I2C_1 : I2C_0);
|
||||
|
||||
pxa260TimingTriggerEvent(PXA260_TIMING_CALLBACK_I2C_TRANSMIT_EMPTY, PXA260_I2C_TRANSFER_DURATION);
|
||||
}
|
||||
}
|
||||
if(value & 0x0002)
|
||||
tps65010I2cExchange(I2C_STOP);
|
||||
}
|
||||
if(value & 0x0002){
|
||||
tps65010I2cExchange(I2C_STOP);
|
||||
|
||||
//clear read/write bit
|
||||
pxa260I2cIsr &= 0xFFFE;
|
||||
}
|
||||
//cant clear current transfer flag
|
||||
pxa260I2cIcr = value & 0xFFFF | pxa260I2cIcr & 0x0008;
|
||||
|
||||
return;
|
||||
|
||||
case ISR:{
|
||||
//clear IDBR RECEIVE FULL
|
||||
if(value & 0x0080)
|
||||
pxa260I2cIsr &= 0xFF7F;
|
||||
//debugLog("PXA260 I2C write to ISR:0x%04X\n", value & 0xFFFF);
|
||||
|
||||
//clear IDBR TRANSMIT EMPTY
|
||||
if(value & 0x0040)
|
||||
pxa260I2cIsr &= 0xFFBF;
|
||||
|
||||
//unit busy
|
||||
pxa260I2cIsr |= pxa260I2cUnitBusy << 2;
|
||||
//clear all clear on write 1 bits
|
||||
pxa260I2cIsr = pxa260I2cIsr & ~(value & 0x07F0);
|
||||
|
||||
//read write setting
|
||||
pxa260I2cIsr = pxa260I2cIsr & 0xFFFE | value & 0x0001;
|
||||
@@ -149,17 +150,31 @@ void pxa260I2cWriteWord(uint32_t address, uint32_t value){
|
||||
}
|
||||
|
||||
void pxa260I2cTransmitEmpty(void){
|
||||
//clear transfer byte
|
||||
pxa260I2cIcr &= 0xFFF7;
|
||||
|
||||
//set transmit empty
|
||||
pxa260I2cIsr |= 0x0040;
|
||||
pxa260I2cUnitBusy = false;
|
||||
|
||||
//clear read write and unit busy bits if stop was sent
|
||||
if(pxa260I2cIcr & 0x0002)
|
||||
pxa260I2cIsr &= 0xFFFA;
|
||||
|
||||
pxa260I2cUpdateInterrupt();
|
||||
debugLog("I2C transmit empty triggered\n");
|
||||
}
|
||||
|
||||
void pxa260I2cReceiveFull(void){
|
||||
//clear transfer byte
|
||||
pxa260I2cIcr &= 0xFFF7;
|
||||
|
||||
//set receive full
|
||||
pxa260I2cIsr |= 0x0080;
|
||||
pxa260I2cUnitBusy = false;
|
||||
|
||||
//clear read write and unit busy bits if stop was sent
|
||||
if(pxa260I2cIcr & 0x0002)
|
||||
pxa260I2cIsr &= 0xFFFA;
|
||||
|
||||
pxa260I2cUpdateInterrupt();
|
||||
debugLog("I2C receive full triggered\n");
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ extern uint8_t pxa260I2cBuffer;
|
||||
extern uint16_t pxa260I2cIcr;
|
||||
extern uint16_t pxa260I2cIsr;
|
||||
extern uint8_t pxa260I2cIsar;
|
||||
extern bool pxa260I2cUnitBusy;
|
||||
|
||||
void pxa260I2cReset(void);
|
||||
|
||||
|
||||
@@ -10,6 +10,13 @@ static void pxa260gpioOnOutputPinUpdated(Pxa260gpio* gpio, UInt8 gpioNum){
|
||||
//debugLog("PXA260 GPIO %d set:%d\n", gpioNum, pxa260gpioGetState(gpio, gpioNum));
|
||||
|
||||
switch(gpioNum){
|
||||
/*
|
||||
case 19:
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
*/
|
||||
|
||||
case 24:
|
||||
//TSC2101 chip select
|
||||
tsc2101SetChipSelect(!!pxa260gpioGetState(gpio, gpioNum));
|
||||
@@ -106,6 +113,7 @@ Boolean pxa260gpioPrvMemAccessF(void* userData, UInt32 pa, UInt8 size, Boolean w
|
||||
case 8:
|
||||
pa -= 6;
|
||||
gpio->latches[pa] |= val;
|
||||
debugLog("PXA260 GPIO register read:%d\n", pa);
|
||||
goto recalc;
|
||||
|
||||
case 9:
|
||||
|
||||
@@ -79,7 +79,6 @@ uint8_t tps65010I2cExchange(uint8_t i2cBus){
|
||||
|
||||
if(i2cBus == I2C_START){
|
||||
tps65010State = I2C_WAIT_FOR_ADDR;
|
||||
tps65010SelectedRegisterAlreadySet = false;
|
||||
return I2C_FLOATING_BUS;
|
||||
}
|
||||
else if(i2cBus == I2C_STOP){
|
||||
@@ -89,6 +88,7 @@ uint8_t tps65010I2cExchange(uint8_t i2cBus){
|
||||
return I2C_FLOATING_BUS;
|
||||
}
|
||||
|
||||
tps65010CurrentI2cByte <<= 1;
|
||||
tps65010CurrentI2cByte |= (i2cBus == I2C_1);
|
||||
if(tps65010State == I2C_SENDING){
|
||||
if(tps65010SelectedRegister < 0x11)
|
||||
@@ -100,23 +100,35 @@ uint8_t tps65010I2cExchange(uint8_t i2cBus){
|
||||
|
||||
if(tps65010CurrentI2cByteBitsRemaining == 0){
|
||||
//process data from byte
|
||||
if(tps65010State == I2C_WAIT_FOR_ADDR){
|
||||
if((tps65010CurrentI2cByte & 0xFE) == 0x90){
|
||||
//the address is of this device
|
||||
tps65010State = (tps65010CurrentI2cByte & 0x01) ? I2C_SENDING : I2C_RECEIVING;
|
||||
}
|
||||
else{
|
||||
tps65010State = I2C_NOT_SELECTED;
|
||||
}
|
||||
}
|
||||
else if(tps65010State == I2C_RECEIVING){
|
||||
if(tps65010SelectedRegisterAlreadySet){
|
||||
tps65010WriteRegister(tps65010SelectedRegister, tps65010CurrentI2cByte);
|
||||
}
|
||||
else{
|
||||
tps65010SelectedRegister = tps65010CurrentI2cByte;
|
||||
tps65010SelectedRegisterAlreadySet = true;
|
||||
}
|
||||
switch(tps65010State){
|
||||
case I2C_WAIT_FOR_ADDR:
|
||||
if((tps65010CurrentI2cByte & 0xFE) == 0x90){
|
||||
//the address is of this device
|
||||
tps65010State = (tps65010CurrentI2cByte & 0x01) ? I2C_SENDING : I2C_RECEIVING;
|
||||
}
|
||||
else{
|
||||
tps65010State = I2C_NOT_SELECTED;
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_RECEIVING:
|
||||
if(tps65010SelectedRegisterAlreadySet){
|
||||
tps65010WriteRegister(tps65010SelectedRegister, tps65010CurrentI2cByte);
|
||||
tps65010SelectedRegisterAlreadySet = false;
|
||||
}
|
||||
else{
|
||||
tps65010SelectedRegister = tps65010CurrentI2cByte;
|
||||
tps65010SelectedRegisterAlreadySet = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_SENDING:
|
||||
tps65010SelectedRegisterAlreadySet = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
debugLog("TPS65010 dont know what to do with byte, cmd:%d\n", tps65010State);
|
||||
break;
|
||||
}
|
||||
|
||||
tps65010CurrentI2cByteBitsRemaining = 8;
|
||||
|
||||
Reference in New Issue
Block a user