bcm64: add pci express driver for raspberry pi 4

This commit is contained in:
cinap_lenrek 2019-07-25 09:04:50 +02:00
parent 676ef0ca0b
commit 6d9edeeb67
4 changed files with 1207 additions and 20 deletions

View file

@ -24,6 +24,7 @@ typedef struct MMMU MMMU;
typedef struct Mach Mach; typedef struct Mach Mach;
typedef struct Page Page; typedef struct Page Page;
typedef struct PhysUart PhysUart; typedef struct PhysUart PhysUart;
typedef struct Pcidev Pcidev;
typedef struct PMMU PMMU; typedef struct PMMU PMMU;
typedef struct Proc Proc; typedef struct Proc Proc;
typedef u64int PTE; typedef u64int PTE;
@ -33,6 +34,7 @@ typedef struct Ureg Ureg;
typedef uvlong Tval; typedef uvlong Tval;
typedef void KMap; typedef void KMap;
#pragma incomplete Pcidev
#pragma incomplete Ureg #pragma incomplete Ureg
#define MAXSYSARG 5 /* for mount(fd, mpt, flag, arg, srv) */ #define MAXSYSARG 5 /* for mount(fd, mpt, flag, arg, srv) */

View file

@ -68,6 +68,8 @@ extern void kmapinval(void);
extern KMap *kmap(Page*); extern KMap *kmap(Page*);
extern void kunmap(KMap*); extern void kunmap(KMap*);
extern uintptr mmukmap(uintptr, uintptr, usize); extern uintptr mmukmap(uintptr, uintptr, usize);
extern void* vmap(uintptr, int);
extern void vunmap(void*, int);
extern void mmu0init(uintptr*); extern void mmu0init(uintptr*);
extern void mmu0clear(uintptr*); extern void mmu0clear(uintptr*);
@ -173,3 +175,29 @@ extern void writeconf(void);
extern void screeninit(void); extern void screeninit(void);
extern int isaconfig(char*, int, ISAConf*); extern int isaconfig(char*, int, ISAConf*);
/* pci */
typedef struct Pcidev Pcidev;
extern int pcicfgr32(Pcidev* pcidev, int rno);
extern void pcicfgw32(Pcidev* pcidev, int rno, int data);
extern int pcicfgr16(Pcidev* pcidev, int rno);
extern void pcicfgw16(Pcidev* pcidev, int rno, int data);
extern int pcicfgr8(Pcidev* pcidev, int rno);
extern void pcicfgw8(Pcidev* pcidev, int rno, int data);
extern Pcidev* pcimatch(Pcidev* prev, int vid, int did);
extern Pcidev* pcimatchtbdf(int tbdf);
extern void pcisetioe(Pcidev* p);
extern void pciclrioe(Pcidev* p);
extern void pcisetbme(Pcidev* p);
extern void pciclrbme(Pcidev* p);
extern void pcisetmwi(Pcidev* p);
extern void pciclrmwi(Pcidev* p);
extern int pcicap(Pcidev *p, int cap);
extern int pcinextcap(Pcidev *pci, int offset);
extern int pcihtcap(Pcidev *p, int cap);
extern int pcigetpms(Pcidev* p);
extern int pcisetpms(Pcidev* p, int state);
extern void pcienable(Pcidev *p);
extern void pcidisable(Pcidev *p);
extern void pciintrenable(int tbdf, void (*f)(Ureg*, void*), void *a);
extern void pciintrdisable(int tbdf, void (*f)(Ureg*, void*), void *a);

View file

@ -26,46 +26,56 @@ mmu0init(uintptr *l1)
l1[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | attr; l1[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | attr;
l1[PTL1X(pa, 1)] = pa | PTEVALID | PTEBLOCK | attr; l1[PTL1X(pa, 1)] = pa | PTEVALID | PTEBLOCK | attr;
} }
pe = (uintptr)-KZERO; /* populate top levels for mmukmap() */
if(PTLEVELS > 2) if(PTLEVELS > 2)
for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(2), va += PGLSZ(2)){ for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(2), va += PGLSZ(2))
l1[PTL1X(va, 2)] = (uintptr)&l1[L1TABLEX(va, 1)] | PTEVALID | PTETABLE;
l1[PTL1X(pa, 2)] = (uintptr)&l1[L1TABLEX(pa, 1)] | PTEVALID | PTETABLE; l1[PTL1X(pa, 2)] = (uintptr)&l1[L1TABLEX(pa, 1)] | PTEVALID | PTETABLE;
}
if(PTLEVELS > 3) if(PTLEVELS > 3)
for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3)){ for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3))
l1[PTL1X(va, 3)] = (uintptr)&l1[L1TABLEX(va, 2)] | PTEVALID | PTETABLE;
l1[PTL1X(pa, 3)] = (uintptr)&l1[L1TABLEX(pa, 2)] | PTEVALID | PTETABLE; l1[PTL1X(pa, 3)] = (uintptr)&l1[L1TABLEX(pa, 2)] | PTEVALID | PTETABLE;
}
/* VIRTIO */ /* VIRTIO */
attr = PTEWRITE | PTEAF | PTEKERNEL | PTESH(SHARE_OUTER) | PTEDEVICE; attr = PTEWRITE | PTEAF | PTEKERNEL | PTESH(SHARE_OUTER) | PTEDEVICE;
pe = soc.physio + IOSIZE; pe = soc.physio + soc.iosize;
for(pa = soc.physio, va = VIRTIO; pa < pe; pa += PGLSZ(1), va += PGLSZ(1)){ for(pa = soc.physio, va = soc.virtio; pa < pe; pa += PGLSZ(1), va += PGLSZ(1)){
if(pe - pa < PGLSZ(1)){ if(((pa|va) & PGLSZ(1)-1) != 0){
l1[PTL1X(va, 1)] = (uintptr)l1 | PTEVALID | PTETABLE; l1[PTL1X(va, 1)] = (uintptr)l1 | PTEVALID | PTETABLE;
for(; pa < pe; pa += PGLSZ(0), va += PGLSZ(0)) for(; pa < pe && ((va|pa) & PGLSZ(1)-1) != 0; pa += PGLSZ(0), va += PGLSZ(0)){
assert(l1[PTLX(va, 0)] == 0);
l1[PTLX(va, 0)] = pa | PTEVALID | PTEPAGE | attr; l1[PTLX(va, 0)] = pa | PTEVALID | PTEPAGE | attr;
}
break; break;
} }
l1[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | attr; l1[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | attr;
} }
if(PTLEVELS > 2)
for(pa = soc.physio, va = VIRTIO; pa < pe; pa += PGLSZ(2), va += PGLSZ(2))
l1[PTL1X(va, 2)] = (uintptr)&l1[L1TABLEX(va, 1)] | PTEVALID | PTETABLE;
if(PTLEVELS > 3)
for(pa = soc.physio, va = VIRTIO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3))
l1[PTL1X(va, 3)] = (uintptr)&l1[L1TABLEX(va, 2)] | PTEVALID | PTETABLE;
/* ARMLOCAL */ /* ARMLOCAL */
attr = PTEWRITE | PTEAF | PTEKERNEL | PTESH(SHARE_OUTER) | PTEDEVICE;
pe = soc.armlocal + MB; pe = soc.armlocal + MB;
for(pa = soc.armlocal, va = ARMLOCAL; pa < pe; pa += PGLSZ(1), va += PGLSZ(1)) for(pa = soc.armlocal, va = ARMLOCAL; pa < pe; pa += PGLSZ(1), va += PGLSZ(1)){
if(((pa|va) & PGLSZ(1)-1) != 0){
l1[PTL1X(va, 1)] = (uintptr)l1 | PTEVALID | PTETABLE;
for(; pa < pe && ((va|pa) & PGLSZ(1)-1) != 0; pa += PGLSZ(0), va += PGLSZ(0)){
assert(l1[PTLX(va, 0)] == 0);
l1[PTLX(va, 0)] = pa | PTEVALID | PTEPAGE | attr;
}
break;
}
l1[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | attr; l1[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | attr;
}
/* VIRTPCI */
if(soc.pciwin){
attr = PTEWRITE | PTEAF | PTEKERNEL | PTESH(SHARE_OUTER) | PTEDEVICE;
pe = soc.pciwin + 512*MB;
for(pa = soc.pciwin, va = VIRTPCI; pa < pe; pa += PGLSZ(1), va += PGLSZ(1))
l1[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | attr;
}
if(PTLEVELS > 2) if(PTLEVELS > 2)
for(pa = soc.armlocal, va = ARMLOCAL; pa < pe; pa += PGLSZ(2), va += PGLSZ(2)) for(va = KSEG0; va != 0; va += PGLSZ(2))
l1[PTL1X(va, 2)] = (uintptr)&l1[L1TABLEX(va, 1)] | PTEVALID | PTETABLE; l1[PTL1X(va, 2)] = (uintptr)&l1[L1TABLEX(va, 1)] | PTEVALID | PTETABLE;
if(PTLEVELS > 3) if(PTLEVELS > 3)
for(pa = soc.armlocal, va = ARMLOCAL; pa < pe; pa += PGLSZ(3), va += PGLSZ(3)) for(va = KSEG0; va != 0; va += PGLSZ(3))
l1[PTL1X(va, 3)] = (uintptr)&l1[L1TABLEX(va, 2)] | PTEVALID | PTETABLE; l1[PTL1X(va, 3)] = (uintptr)&l1[L1TABLEX(va, 2)] | PTEVALID | PTETABLE;
} }
@ -107,6 +117,7 @@ mmuidmap(uintptr *l1)
for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3)) for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3))
l1[PTL1X(pa, 3)] = l1[PTL1X(va, 3)]; l1[PTL1X(pa, 3)] = l1[PTL1X(va, 3)];
setttbr(PADDR(&l1[L1TABLEX(0, PTLEVELS-1)])); setttbr(PADDR(&l1[L1TABLEX(0, PTLEVELS-1)]));
flushtlb();
} }
void void
@ -184,6 +195,23 @@ mmukmap(uintptr va, uintptr pa, usize size)
return a; return a;
} }
void*
vmap(uintptr pa, int)
{
if(soc.pciwin && pa >= soc.pciwin)
return (void*)(VIRTPCI + (pa - soc.pciwin));
if(soc.armlocal && pa >= soc.armlocal)
return (void*)(ARMLOCAL + (pa - soc.armlocal));
if(soc.physio && pa >= soc.physio)
return (void*)(soc.virtio + (pa - soc.physio));
return nil;
}
void
vunmap(void *, int)
{
}
static uintptr* static uintptr*
mmuwalk(uintptr va, int level) mmuwalk(uintptr va, int level)
{ {

1129
sys/src/9/bcm64/pci.c Normal file

File diff suppressed because it is too large Load diff