xref: /plan9-contrib/sys/src/9/bcm/archbcm4.c (revision 5c47fe09a0cc86dfb02c0ea4a2b6aec7eda2361f)
1 /*
2  * bcm2711 (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 "arm.h"
13 
14 #include "../port/netif.h"
15 #include "etherif.h"
16 
17 typedef struct Mbox Mbox;
18 typedef struct Mboxes Mboxes;
19 
20 #define	POWERREGS	(VIRTIO+0x100000)
21 
22 Soc soc = {
23 	.dramsize	= 0xFC000000,
24 	.physio		= 0xFE000000,
25 	.busdram	= 0xC0000000,
26 	.busio		= 0x7E000000,
27 	.armlocal	= 0xFF800000,
28 	.oscfreq	= 54000000,
29 	.l1ptedramattrs = Cached | Buffered | L1wralloc | L1sharable,
30 	.l2ptedramattrs = Cached | Buffered | L2wralloc | L2sharable,
31 };
32 
33 enum {
34 	Wdogfreq	= 65536,
35 	Wdogtime	= 10,	/* seconds, ≤ 15 */
36 };
37 
38 /*
39  * Power management / watchdog registers
40  */
41 enum {
42 	Rstc		= 0x1c>>2,
43 		Password	= 0x5A<<24,
44 		CfgMask		= 0x03<<4,
45 		CfgReset	= 0x02<<4,
46 	Rsts		= 0x20>>2,
47 	Wdog		= 0x24>>2,
48 };
49 
50 /*
51  * Arm local regs for smp
52  */
53 struct Mbox {
54 	u32int	doorbell;
55 	u32int	mbox1;
56 	u32int	mbox2;
57 	u32int	startcpu;
58 };
59 struct Mboxes {
60 	Mbox	set[4];
61 	Mbox	clr[4];
62 };
63 
64 enum {
65 	Mboxregs	= 0x80
66 };
67 
68 static Lock startlock[MAXMACH + 1];
69 
70 void
archreset(void)71 archreset(void)
72 {
73 	fpon();
74 }
75 
76 void
archreboot(void)77 archreboot(void)
78 {
79 	u32int *r;
80 
81 	r = (u32int*)POWERREGS;
82 	r[Wdog] = Password | 1;
83 	r[Rstc] = Password | (r[Rstc] & ~CfgMask) | CfgReset;
84 	coherence();
85 	for(;;)
86 		;
87 }
88 
89 void
wdogfeed(void)90 wdogfeed(void)
91 {
92 	u32int *r;
93 
94 	r = (u32int*)POWERREGS;
95 	r[Wdog] = Password | (Wdogtime * Wdogfreq);
96 	r[Rstc] = Password | (r[Rstc] & ~CfgMask) | CfgReset;
97 }
98 
99 void
wdogoff(void)100 wdogoff(void)
101 {
102 	u32int *r;
103 
104 	r = (u32int*)POWERREGS;
105 	r[Rstc] = Password | (r[Rstc] & ~CfgMask);
106 }
107 
108 
109 char *
cputype2name(char * buf,int size)110 cputype2name(char *buf, int size)
111 {
112 	u32int r;
113 	uint part;
114 	char *p;
115 
116 	r = cpidget();			/* main id register */
117 	assert((r >> 24) == 'A');
118 	part = (r >> 4) & MASK(12);
119 	switch(part){
120 	case 0xc07:
121 		p = seprint(buf, buf + size, "Cortex-A7");
122 		break;
123 	case 0xd03:
124 		p = seprint(buf, buf + size, "Cortex-A53");
125 		break;
126 	case 0xd08:
127 		p = seprint(buf, buf + size, "Cortex-A72");
128 		break;
129 	default:
130 		p = seprint(buf, buf + size, "Unknown-%#x", part);
131 		break;
132 	}
133 	seprint(p, buf + size, " r%ldp%ld",
134 		(r >> 20) & MASK(4), r & MASK(4));
135 	return buf;
136 }
137 
138 void
cpuidprint(void)139 cpuidprint(void)
140 {
141 	char name[64];
142 
143 	cputype2name(name, sizeof name);
144 	delay(50);				/* let uart catch up */
145 	print("cpu%d: %dMHz ARM %s\n", m->machno, m->cpumhz, name);
146 }
147 
148 int
getncpus(void)149 getncpus(void)
150 {
151 	int n, max;
152 	char *p;
153 
154 	n = 4;
155 	if(n > MAXMACH)
156 		n = MAXMACH;
157 	p = getconf("*ncpu");
158 	if(p && (max = atoi(p)) > 0 && n > max)
159 		n = max;
160 	return n;
161 }
162 
163 static int
startcpu(uint cpu)164 startcpu(uint cpu)
165 {
166 	Mboxes *mb;
167 	int i;
168 	void cpureset();
169 
170 	mb = (Mboxes*)(ARMLOCAL + Mboxregs);
171 	if(mb->clr[cpu].startcpu)
172 		return -1;
173 	mb->set[cpu].startcpu = PADDR(cpureset);
174 	coherence();
175 	sev();
176 	for(i = 0; i < 1000; i++)
177 		if(mb->clr[cpu].startcpu == 0)
178 			return 0;
179 	mb->clr[cpu].startcpu = PADDR(cpureset);
180 	mb->set[cpu].doorbell = 1;
181 	return 0;
182 }
183 
184 void
mboxclear(uint cpu)185 mboxclear(uint cpu)
186 {
187 	Mboxes *mb;
188 
189 	mb = (Mboxes*)(ARMLOCAL + Mboxregs);
190 	mb->clr[cpu].mbox1 = 1;
191 }
192 
193 void
wakecpu(uint cpu)194 wakecpu(uint cpu)
195 {
196 	Mboxes *mb;
197 
198 	mb = (Mboxes*)(ARMLOCAL + Mboxregs);
199 	mb->set[cpu].mbox1 = 1;
200 }
201 
202 int
startcpus(uint ncpu)203 startcpus(uint ncpu)
204 {
205 	int i, timeout;
206 
207 	for(i = 0; i < ncpu; i++)
208 		lock(&startlock[i]);
209 	cachedwbse(startlock, sizeof startlock);
210 	for(i = 1; i < ncpu; i++){
211 		if(startcpu(i) < 0)
212 			return i;
213 		timeout = 10000000;
214 		while(!canlock(&startlock[i]))
215 			if(--timeout == 0)
216 				return i;
217 		unlock(&startlock[i]);
218 	}
219 	return ncpu;
220 }
221 
222 void
archbcm4link(void)223 archbcm4link(void)
224 {
225 	addclock0link(wdogfeed, HZ);
226 }
227 
228 int
archether(unsigned ctlrno,Ether * ether)229 archether(unsigned ctlrno, Ether *ether)
230 {
231 	switch(ctlrno){
232 	case 0:
233 		ether->type = "genet";
234 		break;
235 	case 1:
236 		ether->type = "4330";
237 		break;
238 	default:
239 		return 0;
240 	}
241 	ether->ctlrno = ctlrno;
242 	ether->irq = -1;
243 	ether->nopt = 0;
244 	ether->maxmtu = 9014;
245 	return 1;
246 }
247 
248 int
l2ap(int ap)249 l2ap(int ap)
250 {
251 	return (AP(0, (ap)));
252 }
253 
254 int
cmpswap(long * addr,long old,long new)255 cmpswap(long *addr, long old, long new)
256 {
257 	return cas((ulong*)addr, old, new);
258 }
259 
260 void
cpustart(int cpu)261 cpustart(int cpu)
262 {
263 	Mboxes *mb;
264 	void machon(int);
265 
266 	up = nil;
267 	machinit();
268 	mb = (Mboxes*)(ARMLOCAL + Mboxregs);
269 	mb->clr[cpu].doorbell = 1;
270 	trapinit();
271 	clockinit();
272 	mmuinit1();
273 	timersinit();
274 	cpuidprint();
275 	archreset();
276 	machon(m->machno);
277 	unlock(&startlock[cpu]);
278 	schedinit();
279 	panic("schedinit returned");
280 }
281