]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/bcm64/archbcm4.c
amd64: FP: always use enough to fit AVX state and align to 64 bytes
[plan9front.git] / sys / src / 9 / bcm64 / archbcm4.c
1 /*
2  * bcm2711 (e.g.raspberry pi 4) architecture-specific stuff
3  */
4
5 #include "u.h"
6 #include "../port/lib.h"
7 #include "mem.h"
8 #include "dat.h"
9 #include "fns.h"
10 #include "../port/error.h"
11 #include "io.h"
12 #include "../port/pci.h"
13 #include "sysreg.h"
14
15 typedef struct Mbox Mbox;
16 typedef struct Mboxes Mboxes;
17
18 #define POWERREGS       (VIRTIO+0x100000)
19
20 Soc soc = {
21         .dramsize       = 0xFC000000,
22         .busdram        = 0xC0000000,
23         .iosize         = 0x03000000,
24         .busio          = 0x7C000000,
25         .physio         = 0xFC000000,
26         .virtio         = VIRTIO2,
27         .armlocal       = 0xFF800000,
28         .pciwin         = 0x0600000000ULL,
29         .oscfreq        = 54000000,
30 };
31
32 enum {
33         Wdogfreq        = 65536,
34         Wdogtime        = 10,   /* seconds, ≤ 15 */
35 };
36
37 /*
38  * Power management / watchdog registers
39  */
40 enum {
41         Rstc            = 0x1c>>2,
42                 Password        = 0x5A<<24,
43                 CfgMask         = 0x03<<4,
44                 CfgReset        = 0x02<<4,
45         Rsts            = 0x20>>2,
46         Wdog            = 0x24>>2,
47 };
48
49 /*
50  * Arm local regs for smp
51  */
52 struct Mbox {
53         u32int  doorbell;
54         u32int  mbox1;
55         u32int  mbox2;
56         u32int  startcpu;
57 };
58 struct Mboxes {
59         Mbox    set[4];
60         Mbox    clr[4];
61 };
62
63 enum {
64         Mboxregs        = 0x80,
65 };
66
67 void
68 archreset(void)
69 {
70 }
71
72 void
73 archreboot(void)
74 {
75         u32int *r;
76
77         r = (u32int*)POWERREGS;
78         r[Wdog] = Password | 1;
79         r[Rstc] = Password | (r[Rstc] & ~CfgMask) | CfgReset;
80         coherence();
81         for(;;)
82                 ;
83 }
84
85 void
86 wdogfeed(void)
87 {
88         u32int *r;
89
90         r = (u32int*)POWERREGS;
91         r[Wdog] = Password | (Wdogtime * Wdogfreq);
92         r[Rstc] = Password | (r[Rstc] & ~CfgMask) | CfgReset;
93 }
94
95 void
96 wdogoff(void)
97 {
98         u32int *r;
99
100         r = (u32int*)POWERREGS;
101         r[Rstc] = Password | (r[Rstc] & ~CfgMask);
102 }
103
104
105 char *
106 cputype2name(char *buf, int size)
107 {
108         u32int r, part;
109         char *p;
110
111         r = sysrd(MIDR_EL1);
112         part = (r >> 4) & 0xFFF;
113         switch(part){
114         case 0xc07:
115                 p = seprint(buf, buf + size, "Cortex-A7");
116                 break;
117         case 0xd03:
118                 p = seprint(buf, buf + size, "Cortex-A53");
119                 break;
120         case 0xd08:
121                 p = seprint(buf, buf + size, "Cortex-A72");
122                 break;
123         default:
124                 p = seprint(buf, buf + size, "Unknown-%#x", part);
125                 break;
126         }
127         seprint(p, buf + size, " r%udp%ud", (r >> 20) & 0xF, r & 0xF);
128         return buf;
129 }
130
131 void
132 cpuidprint(void)
133 {
134         char name[64];
135
136         cputype2name(name, sizeof name);
137         iprint("cpu%d: %dMHz ARM %s\n", m->machno, m->cpumhz, name);
138 }
139
140 int
141 getncpus(void)
142 {
143         int n, max;
144         char *p;
145
146         n = 4;
147         if(n > MAXMACH)
148                 n = MAXMACH;
149         p = getconf("*ncpu");
150         if(p && (max = atoi(p)) > 0 && n > max)
151                 n = max;
152         return n;
153 }
154
155 void
156 mboxclear(uint cpu)
157 {
158         Mboxes *mb;
159
160         mb = (Mboxes*)(ARMLOCAL + Mboxregs);
161         mb->clr[cpu].mbox1 = 1;
162 }
163
164 void
165 wakecpu(uint cpu)
166 {
167         Mboxes *mb;
168
169         mb = (Mboxes*)(ARMLOCAL + Mboxregs);
170         mb->set[cpu].mbox1 = 1;
171 }
172
173 void
174 archbcm4link(void)
175 {
176         Pcidev *p;
177
178         /*
179          * The firmware resets PCI before starting the host OS because
180          * without SDRAM the VL805 makes inbound requests to page-in firmware
181          * from SDRAM. If the OS has a different PCI mapping that would all break.
182          * There's no way to pause and move the mappings and it's not really desirable
183          * for the firmware to dictate the PCI configuration. Consequently, the mailbox
184          * is required so that the OS can reset the VLI after asserting PCI chip reset.
185          */
186         if((p = pcimatch(nil, 0x1106, 0x3483)) != nil)
187                 xhcireset(BUSBNO(p->tbdf)<<20 | BUSDNO(p->tbdf)<<15 | BUSFNO(p->tbdf)<<12);
188
189         // addclock0link(wdogfeed, HZ);
190 }