Plan 9 from Bell Labs’s /usr/web/sources/contrib/kws/v3d/poke.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#include <u.h>
#include <libc.h>
#include <stdio.h>

#define V3D_SET_FIELD(v, s, m)	(((v)<<(s)) & (m))

typedef struct Bo	Bo;

struct Bo {
	ulong	off;
	ulong	size;
	u32int	*base;
};

enum {
	V3D_HUB_IDENT0		= 0x08>>2,
	V3D_HUB_IDENT1		= 0x0c>>2,

	V3D_CTL_L2TFLSTA	= 0x34>>2,
	V3D_CTL_L2TFLEND	= 0x38>>2,

	V3D_MMU_CTL		= 0x1200>>2,
		V3D_MMU_CTL_TLB_CLEAR			= 1<<2,
		V3D_MMU_CTL_TLB_CLEARING		= 1<<7,
		V3D_MMU_CTL_ENABLE			= 1<<0,
		V3D_MMU_CTL_PT_INVALID_ENABLE		= 1<<16,
		V3D_MMU_CTL_PT_INVALID_ABORT		= 1<<19,
		V3D_MMU_CTL_PT_INVALID_INT		= 1<<18,
		V3D_MMU_CTL_WRITE_VIOLATION_ABORT	= 1<<11,
		V3D_MMU_CTL_WRITE_VIOLATION_INT		= 1<<10,
		V3D_MMU_CTL_CAP_EXCEEDED_ABORT		= 1<<26,
		V3D_MMU_CTL_CAP_EXCEEDED_INT		= 1<<25,
	V3D_MMU_ILLEGAL_ADDR	= 0x1230>>2,
		V3D_MMU_ILLEGAL_ADDR_ENABLE = 1<<31,

	V3D_MMUC_CONTROL	= 0x1000>>2,
		V3D_MMUC_CONTROL_FLUSHING	= 1<<2,
		V3D_MMUC_CONTROL_FLUSH		= 1<<1,
		V3D_MMUC_CONTROL_ENABLE		= 1<<0,
	V3D_MMU_PT_PA_BASE	= 0x1204>>2,

	V3D_CSD_QUEUED_CFG	= 0x904>>2,

	V3D_CSD_STATUS		= 0x900>>2,

	V3D_PTE_WRITEABLE	= 1<<29,
	V3D_PTE_VALID		= 1<<28,

	V3D_PAGE_SHIFT		= 12,
	V3D_PAGE_SIZE		= 1<<V3D_PAGE_SHIFT,

	V3D_CTL_L2TCACTL = 0x00030>>2,
		V3D_L2TCACTL_TMUWCF	= 1<<8,
		V3D_L2TCACTL_L2TFLS	= 1<<0,
		V3D_L2TCACTL_FLM_FLUSH	= 0,
		V3D_L2TCACTL_FLM_CLEAN	= 2,
		V3D_L2TCACTL_FLM_MASK	= 0xFFFFFFFEUL,
		V3D_L2TCACTL_FLM_SHIFT	= 1,
};

enum {
	WgX = 16,
	WgY = 1,
	WgZ = 1,
	Wgsize = WgX * WgY * WgZ,
	Wgspersg = 16,
};

/* Example program that uses 1 QPU to initialize buffer from 0...127 */
static uvlong	pgm[] = {
	0x3d907186bb800000,
	0x3d90b186bb800000,
	0x3de031827d83a004,
	0x3c003180bb802000,
	0x3de031807c838002,
	0x3c00318138801000,
	0x3de031837c83f004,
	0x3c003180bb802000,
	0x3c00318bb6800000,
	0x3c00318cb6809000,
	0x3c003186bb815000,
	0x3c00318138819000,
	0x3de031803c838010,
	0x3de071823c83a001,
	0x02ffffb3ff009000,
	0x3c003186bb800000,
	0x3c003186bb800000,
	0x3c003186bb800000,
	0x3c203186bb800000,
	0x3c203186bb800000,
	0x3c003186bb800000,
	0x3c003186bb800000,
	0x3c203186bb800000,
	0x3c003186bb800000,
	0x3c003186bb800000,
	0x3c003186bb800000,
};

static u32int	*hub;
static u32int	*core;
static u32int	*pt;

void
coherence(void)
{
	hub[V3D_MMU_CTL] |= V3D_MMU_CTL_TLB_CLEAR;
	hub[V3D_MMUC_CONTROL] = V3D_MMUC_CONTROL_FLUSH | V3D_MMUC_CONTROL_ENABLE;
	while(hub[V3D_MMU_CTL] & V3D_MMU_CTL_TLB_CLEARING)
		;
	while(hub[V3D_MMUC_CONTROL] & V3D_MMUC_CONTROL_FLUSHING)
		;
}

Bo *
readbo(char *name)
{
	int fd;
	char buf[100];
	Bo *bo = malloc(sizeof(Bo));

	sprint(buf, "v3d%s", name);
	bo->base = segattach(0, buf, 0, 0);
	if(bo->base == (void *)-1)
		sysfatal("segattach %s failed: %r", name);

	sprint(buf, "#g/v3d%s/ctl", name);
	fd = open(buf, OREAD);
	if(fd < 0)
		sysfatal("open failed: %r");
	if(read(fd, buf, sizeof(buf)) <= 0)
		sysfatal("read failed: %r");
	sscanf(buf, "va %lx %lx fixed %lx", &bo->off, &bo->size, &bo->off);
	return bo;
}

void
mapbo(u32int addr, Bo *bo)
{
	u32int i;
	u32int npages = bo->size >> V3D_PAGE_SHIFT;
	u32int *base = &pt[addr >> V3D_PAGE_SHIFT];
	u32int off = bo->off >> V3D_PAGE_SHIFT;

	for(i = 0; i < npages; i++)
		base[i] = V3D_PTE_VALID | V3D_PTE_WRITEABLE | (off + i);
	coherence();
}

void
main()
{
	Bo *mmu, *code, *bo, *unif;
	char buf[32];
	int donefd;

	hub = segattach(0, "v3d", nil, 0x8000);
	if(hub == (void *)-1)
		sysfatal("segattach failed: %r");
	core = hub + (0x4000>>2);
	if(hub[V3D_HUB_IDENT0] != 0x42554856)
		sysfatal("videocore fell off");

	core[V3D_CTL_L2TFLSTA] = 0;
	core[V3D_CTL_L2TFLEND] = ~0;

	donefd = open("#β/done", OREAD);
	if(donefd < 0)
		sysfatal("open failed: %r");

	mmu = readbo("mmu");
	pt = mmu->base;
	code = readbo("code");
	bo = readbo("bo");
	unif = readbo("unif");

	hub[V3D_MMU_PT_PA_BASE] = mmu->off >> V3D_PAGE_SHIFT;
	hub[V3D_MMU_CTL] = V3D_MMU_CTL_ENABLE | V3D_MMU_CTL_PT_INVALID_ENABLE | V3D_MMU_CTL_PT_INVALID_ABORT | V3D_MMU_CTL_PT_INVALID_INT | V3D_MMU_CTL_WRITE_VIOLATION_ABORT | V3D_MMU_CTL_WRITE_VIOLATION_INT | V3D_MMU_CTL_CAP_EXCEEDED_ABORT | V3D_MMU_CTL_CAP_EXCEEDED_INT;
	hub[V3D_MMU_ILLEGAL_ADDR] = ((mmu->off + 0x400000) >> V3D_PAGE_SHIFT) | V3D_MMU_ILLEGAL_ADDR_ENABLE;
	hub[V3D_MMUC_CONTROL] = V3D_MMUC_CONTROL_ENABLE;
	coherence();

	/* These addresses are chosen arbitrarily for now - we could have done 1:1 as well */
	u32int codeaddr = 0x4200<<V3D_PAGE_SHIFT;
	mapbo(codeaddr, code);
	u32int boaddr = 0x4300<<V3D_PAGE_SHIFT;
	mapbo(boaddr, bo);
	u32int unifaddr = 0x4400<<V3D_PAGE_SHIFT;
	mapbo(unifaddr, unif);

	unif->base[0] = boaddr;
	unif->base[1] = 128;

	memcpy(code->base, pgm, sizeof(pgm));

	/* Clear cache beforehand */
	core[V3D_CTL_L2TCACTL] = V3D_L2TCACTL_L2TFLS | V3D_SET_FIELD(V3D_L2TCACTL_FLM_FLUSH, V3D_L2TCACTL_FLM_SHIFT, V3D_L2TCACTL_FLM_MASK);

	core[V3D_CSD_QUEUED_CFG+1] = WgY << 16;
	core[V3D_CSD_QUEUED_CFG+2] = WgZ << 16;
	core[V3D_CSD_QUEUED_CFG+3] = ((((Wgspersg * Wgsize + 15) / 16) - 1) << 12) | (Wgspersg << 8) | (Wgsize & 0xff);
	core[V3D_CSD_QUEUED_CFG+4] = 0;
	core[V3D_CSD_QUEUED_CFG+5] = codeaddr;
	core[V3D_CSD_QUEUED_CFG+6] = unifaddr;
	core[V3D_CSD_QUEUED_CFG+0] = WgX << 16;	/* Kicks off */

	/* Barrier */
	read(donefd, buf, sizeof(buf));

	/* Flush TMU */
	core[V3D_CTL_L2TCACTL] = V3D_L2TCACTL_TMUWCF;
	while(core[V3D_CTL_L2TCACTL] & V3D_L2TCACTL_TMUWCF)
		;
	core[V3D_CTL_L2TCACTL] = V3D_L2TCACTL_L2TFLS | V3D_SET_FIELD(V3D_L2TCACTL_FLM_CLEAN, V3D_L2TCACTL_FLM_SHIFT, V3D_L2TCACTL_FLM_MASK);
	while(core[V3D_CTL_L2TCACTL] & V3D_L2TCACTL_L2TFLS)
		;

	for(int i = 0; i < 128; i++){
		print("%d ", bo->base[i]);
	}
	print("\n");

	exits(nil);
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.