diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2018-10-20 19:56:31 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2018-10-20 19:56:31 +0200 |
commit | 83e20b4df18d539db59c8e1090f77a6565df250e (patch) | |
tree | d42f2d4c7fdd8cb1526131515690bc9229150505 /sys/src/9/bcm/trap.c | |
parent | 796e5e6000677a39577d545e4603ce251e7cbfe9 (diff) |
bcm: import changes for raspi2/3 from richard miller
Diffstat (limited to 'sys/src/9/bcm/trap.c')
-rw-r--r-- | sys/src/9/bcm/trap.c | 67 |
1 files changed, 54 insertions, 13 deletions
diff --git a/sys/src/9/bcm/trap.c b/sys/src/9/bcm/trap.c index b6bf34389..ae6489cba 100644 --- a/sys/src/9/bcm/trap.c +++ b/sys/src/9/bcm/trap.c @@ -13,6 +13,7 @@ #include "arm.h" #define INTREGS (VIRTIO+0xB200) +#define LOCALREGS (VIRTIO+IOSIZE) typedef struct Intregs Intregs; typedef struct Vctl Vctl; @@ -20,6 +21,10 @@ typedef struct Vctl Vctl; enum { Nvec = 8, /* # of vectors at start of lexception.s */ Fiqenable = 1<<7, + + Localtimerint = 0x40, + Localmboxint = 0x50, + Localintpending = 0x60, }; /* @@ -46,12 +51,14 @@ struct Intregs { struct Vctl { Vctl *next; int irq; + int cpu; u32int *reg; u32int mask; void (*f)(Ureg*, void*); void *a; }; +static Lock vctllock; static Vctl *vctl, *vfiq; static char *trapnames[PsrMask+1] = { @@ -75,14 +82,16 @@ trapinit(void) { Vpage0 *vpage0; - /* disable everything */ - intrsoff(); - - /* set up the exception vectors */ - vpage0 = (Vpage0*)HVECTORS; - memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors)); - memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable)); - cacheuwbinv(); + if (m->machno == 0) { + /* disable everything */ + intrsoff(); + /* set up the exception vectors */ + vpage0 = (Vpage0*)HVECTORS; + memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors)); + memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable)); + cacheuwbinv(); + l2cacheuwbinv(); + } /* set up the stacks for the interrupt modes */ setr13(PsrMfiq, (u32int*)(FIQSTKTOP)); @@ -95,6 +104,21 @@ trapinit(void) } void +intrcpushutdown(void) +{ + u32int *enable; + + if(soc.armlocal == 0) + return; + enable = (u32int*)(LOCALREGS + Localtimerint) + m->machno; + *enable = 0; + if(m->machno){ + enable = (u32int*)(LOCALREGS + Localmboxint) + m->machno; + *enable = 1; + } +} + +void intrsoff(void) { Intregs *ip; @@ -120,11 +144,11 @@ irq(Ureg* ureg) clockintr = 0; for(v = vctl; v; v = v->next) - if(*v->reg & v->mask){ + if(v->cpu == m->machno && (*v->reg & v->mask) != 0){ coherence(); v->f(ureg, v->a); coherence(); - if(v->irq == IRQclock) + if(v->irq == IRQclock || v->irq == IRQcntps || v->irq == IRQcntpns) clockintr = 1; } return clockintr; @@ -140,7 +164,7 @@ fiq(Ureg *ureg) v = vfiq; if(v == nil) - panic("unexpected item in bagging area"); + panic("cpu%d: unexpected item in bagging area", m->machno); m->intr++; ureg->pc -= 4; coherence(); @@ -160,7 +184,16 @@ irqenable(int irq, void (*f)(Ureg*, void*), void* a) if(v == nil) panic("irqenable: no mem"); v->irq = irq; - if(irq >= IRQbasic){ + v->cpu = 0; + if(irq >= IRQlocal){ + v->reg = (u32int*)(LOCALREGS + Localintpending) + m->machno; + if(irq >= IRQmbox0) + enable = (u32int*)(LOCALREGS + Localmboxint) + m->machno; + else + enable = (u32int*)(LOCALREGS + Localtimerint) + m->machno; + v->mask = 1 << (irq - IRQlocal); + v->cpu = m->machno; + }else if(irq >= IRQbasic){ enable = &ip->ARMenable; v->reg = &ip->ARMpending; v->mask = 1 << (irq - IRQbasic); @@ -171,6 +204,7 @@ irqenable(int irq, void (*f)(Ureg*, void*), void* a) } v->f = f; v->a = a; + lock(&vctllock); if(irq == IRQfiq){ assert((ip->FIQctl & Fiqenable) == 0); assert((*enable & v->mask) == 0); @@ -179,8 +213,15 @@ irqenable(int irq, void (*f)(Ureg*, void*), void* a) }else{ v->next = vctl; vctl = v; - *enable = v->mask; + if(irq >= IRQmbox0){ + if(irq <= IRQmbox3) + *enable |= 1 << (irq - IRQmbox0); + }else if(irq >= IRQlocal) + *enable |= 1 << (irq - IRQlocal); + else + *enable = v->mask; } + unlock(&vctllock); } static char * |