bcm64: add pci express driver for raspberry pi 4
This commit is contained in:
parent
676ef0ca0b
commit
6d9edeeb67
4 changed files with 1207 additions and 20 deletions
|
@ -24,6 +24,7 @@ typedef struct MMMU MMMU;
|
|||
typedef struct Mach Mach;
|
||||
typedef struct Page Page;
|
||||
typedef struct PhysUart PhysUart;
|
||||
typedef struct Pcidev Pcidev;
|
||||
typedef struct PMMU PMMU;
|
||||
typedef struct Proc Proc;
|
||||
typedef u64int PTE;
|
||||
|
@ -33,6 +34,7 @@ typedef struct Ureg Ureg;
|
|||
typedef uvlong Tval;
|
||||
typedef void KMap;
|
||||
|
||||
#pragma incomplete Pcidev
|
||||
#pragma incomplete Ureg
|
||||
|
||||
#define MAXSYSARG 5 /* for mount(fd, mpt, flag, arg, srv) */
|
||||
|
|
|
@ -68,6 +68,8 @@ extern void kmapinval(void);
|
|||
extern KMap *kmap(Page*);
|
||||
extern void kunmap(KMap*);
|
||||
extern uintptr mmukmap(uintptr, uintptr, usize);
|
||||
extern void* vmap(uintptr, int);
|
||||
extern void vunmap(void*, int);
|
||||
|
||||
extern void mmu0init(uintptr*);
|
||||
extern void mmu0clear(uintptr*);
|
||||
|
@ -173,3 +175,29 @@ extern void writeconf(void);
|
|||
extern void screeninit(void);
|
||||
|
||||
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);
|
||||
|
|
|
@ -26,46 +26,56 @@ mmu0init(uintptr *l1)
|
|||
l1[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | attr;
|
||||
l1[PTL1X(pa, 1)] = pa | PTEVALID | PTEBLOCK | attr;
|
||||
}
|
||||
pe = (uintptr)-KZERO; /* populate top levels for mmukmap() */
|
||||
if(PTLEVELS > 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;
|
||||
for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(2), va += PGLSZ(2))
|
||||
l1[PTL1X(pa, 2)] = (uintptr)&l1[L1TABLEX(pa, 1)] | PTEVALID | PTETABLE;
|
||||
}
|
||||
if(PTLEVELS > 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;
|
||||
for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3))
|
||||
l1[PTL1X(pa, 3)] = (uintptr)&l1[L1TABLEX(pa, 2)] | PTEVALID | PTETABLE;
|
||||
}
|
||||
|
||||
/* VIRTIO */
|
||||
attr = PTEWRITE | PTEAF | PTEKERNEL | PTESH(SHARE_OUTER) | PTEDEVICE;
|
||||
pe = soc.physio + IOSIZE;
|
||||
for(pa = soc.physio, va = VIRTIO; pa < pe; pa += PGLSZ(1), va += PGLSZ(1)){
|
||||
if(pe - pa < PGLSZ(1)){
|
||||
pe = soc.physio + soc.iosize;
|
||||
for(pa = soc.physio, va = soc.virtio; 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; 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;
|
||||
}
|
||||
break;
|
||||
}
|
||||
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 */
|
||||
attr = PTEWRITE | PTEAF | PTEKERNEL | PTESH(SHARE_OUTER) | PTEDEVICE;
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -107,6 +117,7 @@ mmuidmap(uintptr *l1)
|
|||
for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3))
|
||||
l1[PTL1X(pa, 3)] = l1[PTL1X(va, 3)];
|
||||
setttbr(PADDR(&l1[L1TABLEX(0, PTLEVELS-1)]));
|
||||
flushtlb();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -184,6 +195,23 @@ mmukmap(uintptr va, uintptr pa, usize size)
|
|||
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*
|
||||
mmuwalk(uintptr va, int level)
|
||||
{
|
||||
|
|
1129
sys/src/9/bcm64/pci.c
Normal file
1129
sys/src/9/bcm64/pci.c
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue