2 #include "../port/lib.h"
8 * Mailbox interface with videocore gpu
11 #define MAILBOX (VIRTIO+0xB880)
13 typedef struct Prophdr Prophdr;
14 typedef struct Fbinfo Fbinfo;
15 typedef struct Vgpio Vgpio;
36 TagGetfwrev = 0x00000001,
37 TagGetrev = 0x00010002,
38 TagGetmac = 0x00010003,
39 TagGetram = 0x00010005,
40 TagGetpower = 0x00020001,
41 TagSetpower = 0x00028001,
43 TagGetclkstate = 0x00030001,
44 TagGetclkspd = 0x00030002,
45 TagGetclkmax = 0x00030004,
46 TagSetclkstate = 0x00038001,
47 TagSetclkspd = 0x00038002,
49 TagGetEgpioState= 0x00030041,
50 TagSetEgpioState= 0x00038041,
51 TagSetSdhostClk = 0x00038042,
52 TagGetEgpioConf = 0x00030043,
53 TagSetEgpioConf = 0x00038043,
55 TagGettemp = 0x00030006,
56 TagXhciReset = 0x00030058,
57 TagFballoc = 0x00040001,
58 TagFbfree = 0x00048001,
59 TagFbblank = 0x00040002,
60 TagGetres = 0x00040003,
61 TagSetres = 0x00048003,
62 TagGetvres = 0x00040004,
63 TagSetvres = 0x00048004,
64 TagGetdepth = 0x00040005,
65 TagSetdepth = 0x00048005,
66 TagGetrgb = 0x00040006,
67 TagSetrgb = 0x00048006,
68 TagGetGpio = 0x00040010,
78 u32int pitch; /* returned by gpu */
82 u32int base; /* returned by gpu */
83 u32int screensize; /* returned by gpu */
106 vcwrite(uint chan, int val)
110 r = (u32int*)MAILBOX + NRegs;
112 while(r[Status]&Full)
115 r[Write] = val | chan;
124 r = (u32int*)MAILBOX;
126 while(r[Status]&Empty)
130 }while((x&ChanMask) != chan);
131 return x & ~ChanMask;
139 vcreq(int tag, void *buf, int vallen, int rsplen)
145 static int busaddr = 1;
149 rsplen = (rsplen+3) & ~3;
150 prop = (Prophdr*)(VCBUFFER);
151 n = sizeof(Prophdr) + rsplen + 8;
156 prop->tagbuflen = rsplen;
157 prop->taglen = vallen;
159 memmove(prop->data, buf, vallen);
160 cachedwbinvse(prop, n);
162 aprop = busaddr? dmaaddr(prop) : (uintptr)prop;
163 vcwrite(ChanProps, aprop);
164 r = vcread(ChanProps);
171 cachedinvse(prop, n);
172 if(prop->req == RspOk &&
174 (prop->taglen&TagResp)) {
175 if((n = prop->taglen & ~TagResp) < rsplen)
177 memmove(buf, prop->data, rsplen);
189 fbdefault(int *width, int *height, int *depth)
194 if(vcreq(TagGetres, &buf[0], 0, 2*4) != 2*4 ||
195 vcreq(TagGetdepth, &buf[2], 0, 4) != 4)
199 if((p = getconf("bcm2708_fb.fbdepth")) != nil)
207 fbinit(int set, int *width, int *height, int *depth)
213 fbdefault(width, height, depth);
214 /* Screen width must be a multiple of 16 */
216 fi = (Fbinfo*)(VCBUFFER);
217 memset(fi, 0, sizeof(*fi));
218 fi->xres = fi->xresvirtual = *width;
219 fi->yres = fi->yresvirtual = *height;
221 cachedwbinvse(fi, sizeof(*fi));
222 vcwrite(ChanFb, dmaaddr(fi));
223 if(vcread(ChanFb) != 0)
225 cachedinvse(fi, sizeof(*fi));
226 va = mmukmap(FRAMEBUFFER, (fi->base&~0xC0000000)|PHYSDRAM, fi->screensize);
228 memset((char*)va, 0x7F, fi->screensize);
238 if(vcreq(TagFbblank, buf, sizeof buf, sizeof buf) != sizeof buf)
247 setpower(int dev, int on)
252 buf[1] = Powerwait | (on? 1 : 0);
253 vcreq(TagSetpower, buf, sizeof buf, sizeof buf);
263 if(vcreq(TagGetpower, buf, sizeof buf[0], sizeof buf) != sizeof buf)
269 * Get ethernet address (as hex string)
280 memset(ea, 0, sizeof ea);
281 vcreq(TagGetmac, ea, 0, sizeof ea);
283 for(i = 0; i < 6; i++)
284 p += sprint(p, "%.2x", ea[i]);
296 if(vcreq(TagGetrev, buf, 0, sizeof buf) != sizeof buf)
302 * Get firmware revision
309 if(vcreq(TagGetfwrev, buf, 0, sizeof buf) != sizeof buf)
318 getramsize(Confmem *mem)
322 if(vcreq(TagGetram, buf, 0, sizeof buf) != sizeof buf)
332 getclkrate(int clkid)
337 if(vcreq(TagGetclkspd, buf, sizeof(buf[0]), sizeof(buf)) != sizeof buf)
343 * Set clock rate to hz (or max speed if hz == 0)
346 setclkrate(int clkid, ulong hz)
353 else if(vcreq(TagGetclkmax, buf, sizeof(buf[0]), sizeof(buf)) != sizeof buf)
355 vcreq(TagSetclkspd, buf, sizeof(buf), sizeof(buf));
359 * Get cpu temperature
367 if(vcreq(TagGettemp, buf, sizeof(buf[0]), sizeof buf) != sizeof buf)
373 * Virtual GPIO - used for ACT LED on pi3
382 if(vcreq(TagGetGpio, buf, 0, sizeof(buf)) != sizeof buf || buf[0] == 0)
384 va = mmukmap(VGPIO, buf[0] & ~0xC0000000, BY2PG);
387 vgpio.counts = (u32int*)va;
391 vgpset(uint port, int on)
393 if(vgpio.counts == nil || port >= Nvgpio || on == vgpio.ison)
399 vgpio.counts[port] = (vgpio.incs << 16) | vgpio.decs;
404 * Raspberry Pi GPIO expander (Pi 3 and 4)
407 egpset(uint port, int on)
415 vcreq(TagSetEgpioState, buf, sizeof(buf), sizeof(buf));
419 * Notify gpu that xhci firmware might need loading. This is for some
420 * pi4 board versions which are missing the eeprom chip for the vl805,
421 * requiring its firmware to come from the boot eeprom instead.
424 xhcireset(int devaddr)
429 if(vcreq(TagXhciReset, buf, sizeof(buf), sizeof(buf[0])) == sizeof(buf[0]))