xref: /plan9-contrib/sys/src/9/bcm/vcore.c (revision 5c47fe09a0cc86dfb02c0ea4a2b6aec7eda2361f)
15d9de2d3SDavid du Colombier #include "u.h"
25d9de2d3SDavid du Colombier #include "../port/lib.h"
35d9de2d3SDavid du Colombier #include "mem.h"
45d9de2d3SDavid du Colombier #include "dat.h"
55d9de2d3SDavid du Colombier #include "fns.h"
65d9de2d3SDavid du Colombier 
75d9de2d3SDavid du Colombier /*
85d9de2d3SDavid du Colombier  * Mailbox interface with videocore gpu
95d9de2d3SDavid du Colombier  */
105d9de2d3SDavid du Colombier 
115d9de2d3SDavid du Colombier #define	MAILBOX		(VIRTIO+0xB880)
125d9de2d3SDavid du Colombier 
135d9de2d3SDavid du Colombier typedef struct Prophdr Prophdr;
145d9de2d3SDavid du Colombier typedef struct Fbinfo Fbinfo;
15*5c47fe09SDavid du Colombier typedef struct Vgpio Vgpio;
165d9de2d3SDavid du Colombier 
175d9de2d3SDavid du Colombier enum {
185d9de2d3SDavid du Colombier 	Read		= 0x00>>2,
195d9de2d3SDavid du Colombier 	Write		= 0x00>>2,
205d9de2d3SDavid du Colombier 	Peek		= 0x10>>2,
215d9de2d3SDavid du Colombier 	Sender		= 0x14>>2,
225d9de2d3SDavid du Colombier 	Status		= 0x18>>2,
235d9de2d3SDavid du Colombier 		Full		= 1<<31,
245d9de2d3SDavid du Colombier 		Empty		= 1<<30,
255d9de2d3SDavid du Colombier 	Config		= 0x1C>>2,
265d9de2d3SDavid du Colombier 	NRegs		= 0x20>>2,
275d9de2d3SDavid du Colombier 
285d9de2d3SDavid du Colombier 	ChanMask	= 0xF,
295d9de2d3SDavid du Colombier 	ChanProps	= 8,
305d9de2d3SDavid du Colombier 	ChanFb		= 1,
315d9de2d3SDavid du Colombier 
325d9de2d3SDavid du Colombier 	Req			= 0x0,
335d9de2d3SDavid du Colombier 	RspOk		= 0x80000000,
345d9de2d3SDavid du Colombier 	TagResp		= 1<<31,
355d9de2d3SDavid du Colombier 
365d9de2d3SDavid du Colombier 	TagGetfwrev	= 0x00000001,
37*5c47fe09SDavid du Colombier 	TagGetrev	= 0x00010002,
385d9de2d3SDavid du Colombier 	TagGetmac	= 0x00010003,
39*5c47fe09SDavid du Colombier 	TagGetser	= 0x00010004,
405d9de2d3SDavid du Colombier 	TagGetram	= 0x00010005,
415d9de2d3SDavid du Colombier 	TagGetpower	= 0x00020001,
425d9de2d3SDavid du Colombier 	TagSetpower	= 0x00028001,
435d9de2d3SDavid du Colombier 		Powerwait	= 1<<1,
445d9de2d3SDavid du Colombier 	TagGetclkspd= 0x00030002,
45*5c47fe09SDavid du Colombier 	TagGetclkmax= 0x00030004,
46*5c47fe09SDavid du Colombier 	TagSetclkspd= 0x00038002,
47*5c47fe09SDavid du Colombier 	TagGettemp	= 0x00030006,
48*5c47fe09SDavid du Colombier 	TagXhciReset= 0x00030058,
495d9de2d3SDavid du Colombier 	TagFballoc	= 0x00040001,
505d9de2d3SDavid du Colombier 	TagFbfree	= 0x00048001,
515d9de2d3SDavid du Colombier 	TagFbblank	= 0x00040002,
525d9de2d3SDavid du Colombier 	TagGetres	= 0x00040003,
535d9de2d3SDavid du Colombier 	TagSetres	= 0x00048003,
545d9de2d3SDavid du Colombier 	TagGetvres	= 0x00040004,
555d9de2d3SDavid du Colombier 	TagSetvres	= 0x00048004,
565d9de2d3SDavid du Colombier 	TagGetdepth	= 0x00040005,
575d9de2d3SDavid du Colombier 	TagSetdepth	= 0x00048005,
58*5c47fe09SDavid du Colombier 	TagGetrgb	= 0x00040006,
595d9de2d3SDavid du Colombier 	TagSetrgb	= 0x00048006,
60*5c47fe09SDavid du Colombier 	TagGetGpio	= 0x00040010,
61*5c47fe09SDavid du Colombier 
62*5c47fe09SDavid du Colombier 	Nvgpio		= 2,
635d9de2d3SDavid du Colombier };
645d9de2d3SDavid du Colombier 
655d9de2d3SDavid du Colombier struct Fbinfo {
665d9de2d3SDavid du Colombier 	u32int	xres;
675d9de2d3SDavid du Colombier 	u32int	yres;
685d9de2d3SDavid du Colombier 	u32int	xresvirtual;
695d9de2d3SDavid du Colombier 	u32int	yresvirtual;
705d9de2d3SDavid du Colombier 	u32int	pitch;			/* returned by gpu */
715d9de2d3SDavid du Colombier 	u32int	bpp;
725d9de2d3SDavid du Colombier 	u32int	xoffset;
735d9de2d3SDavid du Colombier 	u32int	yoffset;
745d9de2d3SDavid du Colombier 	u32int	base;			/* returned by gpu */
755d9de2d3SDavid du Colombier 	u32int	screensize;		/* returned by gpu */
765d9de2d3SDavid du Colombier };
775d9de2d3SDavid du Colombier 
785d9de2d3SDavid du Colombier 
795d9de2d3SDavid du Colombier struct Prophdr {
805d9de2d3SDavid du Colombier 	u32int	len;
815d9de2d3SDavid du Colombier 	u32int	req;
825d9de2d3SDavid du Colombier 	u32int	tag;
835d9de2d3SDavid du Colombier 	u32int	tagbuflen;
845d9de2d3SDavid du Colombier 	u32int	taglen;
855d9de2d3SDavid du Colombier 	u32int	data[1];
865d9de2d3SDavid du Colombier };
875d9de2d3SDavid du Colombier 
88*5c47fe09SDavid du Colombier struct Vgpio {
89*5c47fe09SDavid du Colombier 	u32int	*counts;
90*5c47fe09SDavid du Colombier 	u16int	incs;
91*5c47fe09SDavid du Colombier 	u16int	decs;
92*5c47fe09SDavid du Colombier 	int	ison;
93*5c47fe09SDavid du Colombier };
94*5c47fe09SDavid du Colombier 
95*5c47fe09SDavid du Colombier static Vgpio vgpio;
96*5c47fe09SDavid du Colombier 
975d9de2d3SDavid du Colombier static void
vcwrite(uint chan,int val)985d9de2d3SDavid du Colombier vcwrite(uint chan, int val)
995d9de2d3SDavid du Colombier {
1005d9de2d3SDavid du Colombier 	u32int *r;
1015d9de2d3SDavid du Colombier 
1025d9de2d3SDavid du Colombier 	r = (u32int*)MAILBOX + NRegs;
1035d9de2d3SDavid du Colombier 	val &= ~ChanMask;
1045d9de2d3SDavid du Colombier 	while(r[Status]&Full)
1055d9de2d3SDavid du Colombier 		;
1065d9de2d3SDavid du Colombier 	coherence();
1075d9de2d3SDavid du Colombier 	r[Write] = val | chan;
1085d9de2d3SDavid du Colombier }
1095d9de2d3SDavid du Colombier 
1105d9de2d3SDavid du Colombier static int
vcread(uint chan)1115d9de2d3SDavid du Colombier vcread(uint chan)
1125d9de2d3SDavid du Colombier {
1135d9de2d3SDavid du Colombier 	u32int *r;
1145d9de2d3SDavid du Colombier 	int x;
1155d9de2d3SDavid du Colombier 
1165d9de2d3SDavid du Colombier 	r = (u32int*)MAILBOX;
1175d9de2d3SDavid du Colombier 	do{
1185d9de2d3SDavid du Colombier 		while(r[Status]&Empty)
1195d9de2d3SDavid du Colombier 			;
1205d9de2d3SDavid du Colombier 		coherence();
1215d9de2d3SDavid du Colombier 		x = r[Read];
1225d9de2d3SDavid du Colombier 	}while((x&ChanMask) != chan);
1235d9de2d3SDavid du Colombier 	return x & ~ChanMask;
1245d9de2d3SDavid du Colombier }
1255d9de2d3SDavid du Colombier 
1265d9de2d3SDavid du Colombier /*
1275d9de2d3SDavid du Colombier  * Property interface
1285d9de2d3SDavid du Colombier  */
1295d9de2d3SDavid du Colombier 
1305d9de2d3SDavid du Colombier static int
vcreq(int tag,void * buf,int vallen,int rsplen)1315d9de2d3SDavid du Colombier vcreq(int tag, void *buf, int vallen, int rsplen)
1325d9de2d3SDavid du Colombier {
1335d9de2d3SDavid du Colombier 	uintptr r;
1345d9de2d3SDavid du Colombier 	int n;
1355d9de2d3SDavid du Colombier 	Prophdr *prop;
136*5c47fe09SDavid du Colombier 	uintptr aprop;
137*5c47fe09SDavid du Colombier 	static int busaddr = 1;
1385d9de2d3SDavid du Colombier 
1395d9de2d3SDavid du Colombier 	if(rsplen < vallen)
1405d9de2d3SDavid du Colombier 		rsplen = vallen;
1415d9de2d3SDavid du Colombier 	rsplen = (rsplen+3) & ~3;
1425d9de2d3SDavid du Colombier 	prop = (Prophdr*)(VCBUFFER);
1435d9de2d3SDavid du Colombier 	n = sizeof(Prophdr) + rsplen + 8;
1445d9de2d3SDavid du Colombier 	memset(prop, 0, n);
1455d9de2d3SDavid du Colombier 	prop->len = n;
1465d9de2d3SDavid du Colombier 	prop->req = Req;
1475d9de2d3SDavid du Colombier 	prop->tag = tag;
1485d9de2d3SDavid du Colombier 	prop->tagbuflen = rsplen;
1495d9de2d3SDavid du Colombier 	prop->taglen = vallen;
1505d9de2d3SDavid du Colombier 	if(vallen > 0)
1515d9de2d3SDavid du Colombier 		memmove(prop->data, buf, vallen);
1525d9de2d3SDavid du Colombier 	cachedwbinvse(prop, prop->len);
1535d9de2d3SDavid du Colombier 	for(;;){
154*5c47fe09SDavid du Colombier 		aprop = busaddr? dmaaddr(prop) : PTR2UINT(prop);
155*5c47fe09SDavid du Colombier 		vcwrite(ChanProps, aprop);
1565d9de2d3SDavid du Colombier 		r = vcread(ChanProps);
157*5c47fe09SDavid du Colombier 		if(r == aprop)
1585d9de2d3SDavid du Colombier 			break;
159*5c47fe09SDavid du Colombier 		if(!busaddr)
1605d9de2d3SDavid du Colombier 			return -1;
161*5c47fe09SDavid du Colombier 		busaddr = 0;
1625d9de2d3SDavid du Colombier 	}
163b4d1cf41SDavid du Colombier 	if(prop->req == RspOk &&
164b4d1cf41SDavid du Colombier 	   prop->tag == tag &&
165b4d1cf41SDavid du Colombier 	   (prop->taglen&TagResp)) {
1665d9de2d3SDavid du Colombier 		if((n = prop->taglen & ~TagResp) < rsplen)
1675d9de2d3SDavid du Colombier 			rsplen = n;
1685d9de2d3SDavid du Colombier 		memmove(buf, prop->data, rsplen);
1695d9de2d3SDavid du Colombier 	}else
1705d9de2d3SDavid du Colombier 		rsplen = -1;
1715d9de2d3SDavid du Colombier 
1725d9de2d3SDavid du Colombier 	return rsplen;
1735d9de2d3SDavid du Colombier }
1745d9de2d3SDavid du Colombier 
1755d9de2d3SDavid du Colombier /*
1765d9de2d3SDavid du Colombier  * Framebuffer
1775d9de2d3SDavid du Colombier  */
1785d9de2d3SDavid du Colombier 
1795d9de2d3SDavid du Colombier static int
fbdefault(int * width,int * height,int * depth)1805d9de2d3SDavid du Colombier fbdefault(int *width, int *height, int *depth)
1815d9de2d3SDavid du Colombier {
1825d9de2d3SDavid du Colombier 	u32int buf[3];
183*5c47fe09SDavid du Colombier 	char *p;
1845d9de2d3SDavid du Colombier 
1855d9de2d3SDavid du Colombier 	if(vcreq(TagGetres, &buf[0], 0, 2*4) != 2*4 ||
1865d9de2d3SDavid du Colombier 	   vcreq(TagGetdepth, &buf[2], 0, 4) != 4)
1875d9de2d3SDavid du Colombier 		return -1;
1885d9de2d3SDavid du Colombier 	*width = buf[0];
1895d9de2d3SDavid du Colombier 	*height = buf[1];
190*5c47fe09SDavid du Colombier 	if((p = getconf("bcm2708_fb.fbdepth")) != nil)
191*5c47fe09SDavid du Colombier 		*depth = atoi(p);
192*5c47fe09SDavid du Colombier 	else
1935d9de2d3SDavid du Colombier 		*depth = buf[2];
1945d9de2d3SDavid du Colombier 	return 0;
1955d9de2d3SDavid du Colombier }
1965d9de2d3SDavid du Colombier 
1975d9de2d3SDavid du Colombier void*
fbinit(int set,int * width,int * height,int * depth)1985d9de2d3SDavid du Colombier fbinit(int set, int *width, int *height, int *depth)
1995d9de2d3SDavid du Colombier {
2005d9de2d3SDavid du Colombier 	Fbinfo *fi;
2015d9de2d3SDavid du Colombier 	uintptr va;
2025d9de2d3SDavid du Colombier 
2035d9de2d3SDavid du Colombier 	if(!set)
2045d9de2d3SDavid du Colombier 		fbdefault(width, height, depth);
2055d9de2d3SDavid du Colombier 	/* Screen width must be a multiple of 16 */
2065d9de2d3SDavid du Colombier 	*width &= ~0xF;
2075d9de2d3SDavid du Colombier 	fi = (Fbinfo*)(VCBUFFER);
2085d9de2d3SDavid du Colombier 	memset(fi, 0, sizeof(*fi));
2095d9de2d3SDavid du Colombier 	fi->xres = fi->xresvirtual = *width;
2105d9de2d3SDavid du Colombier 	fi->yres = fi->yresvirtual = *height;
2115d9de2d3SDavid du Colombier 	fi->bpp = *depth;
2125d9de2d3SDavid du Colombier 	cachedwbinvse(fi, sizeof(*fi));
213*5c47fe09SDavid du Colombier 	vcwrite(ChanFb, dmaaddr(fi));
2145d9de2d3SDavid du Colombier 	if(vcread(ChanFb) != 0)
2155d9de2d3SDavid du Colombier 		return 0;
216*5c47fe09SDavid du Colombier 	va = mmukmap(FRAMEBUFFER, fi->base & ~0xC0000000, fi->screensize);
2175d9de2d3SDavid du Colombier 	if(va)
2185d9de2d3SDavid du Colombier 		memset((char*)va, 0x7F, fi->screensize);
2195d9de2d3SDavid du Colombier 	return (void*)va;
2205d9de2d3SDavid du Colombier }
2215d9de2d3SDavid du Colombier 
2225d9de2d3SDavid du Colombier int
fbblank(int blank)2235d9de2d3SDavid du Colombier fbblank(int blank)
2245d9de2d3SDavid du Colombier {
2255d9de2d3SDavid du Colombier 	u32int buf[1];
2265d9de2d3SDavid du Colombier 
2275d9de2d3SDavid du Colombier 	buf[0] = blank;
2285d9de2d3SDavid du Colombier 	if(vcreq(TagFbblank, buf, sizeof buf, sizeof buf) != sizeof buf)
2295d9de2d3SDavid du Colombier 		return -1;
2305d9de2d3SDavid du Colombier 	return buf[0] & 1;
2315d9de2d3SDavid du Colombier }
2325d9de2d3SDavid du Colombier 
2335d9de2d3SDavid du Colombier /*
2345d9de2d3SDavid du Colombier  * Power management
2355d9de2d3SDavid du Colombier  */
2365d9de2d3SDavid du Colombier void
setpower(int dev,int on)2375d9de2d3SDavid du Colombier setpower(int dev, int on)
2385d9de2d3SDavid du Colombier {
2395d9de2d3SDavid du Colombier 	u32int buf[2];
2405d9de2d3SDavid du Colombier 
2415d9de2d3SDavid du Colombier 	buf[0] = dev;
2425d9de2d3SDavid du Colombier 	buf[1] = Powerwait | (on? 1 : 0);
2435d9de2d3SDavid du Colombier 	vcreq(TagSetpower, buf, sizeof buf, sizeof buf);
2445d9de2d3SDavid du Colombier }
2455d9de2d3SDavid du Colombier 
2465d9de2d3SDavid du Colombier int
getpower(int dev)2475d9de2d3SDavid du Colombier getpower(int dev)
2485d9de2d3SDavid du Colombier {
2495d9de2d3SDavid du Colombier 	u32int buf[2];
2505d9de2d3SDavid du Colombier 
2515d9de2d3SDavid du Colombier 	buf[0] = dev;
2525d9de2d3SDavid du Colombier 	buf[1] = 0;
2535d9de2d3SDavid du Colombier 	if(vcreq(TagGetpower, buf, sizeof buf[0], sizeof buf) != sizeof buf)
2545d9de2d3SDavid du Colombier 		return -1;
2555d9de2d3SDavid du Colombier 	return buf[0] & 1;
2565d9de2d3SDavid du Colombier }
2575d9de2d3SDavid du Colombier 
2585d9de2d3SDavid du Colombier /*
2595d9de2d3SDavid du Colombier  * Get ethernet address (as hex string)
2605d9de2d3SDavid du Colombier  *	 [not reentrant]
2615d9de2d3SDavid du Colombier  */
2625d9de2d3SDavid du Colombier char *
getethermac(void)2635d9de2d3SDavid du Colombier getethermac(void)
2645d9de2d3SDavid du Colombier {
2655d9de2d3SDavid du Colombier 	uchar ea[8];
2665d9de2d3SDavid du Colombier 	char *p;
2675d9de2d3SDavid du Colombier 	int i;
2685d9de2d3SDavid du Colombier 	static char buf[16];
2695d9de2d3SDavid du Colombier 
2705d9de2d3SDavid du Colombier 	memset(ea, 0, sizeof ea);
2715d9de2d3SDavid du Colombier 	vcreq(TagGetmac, ea, 0, sizeof ea);
2725d9de2d3SDavid du Colombier 	p = buf;
2735d9de2d3SDavid du Colombier 	for(i = 0; i < 6; i++)
2745d9de2d3SDavid du Colombier 		p += sprint(p, "%.2x", ea[i]);
2755d9de2d3SDavid du Colombier 	return buf;
2765d9de2d3SDavid du Colombier }
2775d9de2d3SDavid du Colombier 
2785d9de2d3SDavid du Colombier /*
279*5c47fe09SDavid du Colombier  * Get board revision
280*5c47fe09SDavid du Colombier  */
281*5c47fe09SDavid du Colombier uint
getboardrev(void)282*5c47fe09SDavid du Colombier getboardrev(void)
283*5c47fe09SDavid du Colombier {
284*5c47fe09SDavid du Colombier 	u32int buf[1];
285*5c47fe09SDavid du Colombier 
286*5c47fe09SDavid du Colombier 	if(vcreq(TagGetrev, buf, 0, sizeof buf) != sizeof buf)
287*5c47fe09SDavid du Colombier 		return 0;
288*5c47fe09SDavid du Colombier 	return buf[0];
289*5c47fe09SDavid du Colombier }
290*5c47fe09SDavid du Colombier 
291*5c47fe09SDavid du Colombier /*
2925d9de2d3SDavid du Colombier  * Get firmware revision
2935d9de2d3SDavid du Colombier  */
2945d9de2d3SDavid du Colombier uint
getfirmware(void)2955d9de2d3SDavid du Colombier getfirmware(void)
2965d9de2d3SDavid du Colombier {
2975d9de2d3SDavid du Colombier 	u32int buf[1];
2985d9de2d3SDavid du Colombier 
2995d9de2d3SDavid du Colombier 	if(vcreq(TagGetfwrev, buf, 0, sizeof buf) != sizeof buf)
3005d9de2d3SDavid du Colombier 		return 0;
3015d9de2d3SDavid du Colombier 	return buf[0];
3025d9de2d3SDavid du Colombier }
3035d9de2d3SDavid du Colombier 
3045d9de2d3SDavid du Colombier /*
305*5c47fe09SDavid du Colombier  * Get serial number
306*5c47fe09SDavid du Colombier  */
307*5c47fe09SDavid du Colombier uvlong
getserial(void)308*5c47fe09SDavid du Colombier getserial(void)
309*5c47fe09SDavid du Colombier {
310*5c47fe09SDavid du Colombier 	uvlong buf;
311*5c47fe09SDavid du Colombier 
312*5c47fe09SDavid du Colombier 	if(vcreq(TagGetser, &buf, 0, sizeof buf) != sizeof buf)
313*5c47fe09SDavid du Colombier 		return 0;
314*5c47fe09SDavid du Colombier 	return buf;
315*5c47fe09SDavid du Colombier }
316*5c47fe09SDavid du Colombier 
317*5c47fe09SDavid du Colombier /*
3185d9de2d3SDavid du Colombier  * Get ARM ram
3195d9de2d3SDavid du Colombier  */
3205d9de2d3SDavid du Colombier void
getramsize(Confmem * mem)3215d9de2d3SDavid du Colombier getramsize(Confmem *mem)
3225d9de2d3SDavid du Colombier {
3235d9de2d3SDavid du Colombier 	u32int buf[2];
3245d9de2d3SDavid du Colombier 
3255d9de2d3SDavid du Colombier 	if(vcreq(TagGetram, buf, 0, sizeof buf) != sizeof buf)
3265d9de2d3SDavid du Colombier 		return;
3275d9de2d3SDavid du Colombier 	mem->base = buf[0];
3285d9de2d3SDavid du Colombier 	mem->limit = buf[1];
3295d9de2d3SDavid du Colombier }
3305d9de2d3SDavid du Colombier 
3315d9de2d3SDavid du Colombier /*
3325d9de2d3SDavid du Colombier  * Get clock rate
3335d9de2d3SDavid du Colombier  */
3345d9de2d3SDavid du Colombier ulong
getclkrate(int clkid)3355d9de2d3SDavid du Colombier getclkrate(int clkid)
3365d9de2d3SDavid du Colombier {
3375d9de2d3SDavid du Colombier 	u32int buf[2];
3385d9de2d3SDavid du Colombier 
3395d9de2d3SDavid du Colombier 	buf[0] = clkid;
3405d9de2d3SDavid du Colombier 	if(vcreq(TagGetclkspd, buf, sizeof(buf[0]), sizeof(buf)) != sizeof buf)
3415d9de2d3SDavid du Colombier 		return 0;
3425d9de2d3SDavid du Colombier 	return buf[1];
3435d9de2d3SDavid du Colombier }
344*5c47fe09SDavid du Colombier 
345*5c47fe09SDavid du Colombier /*
346*5c47fe09SDavid du Colombier  * Set clock rate to hz (or max speed if hz == 0)
347*5c47fe09SDavid du Colombier  */
348*5c47fe09SDavid du Colombier void
setclkrate(int clkid,ulong hz)349*5c47fe09SDavid du Colombier setclkrate(int clkid, ulong hz)
350*5c47fe09SDavid du Colombier {
351*5c47fe09SDavid du Colombier 	u32int buf[2];
352*5c47fe09SDavid du Colombier 
353*5c47fe09SDavid du Colombier 	buf[0] = clkid;
354*5c47fe09SDavid du Colombier 	if(hz != 0)
355*5c47fe09SDavid du Colombier 		buf[1] = hz;
356*5c47fe09SDavid du Colombier 	else if(vcreq(TagGetclkmax, buf, sizeof(buf[0]), sizeof(buf)) != sizeof buf)
357*5c47fe09SDavid du Colombier 		return;
358*5c47fe09SDavid du Colombier 	vcreq(TagSetclkspd, buf, sizeof(buf), sizeof(buf));
359*5c47fe09SDavid du Colombier }
360*5c47fe09SDavid du Colombier 
361*5c47fe09SDavid du Colombier /*
362*5c47fe09SDavid du Colombier  * Get cpu temperature
363*5c47fe09SDavid du Colombier  */
364*5c47fe09SDavid du Colombier uint
getcputemp(void)365*5c47fe09SDavid du Colombier getcputemp(void)
366*5c47fe09SDavid du Colombier {
367*5c47fe09SDavid du Colombier 	u32int buf[2];
368*5c47fe09SDavid du Colombier 
369*5c47fe09SDavid du Colombier 	buf[0] = 0;
370*5c47fe09SDavid du Colombier 	if(vcreq(TagGettemp, buf, sizeof(buf[0]), sizeof buf) != sizeof buf)
371*5c47fe09SDavid du Colombier 		return 0;
372*5c47fe09SDavid du Colombier 	return buf[1];
373*5c47fe09SDavid du Colombier }
374*5c47fe09SDavid du Colombier 
375*5c47fe09SDavid du Colombier /*
376*5c47fe09SDavid du Colombier  * Notify gpu that xhci firmware might need loading. This is for some
377*5c47fe09SDavid du Colombier  * pi4 board versions which are missing the eeprom chip for the vl805,
378*5c47fe09SDavid du Colombier  * requiring its firmware to come from the boot eeprom instead.
379*5c47fe09SDavid du Colombier  */
380*5c47fe09SDavid du Colombier int
xhcireset(int devaddr)381*5c47fe09SDavid du Colombier xhcireset(int devaddr)
382*5c47fe09SDavid du Colombier {
383*5c47fe09SDavid du Colombier 	u32int buf[1];
384*5c47fe09SDavid du Colombier 
385*5c47fe09SDavid du Colombier 	buf[0] = devaddr;
386*5c47fe09SDavid du Colombier 	if(vcreq(TagXhciReset, buf, sizeof(buf), sizeof(buf[0])) == sizeof(buf[0]))
387*5c47fe09SDavid du Colombier 		return buf[0];
388*5c47fe09SDavid du Colombier 	return -1;
389*5c47fe09SDavid du Colombier }
390*5c47fe09SDavid du Colombier 
391*5c47fe09SDavid du Colombier /*
392*5c47fe09SDavid du Colombier  * Virtual GPIO - used for ACT LED on pi3
393*5c47fe09SDavid du Colombier  */
394*5c47fe09SDavid du Colombier void
vgpinit(void)395*5c47fe09SDavid du Colombier vgpinit(void)
396*5c47fe09SDavid du Colombier {
397*5c47fe09SDavid du Colombier 	u32int buf[1];
398*5c47fe09SDavid du Colombier 	uintptr va;
399*5c47fe09SDavid du Colombier 
400*5c47fe09SDavid du Colombier 	buf[0] = 0;
401*5c47fe09SDavid du Colombier 	if(vcreq(TagGetGpio, buf, 0, sizeof(buf)) != sizeof buf || buf[0] == 0)
402*5c47fe09SDavid du Colombier 		return;
403*5c47fe09SDavid du Colombier 	va = mmukmap(VGPIO, buf[0] & ~0xC0000000, BY2PG);
404*5c47fe09SDavid du Colombier 	if(va == 0)
405*5c47fe09SDavid du Colombier 		return;
406*5c47fe09SDavid du Colombier 	vgpio.counts = (u32int*)va;
407*5c47fe09SDavid du Colombier }
408*5c47fe09SDavid du Colombier 
409*5c47fe09SDavid du Colombier void
vgpset(uint port,int on)410*5c47fe09SDavid du Colombier vgpset(uint port, int on)
411*5c47fe09SDavid du Colombier {
412*5c47fe09SDavid du Colombier 	if(vgpio.counts == nil || port >= Nvgpio || on == vgpio.ison)
413*5c47fe09SDavid du Colombier 		return;
414*5c47fe09SDavid du Colombier 	if(on)
415*5c47fe09SDavid du Colombier 		vgpio.incs++;
416*5c47fe09SDavid du Colombier 	else
417*5c47fe09SDavid du Colombier 		vgpio.decs++;
418*5c47fe09SDavid du Colombier 	vgpio.counts[port] = (vgpio.incs << 16) | vgpio.decs;
419*5c47fe09SDavid du Colombier 	vgpio.ison = on;
420*5c47fe09SDavid du Colombier }
421