changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > plan9front / changeset: bcm: move interrupt handling out of trap.c into irq.c

changeset 7150: 94aebeed6c4a
parent 7147: a2a8cdde9873
child 7151: 50ff71b7598a
author: cinap_lenrek@felloff.net
date: Wed, 10 Apr 2019 15:04:59 +0200
files: sys/src/9/bcm/irq.c sys/src/9/bcm/trap.c
description: bcm: move interrupt handling out of trap.c into irq.c
     1.1new file mode 100644
     1.2--- /dev/null
     1.3+++ b/sys/src/9/bcm/irq.c
     1.4@@ -0,0 +1,166 @@
     1.5+#include "u.h"
     1.6+#include "../port/lib.h"
     1.7+#include "mem.h"
     1.8+#include "dat.h"
     1.9+#include "fns.h"
    1.10+#include "io.h"
    1.11+#include "ureg.h"
    1.12+#include "../port/error.h"
    1.13+
    1.14+#define INTREGS		(VIRTIO+0xB200)
    1.15+
    1.16+enum {
    1.17+	Fiqenable = 1<<7,
    1.18+
    1.19+	Localtimerint	= 0x40,
    1.20+	Localmboxint	= 0x50,
    1.21+	Localintpending	= 0x60,
    1.22+};
    1.23+
    1.24+/*
    1.25+ * interrupt control registers
    1.26+ */
    1.27+typedef struct Intregs Intregs;
    1.28+struct Intregs {
    1.29+	u32int	ARMpending;
    1.30+	u32int	GPUpending[2];
    1.31+	u32int	FIQctl;
    1.32+	u32int	GPUenable[2];
    1.33+	u32int	ARMenable;
    1.34+	u32int	GPUdisable[2];
    1.35+	u32int	ARMdisable;
    1.36+};
    1.37+
    1.38+typedef struct Vctl Vctl;
    1.39+struct Vctl {
    1.40+	Vctl	*next;
    1.41+	int	irq;
    1.42+	u32int	*reg;
    1.43+	u32int	mask;
    1.44+	void	(*f)(Ureg*, void*);
    1.45+	void	*a;
    1.46+};
    1.47+
    1.48+static Lock vctllock;
    1.49+static Vctl *vctl[MAXMACH], *vfiq;
    1.50+
    1.51+void
    1.52+intrcpushutdown(void)
    1.53+{
    1.54+	u32int *enable;
    1.55+
    1.56+	if(soc.armlocal == 0)
    1.57+		return;
    1.58+	enable = (u32int*)(ARMLOCAL + Localtimerint) + m->machno;
    1.59+	*enable = 0;
    1.60+	if(m->machno){
    1.61+		enable = (u32int*)(ARMLOCAL + Localmboxint) + m->machno;
    1.62+		*enable = 1;
    1.63+	}
    1.64+}
    1.65+
    1.66+void
    1.67+intrsoff(void)
    1.68+{
    1.69+	Intregs *ip;
    1.70+	int disable;
    1.71+
    1.72+	ip = (Intregs*)INTREGS;
    1.73+	disable = ~0;
    1.74+	ip->GPUdisable[0] = disable;
    1.75+	ip->GPUdisable[1] = disable;
    1.76+	ip->ARMdisable = disable;
    1.77+	ip->FIQctl = 0;
    1.78+}
    1.79+
    1.80+/*
    1.81+ *  called by trap to handle irq interrupts.
    1.82+ *  returns true iff a clock interrupt, thus maybe reschedule.
    1.83+ */
    1.84+int
    1.85+irq(Ureg* ureg)
    1.86+{
    1.87+	Vctl *v;
    1.88+	int clockintr;
    1.89+
    1.90+	clockintr = 0;
    1.91+	for(v = vctl[m->machno]; v != nil; v = v->next)
    1.92+		if((*v->reg & v->mask) != 0){
    1.93+			coherence();
    1.94+			v->f(ureg, v->a);
    1.95+			coherence();
    1.96+			if(v->irq == IRQclock || v->irq == IRQcntps || v->irq == IRQcntpns)
    1.97+				clockintr = 1;
    1.98+		}
    1.99+	return clockintr;
   1.100+}
   1.101+
   1.102+/*
   1.103+ * called direct from lexception.s to handle fiq interrupt.
   1.104+ */
   1.105+void
   1.106+fiq(Ureg *ureg)
   1.107+{
   1.108+	Vctl *v;
   1.109+
   1.110+	v = vfiq;
   1.111+	if(v == nil)
   1.112+		panic("cpu%d: unexpected item in bagging area", m->machno);
   1.113+	m->intr++;
   1.114+	ureg->pc -= 4;
   1.115+	coherence();
   1.116+	v->f(ureg, v->a);
   1.117+	coherence();
   1.118+}
   1.119+
   1.120+void
   1.121+irqenable(int irq, void (*f)(Ureg*, void*), void* a)
   1.122+{
   1.123+	Vctl *v;
   1.124+	Intregs *ip;
   1.125+	u32int *enable;
   1.126+	int cpu;
   1.127+
   1.128+	ip = (Intregs*)INTREGS;
   1.129+	if((v = xalloc(sizeof(Vctl))) == nil)
   1.130+		panic("irqenable: no mem");
   1.131+	cpu = 0;
   1.132+	v->irq = irq;
   1.133+	if(irq >= IRQlocal){
   1.134+		cpu = m->machno;
   1.135+		v->reg = (u32int*)(ARMLOCAL + Localintpending) + cpu;
   1.136+		if(irq >= IRQmbox0)
   1.137+			enable = (u32int*)(ARMLOCAL + Localmboxint) + cpu;
   1.138+		else
   1.139+			enable = (u32int*)(ARMLOCAL + Localtimerint) + cpu;
   1.140+		v->mask = 1 << (irq - IRQlocal);
   1.141+	}else if(irq >= IRQbasic){
   1.142+		enable = &ip->ARMenable;
   1.143+		v->reg = &ip->ARMpending;
   1.144+		v->mask = 1 << (irq - IRQbasic);
   1.145+	}else{
   1.146+		enable = &ip->GPUenable[irq/32];
   1.147+		v->reg = &ip->GPUpending[irq/32];
   1.148+		v->mask = 1 << (irq % 32);
   1.149+	}
   1.150+	v->f = f;
   1.151+	v->a = a;
   1.152+	lock(&vctllock);
   1.153+	if(irq == IRQfiq){
   1.154+		assert((ip->FIQctl & Fiqenable) == 0);
   1.155+		assert((*enable & v->mask) == 0);
   1.156+		vfiq = v;
   1.157+		ip->FIQctl = Fiqenable | irq;
   1.158+	}else{
   1.159+		v->next = vctl[cpu];
   1.160+		vctl[cpu] = v;
   1.161+		if(irq >= IRQmbox0){
   1.162+			if(irq <= IRQmbox3)
   1.163+				*enable |= 1 << (irq - IRQmbox0);
   1.164+		}else if(irq >= IRQlocal)
   1.165+			*enable |= 1 << (irq - IRQlocal);
   1.166+		else
   1.167+			*enable = v->mask;
   1.168+	}
   1.169+	unlock(&vctllock);
   1.170+}
     2.1--- a/sys/src/9/bcm/trap.c
     2.2+++ b/sys/src/9/bcm/trap.c
     2.3@@ -12,18 +12,8 @@
     2.4 
     2.5 #include "arm.h"
     2.6 
     2.7-#define INTREGS		(VIRTIO+0xB200)
     2.8-
     2.9-typedef struct Intregs Intregs;
    2.10-typedef struct Vctl Vctl;
    2.11-
    2.12 enum {
    2.13 	Nvec = 8,		/* # of vectors at start of lexception.s */
    2.14-	Fiqenable = 1<<7,
    2.15-
    2.16-	Localtimerint	= 0x40,
    2.17-	Localmboxint	= 0x50,
    2.18-	Localintpending	= 0x60,
    2.19 };
    2.20 
    2.21 /*
    2.22@@ -34,31 +24,6 @@ typedef struct Vpage0 {
    2.23 	u32int	vtable[Nvec];
    2.24 } Vpage0;
    2.25 
    2.26-/*
    2.27- * interrupt control registers
    2.28- */
    2.29-struct Intregs {
    2.30-	u32int	ARMpending;
    2.31-	u32int	GPUpending[2];
    2.32-	u32int	FIQctl;
    2.33-	u32int	GPUenable[2];
    2.34-	u32int	ARMenable;
    2.35-	u32int	GPUdisable[2];
    2.36-	u32int	ARMdisable;
    2.37-};
    2.38-
    2.39-struct Vctl {
    2.40-	Vctl	*next;
    2.41-	int	irq;
    2.42-	u32int	*reg;
    2.43-	u32int	mask;
    2.44-	void	(*f)(Ureg*, void*);
    2.45-	void	*a;
    2.46-};
    2.47-
    2.48-static Lock vctllock;
    2.49-static Vctl *vctl[MAXMACH], *vfiq;
    2.50-
    2.51 static char *trapnames[PsrMask+1] = {
    2.52 	[ PsrMusr ] "user mode",
    2.53 	[ PsrMfiq ] "fiq interrupt",
    2.54@@ -70,6 +35,7 @@ static char *trapnames[PsrMask+1] = {
    2.55 	[ PsrMsys ] "sys trap",
    2.56 };
    2.57 
    2.58+extern int irq(Ureg*);
    2.59 extern int notify(Ureg*);
    2.60 
    2.61 /*
    2.62@@ -102,127 +68,6 @@ trapinit(void)
    2.63 	coherence();
    2.64 }
    2.65 
    2.66-void
    2.67-intrcpushutdown(void)
    2.68-{
    2.69-	u32int *enable;
    2.70-
    2.71-	if(soc.armlocal == 0)
    2.72-		return;
    2.73-	enable = (u32int*)(ARMLOCAL + Localtimerint) + m->machno;
    2.74-	*enable = 0;
    2.75-	if(m->machno){
    2.76-		enable = (u32int*)(ARMLOCAL + Localmboxint) + m->machno;
    2.77-		*enable = 1;
    2.78-	}
    2.79-}
    2.80-
    2.81-void
    2.82-intrsoff(void)
    2.83-{
    2.84-	Intregs *ip;
    2.85-	int disable;
    2.86-
    2.87-	ip = (Intregs*)INTREGS;
    2.88-	disable = ~0;
    2.89-	ip->GPUdisable[0] = disable;
    2.90-	ip->GPUdisable[1] = disable;
    2.91-	ip->ARMdisable = disable;
    2.92-	ip->FIQctl = 0;
    2.93-}
    2.94-
    2.95-/*
    2.96- *  called by trap to handle irq interrupts.
    2.97- *  returns true iff a clock interrupt, thus maybe reschedule.
    2.98- */
    2.99-static int
   2.100-irq(Ureg* ureg)
   2.101-{
   2.102-	Vctl *v;
   2.103-	int clockintr;
   2.104-
   2.105-	clockintr = 0;
   2.106-	for(v = vctl[m->machno]; v != nil; v = v->next)
   2.107-		if((*v->reg & v->mask) != 0){
   2.108-			coherence();
   2.109-			v->f(ureg, v->a);
   2.110-			coherence();
   2.111-			if(v->irq == IRQclock || v->irq == IRQcntps || v->irq == IRQcntpns)
   2.112-				clockintr = 1;
   2.113-		}
   2.114-	return clockintr;
   2.115-}
   2.116-
   2.117-/*
   2.118- * called direct from lexception.s to handle fiq interrupt.
   2.119- */
   2.120-void
   2.121-fiq(Ureg *ureg)
   2.122-{
   2.123-	Vctl *v;
   2.124-
   2.125-	v = vfiq;
   2.126-	if(v == nil)
   2.127-		panic("cpu%d: unexpected item in bagging area", m->machno);
   2.128-	m->intr++;
   2.129-	ureg->pc -= 4;
   2.130-	coherence();
   2.131-	v->f(ureg, v->a);
   2.132-	coherence();
   2.133-}
   2.134-
   2.135-void
   2.136-irqenable(int irq, void (*f)(Ureg*, void*), void* a)
   2.137-{
   2.138-	Vctl *v;
   2.139-	Intregs *ip;
   2.140-	u32int *enable;
   2.141-	int cpu;
   2.142-
   2.143-	ip = (Intregs*)INTREGS;
   2.144-	if((v = xalloc(sizeof(Vctl))) == nil)
   2.145-		panic("irqenable: no mem");
   2.146-	cpu = 0;
   2.147-	v->irq = irq;
   2.148-	if(irq >= IRQlocal){
   2.149-		cpu = m->machno;
   2.150-		v->reg = (u32int*)(ARMLOCAL + Localintpending) + cpu;
   2.151-		if(irq >= IRQmbox0)
   2.152-			enable = (u32int*)(ARMLOCAL + Localmboxint) + cpu;
   2.153-		else
   2.154-			enable = (u32int*)(ARMLOCAL + Localtimerint) + cpu;
   2.155-		v->mask = 1 << (irq - IRQlocal);
   2.156-	}else if(irq >= IRQbasic){
   2.157-		enable = &ip->ARMenable;
   2.158-		v->reg = &ip->ARMpending;
   2.159-		v->mask = 1 << (irq - IRQbasic);
   2.160-	}else{
   2.161-		enable = &ip->GPUenable[irq/32];
   2.162-		v->reg = &ip->GPUpending[irq/32];
   2.163-		v->mask = 1 << (irq % 32);
   2.164-	}
   2.165-	v->f = f;
   2.166-	v->a = a;
   2.167-	lock(&vctllock);
   2.168-	if(irq == IRQfiq){
   2.169-		assert((ip->FIQctl & Fiqenable) == 0);
   2.170-		assert((*enable & v->mask) == 0);
   2.171-		vfiq = v;
   2.172-		ip->FIQctl = Fiqenable | irq;
   2.173-	}else{
   2.174-		v->next = vctl[cpu];
   2.175-		vctl[cpu] = v;
   2.176-		if(irq >= IRQmbox0){
   2.177-			if(irq <= IRQmbox3)
   2.178-				*enable |= 1 << (irq - IRQmbox0);
   2.179-		}else if(irq >= IRQlocal)
   2.180-			*enable |= 1 << (irq - IRQlocal);
   2.181-		else
   2.182-			*enable = v->mask;
   2.183-	}
   2.184-	unlock(&vctllock);
   2.185-}
   2.186-
   2.187 static char *
   2.188 trapname(int psr)
   2.189 {