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/archbcm2.c | |
parent | 796e5e6000677a39577d545e4603ce251e7cbfe9 (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.c | 248 |
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"); +} |