summaryrefslogtreecommitdiff
path: root/sys/src/9/bcm/archbcm2.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/archbcm2.c
parent796e5e6000677a39577d545e4603ce251e7cbfe9 (diff)
bcm: import changes for raspi2/3 from richard miller
Diffstat (limited to 'sys/src/9/bcm/archbcm2.c')
-rw-r--r--sys/src/9/bcm/archbcm2.c248
1 files changed, 248 insertions, 0 deletions
diff --git a/sys/src/9/bcm/archbcm2.c b/sys/src/9/bcm/archbcm2.c
new file mode 100644
index 000000000..03836ca51
--- /dev/null
+++ b/sys/src/9/bcm/archbcm2.c
@@ -0,0 +1,248 @@
+/*
+ * bcm2836 (e.g.raspberry pi 2) architecture-specific stuff
+ */
+
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "io.h"
+#include "arm.h"
+
+#include "../port/netif.h"
+
+typedef struct Mbox Mbox;
+typedef struct Mboxes Mboxes;
+
+#define POWERREGS (VIRTIO+0x100000)
+
+Soc soc = {
+ .dramsize = 0x3F000000, /* was 1024*MiB, but overlaps with physio */
+ .physio = 0x3F000000,
+ .busdram = 0xC0000000,
+ .busio = 0x7E000000,
+ .armlocal = 0x40000000,
+ .l1ptedramattrs = Cached | Buffered | L1wralloc | L1sharable,
+ .l2ptedramattrs = Cached | Buffered | L2wralloc | L2sharable,
+};
+
+enum {
+ Wdogfreq = 65536,
+ Wdogtime = 10, /* seconds, ≤ 15 */
+};
+
+/*
+ * Power management / watchdog registers
+ */
+enum {
+ Rstc = 0x1c>>2,
+ Password = 0x5A<<24,
+ CfgMask = 0x03<<4,
+ CfgReset = 0x02<<4,
+ Rsts = 0x20>>2,
+ Wdog = 0x24>>2,
+};
+
+/*
+ * Arm local regs for smp
+ */
+struct Mbox {
+ u32int doorbell;
+ u32int mbox1;
+ u32int mbox2;
+ u32int startcpu;
+};
+struct Mboxes {
+ Mbox set[4];
+ Mbox clr[4];
+};
+
+enum {
+ Mboxregs = 0x80
+};
+
+static Lock startlock[MAXMACH + 1];
+
+void
+archreset(void)
+{
+ fpon();
+}
+
+void
+archreboot(void)
+{
+ u32int *r;
+
+ r = (u32int*)POWERREGS;
+ r[Wdog] = Password | 1;
+ r[Rstc] = Password | (r[Rstc] & ~CfgMask) | CfgReset;
+ coherence();
+ for(;;)
+ ;
+}
+
+void
+wdogfeed(void)
+{
+ u32int *r;
+
+ r = (u32int*)POWERREGS;
+ r[Wdog] = Password | (Wdogtime * Wdogfreq);
+ r[Rstc] = Password | (r[Rstc] & ~CfgMask) | CfgReset;
+}
+
+void
+wdogoff(void)
+{
+ u32int *r;
+
+ r = (u32int*)POWERREGS;
+ r[Rstc] = Password | (r[Rstc] & ~CfgMask);
+}
+
+
+char *
+cputype2name(char *buf, int size)
+{
+ u32int r;
+ uint part;
+ char *p;
+
+ r = cpidget(); /* main id register */
+ assert((r >> 24) == 'A');
+ part = (r >> 4) & MASK(12);
+ switch(part){
+ case 0xc07:
+ p = seprint(buf, buf + size, "Cortex-A7");
+ break;
+ case 0xd03:
+ p = seprint(buf, buf + size, "Cortex-A53");
+ break;
+ default:
+ p = seprint(buf, buf + size, "Unknown-%#x", part);
+ break;
+ }
+ seprint(p, buf + size, " r%ldp%ld",
+ (r >> 20) & MASK(4), r & MASK(4));
+ return buf;
+}
+
+void
+cpuidprint(void)
+{
+ char name[64];
+
+ cputype2name(name, sizeof name);
+ delay(50); /* let uart catch up */
+ print("cpu%d: %dMHz ARM %s\n", m->machno, m->cpumhz, name);
+}
+
+int
+getncpus(void)
+{
+ int n, max;
+ char *p;
+
+ n = 4;
+ if(n > MAXMACH)
+ n = MAXMACH;
+ p = getconf("*ncpu");
+ if(p && (max = atoi(p)) > 0 && n > max)
+ n = max;
+ return n;
+}
+
+static int
+startcpu(uint cpu)
+{
+ Mboxes *mb;
+ int i;
+ void cpureset();
+
+ mb = (Mboxes*)(ARMLOCAL + Mboxregs);
+ if(mb->clr[cpu].startcpu)
+ return -1;
+ mb->set[cpu].startcpu = PADDR(cpureset);
+ coherence();
+ sev();
+ for(i = 0; i < 1000; i++)
+ if(mb->clr[cpu].startcpu == 0)
+ return 0;
+ mb->clr[cpu].startcpu = PADDR(cpureset);
+ mb->set[cpu].doorbell = 1;
+ return 0;
+}
+
+void
+mboxclear(uint cpu)
+{
+ Mboxes *mb;
+
+ mb = (Mboxes*)(ARMLOCAL + Mboxregs);
+ mb->clr[cpu].mbox1 = 1;
+}
+
+void
+wakecpu(uint cpu)
+{
+ Mboxes *mb;
+
+ mb = (Mboxes*)(ARMLOCAL + Mboxregs);
+ mb->set[cpu].mbox1 = 1;
+}
+
+int
+startcpus(uint ncpu)
+{
+ int i, timeout;
+
+ for(i = 0; i < ncpu; i++)
+ lock(&startlock[i]);
+ cachedwbse(startlock, sizeof startlock);
+ for(i = 1; i < ncpu; i++){
+ if(startcpu(i) < 0)
+ return i;
+ timeout = 10000000;
+ while(!canlock(&startlock[i]))
+ if(--timeout == 0)
+ return i;
+ unlock(&startlock[i]);
+ }
+ return ncpu;
+}
+
+void
+archbcm2link(void)
+{
+ addclock0link(wdogfeed, HZ);
+}
+
+int
+l2ap(int ap)
+{
+ return (AP(0, (ap)));
+}
+
+void
+cpustart(int cpu)
+{
+ Mboxes *mb;
+
+ up = nil;
+ machinit();
+ mb = (Mboxes*)(ARMLOCAL + Mboxregs);
+ mb->clr[cpu].doorbell = 1;
+ trapinit();
+ clockinit();
+ mmuinit1();
+ timersinit();
+ cpuidprint();
+ archreset();
+ active.machs[m->machno] = 1;
+ unlock(&startlock[cpu]);
+ schedinit();
+ panic("schedinit returned");
+}