kolibrios-fun/contrib/other/uarm/pxa255_GPIO.c

207 lines
4.1 KiB
C
Raw Normal View History

#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;
}