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;
--
⑨