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).
This commit is contained in:
parent
0e381493bf
commit
efcfdd23d7
4 changed files with 43 additions and 15 deletions
|
@ -12,6 +12,7 @@ static char *confname[MAXCONF];
|
||||||
static char *confval[MAXCONF];
|
static char *confval[MAXCONF];
|
||||||
static int nconf;
|
static int nconf;
|
||||||
static char maxmem[256];
|
static char maxmem[256];
|
||||||
|
static char pciwin[38], pcidmawin[38];
|
||||||
|
|
||||||
static int
|
static int
|
||||||
findconf(char *k)
|
findconf(char *k)
|
||||||
|
@ -89,23 +90,23 @@ beget4(uchar *p)
|
||||||
static void
|
static void
|
||||||
devtreeprop(char *path, char *key, void *val, int len)
|
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)
|
if((strcmp(path, "/memory") == 0 || strcmp(path, "/memory@0") == 0)
|
||||||
&& strcmp(key, "reg") == 0){
|
&& strcmp(key, "reg") == 0){
|
||||||
if(findconf("*maxmem") < 0 && len > 0 && (len % (3*4)) == 0){
|
if(findconf("*maxmem") < 0 && len > 0 && (len % (3*4)) == 0){
|
||||||
uvlong top;
|
addr = (uvlong)beget4(p)<<32 | beget4(p+4);
|
||||||
uchar *p = val;
|
addr += beget4(p+8);
|
||||||
char *s;
|
s = seprint(maxmem, &maxmem[sizeof(maxmem)], "%#llux", addr);
|
||||||
|
|
||||||
top = (uvlong)beget4(p)<<32 | beget4(p+4);
|
|
||||||
top += beget4(p+8);
|
|
||||||
s = seprint(maxmem, &maxmem[sizeof(maxmem)], "%#llux", top);
|
|
||||||
p += 3*4;
|
p += 3*4;
|
||||||
len -= 3*4;
|
len -= 3*4;
|
||||||
while(len > 0){
|
while(len > 0){
|
||||||
top = (uvlong)beget4(p)<<32 | beget4(p+4);
|
addr = (uvlong)beget4(p)<<32 | beget4(p+4);
|
||||||
s = seprint(s, &maxmem[sizeof(maxmem)], " %#llux", top);
|
s = seprint(s, &maxmem[sizeof(maxmem)], " %#llux", addr);
|
||||||
top += beget4(p+8);
|
addr += beget4(p+8);
|
||||||
s = seprint(s, &maxmem[sizeof(maxmem)], " %#llux", top);
|
s = seprint(s, &maxmem[sizeof(maxmem)], " %#llux", addr);
|
||||||
p += 3*4;
|
p += 3*4;
|
||||||
len -= 3*4;
|
len -= 3*4;
|
||||||
}
|
}
|
||||||
|
@ -113,6 +114,22 @@ devtreeprop(char *path, char *key, void *val, int len)
|
||||||
}
|
}
|
||||||
return;
|
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;
|
||||||
|
}
|
||||||
if(strcmp(path, "/chosen") == 0 && strcmp(key, "bootargs") == 0){
|
if(strcmp(path, "/chosen") == 0 && strcmp(key, "bootargs") == 0){
|
||||||
if(len > BOOTARGSLEN)
|
if(len > BOOTARGSLEN)
|
||||||
len = BOOTARGSLEN;
|
len = BOOTARGSLEN;
|
||||||
|
|
|
@ -249,7 +249,8 @@ struct Soc { /* SoC dependent configuration */
|
||||||
uintptr physio;
|
uintptr physio;
|
||||||
uintptr virtio;
|
uintptr virtio;
|
||||||
uintptr armlocal;
|
uintptr armlocal;
|
||||||
uintptr pciwin;
|
uintptr pciwin; /* PCI outbound window CPU->PCI */
|
||||||
|
uintptr pcidmawin; /* PCI inbound window PCI->DRAM */
|
||||||
int oscfreq;
|
int oscfreq;
|
||||||
};
|
};
|
||||||
extern Soc soc;
|
extern Soc soc;
|
||||||
|
|
|
@ -6,5 +6,5 @@ enum {
|
||||||
IRQether = IRQgic + 29,
|
IRQether = IRQgic + 29,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PCIWINDOW 0
|
#define PCIWINDOW soc.pcidmawin
|
||||||
#define PCIWADDR(va) (PADDR(va)+PCIWINDOW)
|
#define PCIWADDR(va) (PADDR(va)+PCIWINDOW)
|
||||||
|
|
|
@ -244,6 +244,16 @@ void
|
||||||
pcibcmlink(void)
|
pcibcmlink(void)
|
||||||
{
|
{
|
||||||
int log2dmasize = 30; // 1GB
|
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;
|
regs[RGR1_SW_INIT_1] |= 3;
|
||||||
delay(200);
|
delay(200);
|
||||||
|
@ -266,8 +276,8 @@ pcibcmlink(void)
|
||||||
// SCB_ACCESS_EN, CFG_READ_UR_MODE, MAX_BURST_SIZE_128, SCB0SIZE
|
// 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_MISC_CTRL] = 1<<12 | 1<<13 | 0<<20 | (log2dmasize-15)<<27;
|
||||||
|
|
||||||
regs[MISC_RC_BAR2_CONFIG_LO] = (log2dmasize-15);
|
regs[MISC_RC_BAR2_CONFIG_LO] = ((u32int)soc.pcidmawin & ~0x1F) | (log2dmasize-15);
|
||||||
regs[MISC_RC_BAR2_CONFIG_HI] = 0;
|
regs[MISC_RC_BAR2_CONFIG_HI] = soc.pcidmawin >> 32;
|
||||||
|
|
||||||
regs[MISC_RC_BAR1_CONFIG_LO] = 0;
|
regs[MISC_RC_BAR1_CONFIG_LO] = 0;
|
||||||
regs[MISC_RC_BAR3_CONFIG_LO] = 0;
|
regs[MISC_RC_BAR3_CONFIG_LO] = 0;
|
||||||
|
|
Loading…
Reference in a new issue