207 lines
4.1 KiB
C
207 lines
4.1 KiB
C
|
#include "pxa255_GPIO.h"
|
||
|
#include "mem.h"
|
||
|
|
||
|
|
||
|
static void pxa255gpioPrvRecalcValues(Pxa255gpio* gpio, UInt32 which){
|
||
|
|
||
|
UInt8 i;
|
||
|
UInt32 val, bit;
|
||
|
|
||
|
val = gpio->dirs[which];
|
||
|
gpio->levels[which] = (gpio->latches[which] & val) | (gpio->inputs[which] & (~val));
|
||
|
|
||
|
val = 3;
|
||
|
bit = 1;
|
||
|
for(i = 0 ; i < 16; i++, val <<= 2, bit <<= 1) if(gpio->AFRs[(which << 1) + 0] & val) gpio->levels[which] &=~ bit; //all AFRs read as zero to CPU
|
||
|
for(i = 16; i < 32; i++, val <<= 2, bit <<= 1) if(gpio->AFRs[(which << 1) + 1] & val) gpio->levels[which] &=~ bit; //all AFRs read as zero to CPU
|
||
|
}
|
||
|
|
||
|
static void pxa255gpioPrvRecalcIntrs(Pxa255gpio* gpio){
|
||
|
|
||
|
pxa255icInt(gpio->ic, PXA255_I_GPIO_all, gpio->levels[1] || gpio->levels[2] || (gpio->levels[0] &~ 3));
|
||
|
pxa255icInt(gpio->ic, PXA255_I_GPIO_1, (gpio->levels[0] & 2) != 0);
|
||
|
pxa255icInt(gpio->ic, PXA255_I_GPIO_0, (gpio->levels[0] & 1) != 0);
|
||
|
}
|
||
|
|
||
|
static Boolean pxa255gpioPrvMemAccessF(void* userData, UInt32 pa, UInt8 size, Boolean write, void* buf){
|
||
|
|
||
|
Pxa255gpio* gpio = userData;
|
||
|
UInt32 val = 0;
|
||
|
|
||
|
if(size != 4) {
|
||
|
err_str(__FILE__ ": Unexpected ");
|
||
|
// err_str(write ? "write" : "read");
|
||
|
// err_str(" of ");
|
||
|
// err_dec(size);
|
||
|
// err_str(" bytes to 0x");
|
||
|
// err_hex(pa);
|
||
|
// err_str("\r\n");
|
||
|
return true; //we do not support non-word accesses
|
||
|
}
|
||
|
|
||
|
pa = (pa - PXA255_GPIO_BASE) >> 2;
|
||
|
|
||
|
if(write){
|
||
|
val = *(UInt32*)buf;
|
||
|
|
||
|
switch(pa){
|
||
|
case 0:
|
||
|
case 1:
|
||
|
case 2:
|
||
|
|
||
|
break;
|
||
|
|
||
|
case 3:
|
||
|
case 4:
|
||
|
case 5:
|
||
|
pa -= 3;
|
||
|
gpio->dirs[pa] = val;
|
||
|
goto recalc;
|
||
|
|
||
|
case 6:
|
||
|
case 7:
|
||
|
case 8:
|
||
|
pa -= 6;
|
||
|
gpio->levels[pa] |= val;
|
||
|
goto recalc;
|
||
|
|
||
|
case 9:
|
||
|
case 10:
|
||
|
case 11:
|
||
|
pa -= 9;
|
||
|
gpio->levels[pa] &=~ val;
|
||
|
goto recalc;
|
||
|
|
||
|
case 12:
|
||
|
case 13:
|
||
|
case 14:
|
||
|
gpio->riseDet[pa - 12] = val;
|
||
|
break;
|
||
|
|
||
|
case 15:
|
||
|
case 16:
|
||
|
case 17:
|
||
|
gpio->fallDet[pa - 15] = val;
|
||
|
break;
|
||
|
|
||
|
case 18:
|
||
|
case 19:
|
||
|
case 20:
|
||
|
gpio->detStatus[pa - 18] &=~ val;
|
||
|
goto trigger_intrs;
|
||
|
|
||
|
case 21:
|
||
|
case 22:
|
||
|
case 23:
|
||
|
case 24:
|
||
|
case 25:
|
||
|
case 26:
|
||
|
val = gpio->AFRs[pa - 21];
|
||
|
goto recalc;
|
||
|
}
|
||
|
|
||
|
goto done;
|
||
|
|
||
|
recalc:
|
||
|
pxa255gpioPrvRecalcValues(gpio, pa);
|
||
|
|
||
|
trigger_intrs:
|
||
|
pxa255gpioPrvRecalcIntrs(gpio);
|
||
|
}
|
||
|
else{
|
||
|
switch(pa){
|
||
|
case 0:
|
||
|
case 1:
|
||
|
case 2:
|
||
|
val = gpio->levels[pa - 0];
|
||
|
break;
|
||
|
|
||
|
case 3:
|
||
|
case 4:
|
||
|
case 5:
|
||
|
val = gpio->dirs[pa - 3];
|
||
|
break;
|
||
|
|
||
|
case 6:
|
||
|
case 7:
|
||
|
case 8:
|
||
|
case 9:
|
||
|
case 10:
|
||
|
case 11:
|
||
|
val = 0;
|
||
|
break;
|
||
|
|
||
|
case 12:
|
||
|
case 13:
|
||
|
case 14:
|
||
|
val = gpio->riseDet[pa - 12];
|
||
|
break;
|
||
|
|
||
|
case 15:
|
||
|
case 16:
|
||
|
case 17:
|
||
|
val = gpio->fallDet[pa - 15];
|
||
|
break;
|
||
|
|
||
|
case 18:
|
||
|
case 19:
|
||
|
case 20:
|
||
|
val = gpio->detStatus[pa - 18];
|
||
|
break;
|
||
|
|
||
|
case 21:
|
||
|
case 22:
|
||
|
case 23:
|
||
|
case 24:
|
||
|
case 25:
|
||
|
case 26:
|
||
|
val = gpio->AFRs[pa - 21];
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
*(UInt32*)buf = val;
|
||
|
}
|
||
|
|
||
|
done:
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
Boolean pxa255gpioInit(Pxa255gpio* gpio, ArmMem* physMem, Pxa255ic* ic){
|
||
|
|
||
|
__mem_zero(gpio, sizeof(Pxa255gpio));
|
||
|
gpio->ic = ic;
|
||
|
|
||
|
return memRegionAdd(physMem, PXA255_GPIO_BASE, PXA255_GPIO_SIZE, pxa255gpioPrvMemAccessF, gpio);
|
||
|
}
|
||
|
|
||
|
void pxa255gpioSetState(Pxa255gpio* gpio, UInt8 gpioNum, Boolean on){
|
||
|
|
||
|
UInt32 set = gpioNum >> 5;
|
||
|
UInt32 v = 1UL << (gpioNum & 0x1F);
|
||
|
UInt32* p;
|
||
|
|
||
|
if(gpioNum >= 85) return;
|
||
|
|
||
|
p = gpio->inputs + set;
|
||
|
if(on) *p |= v;
|
||
|
else *p &=~ v;
|
||
|
|
||
|
pxa255gpioPrvRecalcValues(gpio, set);
|
||
|
pxa255gpioPrvRecalcIntrs(gpio);
|
||
|
}
|
||
|
|
||
|
UInt8 pxa255gpioGetState(Pxa255gpio* gpio, UInt8 gpioNum){
|
||
|
|
||
|
UInt32 sSet = gpioNum >> 5;
|
||
|
UInt32 bSet = gpioNum >> 4;
|
||
|
UInt32 sV = 1UL << (gpioNum & 0x1F);
|
||
|
UInt32 bV = 3UL << (gpioNum & 0x0F);
|
||
|
|
||
|
|
||
|
if(gpioNum >= 85) return PXA255_GPIO_NOT_PRESENT;
|
||
|
if(gpio->AFRs[bSet] & bV) return ((gpio->AFRs[bSet] & bV) >> (gpioNum & 0x0F)) + PXA255_GPIO_AFR1;
|
||
|
if(gpio->dirs[sSet] & sV) return (gpio->latches[sSet] & sV) ? PXA255_GPIO_HIGH : PXA255_GPIO_LOW;
|
||
|
return PXA255_GPIO_HiZ;
|
||
|
}
|