summaryrefslogtreecommitdiff
path: root/sys/src/9/bcm/trap.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2018-10-20 19:56:31 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2018-10-20 19:56:31 +0200
commit83e20b4df18d539db59c8e1090f77a6565df250e (patch)
treed42f2d4c7fdd8cb1526131515690bc9229150505 /sys/src/9/bcm/trap.c
parent796e5e6000677a39577d545e4603ce251e7cbfe9 (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.c67
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 *