shithub: riscv

Download patch

ref: efcfdd23d72178ed873982f957cbc95b2a1de4c5
parent: 0e381493bfa4963c406cd6340ddcc0e43a4808e2
author: cinap_lenrek <[email protected]>
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;