git: 9front

Download patch

ref: 7b161c903a593e1d04d5ee6777265a01485ce6cb
parent: 9d797f0aa54728d1d2de3eb1424b504f93962ccf
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Feb 6 08:47:45 EST 2021

bcm64: get inbound and outbound pci window base address from device tree

On the pi400, the xhci reset firmware mailbox request
assumes that the pci windows match the ones specified
in the device tree. The inbound window (pcidmawin)
also varies now depending on the amount of memory
installed.

It is all pretty ridiculous, as the firmware could as
well just read the pci controllers hardware register
to determine the window configuration and the os could
keep a nice simple 1:1 mapping (with pci dma addresses
== physical addresses).

--- a/sys/src/9/bcm/bootargs.c
+++ b/sys/src/9/bcm/bootargs.c
@@ -12,6 +12,7 @@
 static char *confval[MAXCONF];
 static int nconf;
 static char maxmem[256];
+static char pciwin[38], pcidmawin[38];
 
 static int
 findconf(char *k)
@@ -89,27 +90,43 @@
 static void
 devtreeprop(char *path, char *key, void *val, int len)
 {
+	uvlong addr, size;
+	uchar *p = val;
+	char *s;
+
 	if((strcmp(path, "/memory") == 0 || strcmp(path, "/memory@0") == 0)
 	&& strcmp(key, "reg") == 0){
 		if(findconf("*maxmem") < 0 && len > 0 && (len % (3*4)) == 0){
-			uvlong top;
-			uchar *p = val;
-			char *s;
-
-			top = (uvlong)beget4(p)<<32 | beget4(p+4);
-			top += beget4(p+8);
-			s = seprint(maxmem, &maxmem[sizeof(maxmem)], "%#llux", top);
+			addr = (uvlong)beget4(p)<<32 | beget4(p+4);
+			addr += beget4(p+8);
+			s = seprint(maxmem, &maxmem[sizeof(maxmem)], "%#llux", addr);
 			p += 3*4;
 			len -= 3*4;
 			while(len > 0){
-				top = (uvlong)beget4(p)<<32 | beget4(p+4);
-				s = seprint(s, &maxmem[sizeof(maxmem)], " %#llux", top);
-				top += beget4(p+8);
-				s = seprint(s, &maxmem[sizeof(maxmem)], " %#llux", top);
+				addr = (uvlong)beget4(p)<<32 | beget4(p+4);
+				s = seprint(s, &maxmem[sizeof(maxmem)], " %#llux", addr);
+				addr += beget4(p+8);
+				s = seprint(s, &maxmem[sizeof(maxmem)], " %#llux", addr);
 				p += 3*4;
 				len -= 3*4;
 			}
 			addconf("*maxmem", maxmem);
+		}
+		return;
+	}
+	if(strncmp(path, "/scb/pcie@", 10) == 0 && len == (3*4 + 4*4)){
+		if((beget4(p) & 0x3000000) == 0x2000000){
+			size = (uvlong)beget4(p+5*4)<<32 | beget4(p+5*4+4);
+			if(strcmp(key, "ranges") == 0 && findconf("*pciwin") < 0){
+				addr = (uvlong)beget4(p+3*4)<<32 | beget4(p+4*4);
+				snprint(pciwin, sizeof(pciwin), "%#llux %#llux", addr, addr+size);
+				addconf("*pciwin", pciwin);
+			} else if(strcmp(key, "dma-ranges") == 0 && findconf("*pcidmawin") < 0){
+				addr = (uvlong)beget4(p+1*4)<<32 | beget4(p+2*4);
+				addr -= (uvlong)beget4(p+3*4)<<32 | beget4(p+4*4);
+				snprint(pcidmawin, sizeof(pcidmawin), "%#llux %#llux", addr, addr+size);
+				addconf("*pcidmawin", pcidmawin);
+			}
 		}
 		return;
 	}
--- a/sys/src/9/bcm64/dat.h
+++ b/sys/src/9/bcm64/dat.h
@@ -249,7 +249,8 @@
 	uintptr	physio;
 	uintptr	virtio;
 	uintptr	armlocal;
-	uintptr	pciwin;
+	uintptr	pciwin;		/* PCI outbound window CPU->PCI */
+	uintptr	pcidmawin;	/* PCI inbound window PCI->DRAM */
 	int	oscfreq;
 };
 extern Soc soc;
--- a/sys/src/9/bcm64/io.h
+++ b/sys/src/9/bcm64/io.h
@@ -6,5 +6,5 @@
 	IRQether	= IRQgic + 29,
 };
 
-#define PCIWINDOW	0
+#define PCIWINDOW	soc.pcidmawin
 #define PCIWADDR(va)	(PADDR(va)+PCIWINDOW)
--- a/sys/src/9/bcm64/pcibcm.c
+++ b/sys/src/9/bcm64/pcibcm.c
@@ -244,7 +244,17 @@
 pcibcmlink(void)
 {
 	int log2dmasize = 30;	// 1GB
+	char *s;
 
+	if((s = getconf("*pciwin")) != nil){
+		print("*pciwin: %s\n", s);
+		soc.pciwin = (uintptr)strtoll(s, nil, 16);
+	}
+	if((s = getconf("*pcidmawin")) != nil){
+		print("*pcidmawin: %s\n", s);
+		soc.pcidmawin = (uintptr)strtoll(s, nil, 16);
+	}
+
 	regs[RGR1_SW_INIT_1] |= 3;
 	delay(200);
 	regs[RGR1_SW_INIT_1] &= ~2;
@@ -266,8 +276,8 @@
 	// SCB_ACCESS_EN, CFG_READ_UR_MODE, MAX_BURST_SIZE_128, SCB0SIZE
 	regs[MISC_MISC_CTRL] = 1<<12 | 1<<13 | 0<<20 | (log2dmasize-15)<<27;
 
-	regs[MISC_RC_BAR2_CONFIG_LO] = (log2dmasize-15);
-	regs[MISC_RC_BAR2_CONFIG_HI] = 0;
+	regs[MISC_RC_BAR2_CONFIG_LO] = ((u32int)soc.pcidmawin & ~0x1F) | (log2dmasize-15);
+	regs[MISC_RC_BAR2_CONFIG_HI] = soc.pcidmawin >> 32;
 
 	regs[MISC_RC_BAR1_CONFIG_LO] = 0;
 	regs[MISC_RC_BAR3_CONFIG_LO] = 0;
--