imx8: pcie and nvme support

This commit is contained in:
cinap_lenrek 2022-07-03 11:36:50 +00:00
parent e39d924907
commit 548a48d156
8 changed files with 635 additions and 2 deletions

View file

@ -1075,6 +1075,90 @@ enablepll(int input)
} }
} }
enum {
CCM_ANALOG_PLLOUT_MONITOR_CFG = 0x74/4,
PLLOUT_MONITOR_CLK_CKE = 1<<4,
CCM_ANALOG_FRAC_PLLOUT_DIV_CFG = 0x78/4,
CCM_ANALOG_SCCG_PLLOUT_DIV_CFG = 0x7C/4,
};
static struct {
uchar input;
uchar reg; /* divider register */
uchar shift; /* divider shift */
} anapllout_input[16] = {
[0] OSC_25M_REF_CLK,
[1] OSC_27M_REF_CLK,
/* [2] HDMI_PHY_27M_CLK */
/* [3] CLK1_P_N */
[4] OSC_32K_REF_CLK,
[5] AUDIO_PLL1_CLK, CCM_ANALOG_FRAC_PLLOUT_DIV_CFG, 0,
[6] AUDIO_PLL2_CLK, CCM_ANALOG_FRAC_PLLOUT_DIV_CFG, 4,
[7] GPU_PLL_CLK, CCM_ANALOG_FRAC_PLLOUT_DIV_CFG, 12,
[8] VPU_PLL_CLK, CCM_ANALOG_FRAC_PLLOUT_DIV_CFG, 16,
[9] VIDEO_PLL1_CLK, CCM_ANALOG_FRAC_PLLOUT_DIV_CFG, 8,
[10] ARM_PLL_CLK, CCM_ANALOG_FRAC_PLLOUT_DIV_CFG, 20,
[11] SYSTEM_PLL1_CLK, CCM_ANALOG_SCCG_PLLOUT_DIV_CFG, 0,
[12] SYSTEM_PLL2_CLK, CCM_ANALOG_SCCG_PLLOUT_DIV_CFG, 4,
[13] SYSTEM_PLL3_CLK, CCM_ANALOG_SCCG_PLLOUT_DIV_CFG, 8,
[14] VIDEO_PLL2_CLK, CCM_ANALOG_SCCG_PLLOUT_DIV_CFG, 16,
[15] DRAM_PLL1_CLK, CCM_ANALOG_SCCG_PLLOUT_DIV_CFG, 12,
};
static void
setanapllout(int input, int freq)
{
int mux, div, reg;
for(mux = 0; mux < nelem(anapllout_input); mux++)
if(anapllout_input[mux].input == input)
goto Muxok;
panic("setanapllout: bad input clock\n");
return;
Muxok:
anatop[CCM_ANALOG_PLLOUT_MONITOR_CFG] = mux;
if(freq <= 0)
return;
div = input_clk_freq[input] / freq;
if(div < 1 || div > 8){
panic("setanapllout: divider out of range\n");
return;
}
enablepll(input);
reg = anapllout_input[mux].reg;
if(reg){
int shift = anapllout_input[mux].shift;
anatop[reg] = (anatop[reg] & ~(7<<shift)) | ((div-1)<<shift);
} else if(div != 1){
panic("setanapllout: bad frequency\n");
return;
}
anatop[CCM_ANALOG_PLLOUT_MONITOR_CFG] |= PLLOUT_MONITOR_CLK_CKE;
}
static int
getanapllout(void)
{
int mux, input, freq, reg, div;
u32int cfg = anatop[CCM_ANALOG_PLLOUT_MONITOR_CFG];
mux = cfg & 0xF;
input = anapllout_input[mux].input;
if(input == 0)
return 0;
freq = input_clk_freq[input];
if((cfg & PLLOUT_MONITOR_CLK_CKE) == 0)
freq = -freq;
reg = anapllout_input[mux].reg;
if(reg){
int shift = anapllout_input[mux].shift;
div = ((anatop[reg] >> shift) & 7)+1;
} else {
div = 1;
}
return freq / div;
}
static u32int static u32int
clkgate(Clock *gate, u32int val) clkgate(Clock *gate, u32int val)
{ {
@ -1330,6 +1414,11 @@ setclkrate(char *name, char *source, int freq)
{ {
int root, input; int root, input;
if(cistrcmp(name, "ccm_analog_pllout") == 0){
setanapllout(lookinputclk(source), freq);
return;
}
if((root = lookrootclk(name)) < 0) if((root = lookrootclk(name)) < 0)
panic("setclkrate: clock %s not defined", name); panic("setclkrate: clock %s not defined", name);
if(source == nil) if(source == nil)
@ -1346,6 +1435,9 @@ getclkrate(char *name)
{ {
int root, input; int root, input;
if(cistrcmp(name, "ccm_analog_pllout") == 0)
return getanapllout();
if((root = lookrootclk(name)) >= 0) if((root = lookrootclk(name)) >= 0)
return rootclkgetcfg(root, &input); return rootclkgetcfg(root, &input);

View file

@ -159,3 +159,10 @@ extern uint iomuxgpr(int gpr, uint set, uint mask);
#define GPIO_PIN(n, m) ((n)<<5 | (m)) #define GPIO_PIN(n, m) ((n)<<5 | (m))
extern void gpioout(uint pin, int set); extern void gpioout(uint pin, int set);
extern int gpioin(uint pin); extern int gpioin(uint pin);
/* pciimx */
extern int pcicfgrw8(int tbdf, int rno, int data, int read);
extern int pcicfgrw16(int tbdf, int rno, int data, int read);
extern int pcicfgrw32(int tbdf, int rno, int data, int read);
extern void pciintrenable(int tbdf, void (*f)(Ureg*, void*), void *a);
extern void pciintrdisable(int tbdf, void (*f)(Ureg*, void*), void *a);

View file

@ -254,6 +254,11 @@ intrenable(int irq, void (*f)(Ureg*, void*), void *a, int tbdf, char *)
u32int intid; u32int intid;
int cpu, prio; int cpu, prio;
if(BUSTYPE(tbdf) == BusPCI){
pciintrenable(tbdf, f, a);
return;
}
if(tbdf != BUSUNKNOWN) if(tbdf != BUSUNKNOWN)
return; return;
@ -306,6 +311,10 @@ intrenable(int irq, void (*f)(Ureg*, void*), void *a, int tbdf, char *)
} }
void void
intrdisable(int, void (*)(Ureg*, void*), void *, int, char*) intrdisable(int tbdf, void (*f)(Ureg*, void*), void *a, int, char*)
{ {
if(BUSTYPE(tbdf) == BusPCI){
pciintrdisable(tbdf, f, a);
return;
}
} }

View file

@ -28,7 +28,12 @@ enum {
IRQsctr0 = SPI+47, IRQsctr0 = SPI+47,
IRQsctr1 = SPI+48, IRQsctr1 = SPI+48,
IRQpci2 = SPI+74,
IRQenet1 = SPI+118, IRQenet1 = SPI+118,
IRQpci1 = SPI+122,
}; };
#define BUSUNKNOWN (-1) #define BUSUNKNOWN (-1)
#define PCIWADDR(x) PADDR(x)

497
sys/src/9/imx8/pciimx.c Normal file
View file

@ -0,0 +1,497 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/pci.h"
typedef struct Intvec Intvec;
struct Intvec
{
Pcidev *p;
void (*f)(Ureg*, void*);
void *a;
};
typedef struct Ctlr Ctlr;
struct Ctlr
{
uvlong mem_base;
uvlong mem_size;
uvlong cfg_base;
uvlong cfg_size;
uvlong io_base;
uvlong io_size;
int bno, ubn;
int irq;
u32int *dbi;
u32int *cfg;
Pcidev *bridge;
Lock;
Intvec vec[32];
};
static Ctlr ctlrs[2] = {
{
0x18000000, 0x7f00000,
0x1ff00000, 0x80000,
0x1ff80000, 0x10000,
0, 127, IRQpci1,
(u32int*)(VIRTIO + 0x3800000),
},
{
0x20000000, 0x7f00000,
0x27f00000, 0x80000,
0x27f80000, 0x10000,
128, 255, IRQpci2,
(u32int*)(VIRTIO + 0x3c00000),
},
};
enum {
IATU_MAX = 8,
IATU_INBOUND = 1<<0,
IATU_INDEX_SHIFT = 1,
IATU_OFFSET = 0x300000/4,
IATU_STRIDE = 0x100/4,
IATU_REGION_CTRL_1 = 0x00/4,
CTRL_1_FUNC_NUM_SHIFT = 20,
CTRL_1_FUNC_NUM_MASK = 7<<CTRL_1_FUNC_NUM_SHIFT,
CTRL_1_INCREASE_REGION_SIZ = 1<<13,
CTRL_1_ATTR_SHIFT = 9,
CTRL_1_ATTR_MASK = 3<<CTRL_1_ATTR_SHIFT,
CTRL_1_TD = 1<<8,
CTRL_1_TC_SHIFT = 5,
CTRL_1_TC_MASK = 7<<CTRL_1_TC_SHIFT,
CTRL_1_TYPE_SHIFT = 0,
CTRL_1_TYPE_MASK = 0x1F<<CTRL_1_TYPE_SHIFT,
CTRL_1_TYPE_MEM = 0x0<<CTRL_1_TYPE_SHIFT,
CTRL_1_TYPE_IO = 0x2<<CTRL_1_TYPE_SHIFT,
CTRL_1_TYPE_CFG0 = 0x4<<CTRL_1_TYPE_SHIFT,
CTRL_1_TYPE_CFG1 = 0x5<<CTRL_1_TYPE_SHIFT,
IATU_REGION_CTRL_2 = 0x04/4,
CTRL_2_REGION_EN = 1<<31,
CTRL_2_INVERT_MODE = 1<<29,
CTRL_2_CFG_SHIFT_MODE = 1<<28,
CTRL_2_DMA_BYPASS = 1<<27,
CTRL_2_HEADER_SUBSITUTE_EN = 1<<23,
CTRL_2_INHIBIT_PAYLOAD = 1<<22,
CTRL_2_SNP = 1<<20,
CTRL_2_FUNC_BYPASS = 1<<19,
CTRL_2_TAG_SUBSTITUTE_EN = 1<<16,
IATU_LWR_BSAE_ADDR = 0x08/4,
IATU_UPPER_BASE_ADDR = 0x0C/4,
IATU_LWR_LIMIT_ADDR = 0x10/4,
IATU_LWR_TARGET_ADDR = 0x14/4,
IATU_UPPER_TARGET_ADDR = 0x18/4,
IATU_UPPER_LIMIT_ADDR = 0x20/4, /* undocumented */
};
/* disable all iATU's */
static void
iatuinit(Ctlr *ctlr)
{
u32int *reg;
int index;
for(index=0; index < IATU_MAX; index++){
reg = &ctlr->dbi[IATU_OFFSET + IATU_STRIDE*index];
reg[IATU_REGION_CTRL_2] &= ~CTRL_2_REGION_EN;
}
}
static void
iatucfg(Ctlr *ctlr, int index, u32int type, uvlong target, uvlong base, uvlong size)
{
uvlong limit = base + size - 1;
u32int *reg;
assert(size > 0);
assert(index < IATU_MAX);
assert((index & IATU_INBOUND) == 0);
reg = &ctlr->dbi[IATU_OFFSET + IATU_STRIDE*index];
reg[IATU_REGION_CTRL_2] &= ~CTRL_2_REGION_EN;
reg[IATU_LWR_BSAE_ADDR] = base;
reg[IATU_UPPER_BASE_ADDR] = base >> 32;
reg[IATU_LWR_LIMIT_ADDR] = limit;
reg[IATU_UPPER_LIMIT_ADDR] = limit >> 32;
reg[IATU_LWR_TARGET_ADDR] = target;
reg[IATU_UPPER_TARGET_ADDR] = target >> 32;
type &= CTRL_1_TYPE_MASK;
if(((size-1)>>32) != 0)
type |= CTRL_1_INCREASE_REGION_SIZ;
reg[IATU_REGION_CTRL_1] = type;
reg[IATU_REGION_CTRL_2] = CTRL_2_REGION_EN;
while((reg[IATU_REGION_CTRL_2] & CTRL_2_REGION_EN) == 0)
microdelay(10);
}
static Ctlr*
bus2ctlr(int bno)
{
Ctlr *ctlr;
for(ctlr = ctlrs; ctlr < &ctlrs[nelem(ctlrs)]; ctlr++)
if(bno >= ctlr->bno && bno <= ctlr->ubn)
return ctlr;
return nil;
}
static void*
cfgaddr(int tbdf, int rno)
{
Ctlr *ctlr;
ctlr = bus2ctlr(BUSBNO(tbdf));
if(ctlr == nil)
return nil;
if(pciparentdev == nil){
if(BUSDNO(tbdf) != 0 || BUSFNO(tbdf) != 0)
return nil;
return (uchar*)ctlr->dbi + rno;
}
iatucfg(ctlr, 0<<IATU_INDEX_SHIFT,
pciparentdev->parent==nil? CTRL_1_TYPE_CFG0: CTRL_1_TYPE_CFG1,
BUSBNO(tbdf)<<24 | BUSDNO(tbdf)<<19 | BUSFNO(tbdf)<<16,
ctlr->cfg_base, ctlr->cfg_size);
return (uchar*)ctlr->cfg + rno;
}
int
pcicfgrw32(int tbdf, int rno, int data, int read)
{
u32int *p;
if((p = cfgaddr(tbdf, rno & ~3)) != nil){
if(read)
data = *p;
else
*p = data;
} else {
data = -1;
}
return data;
}
int
pcicfgrw16(int tbdf, int rno, int data, int read)
{
u16int *p;
if((p = cfgaddr(tbdf, rno & ~1)) != nil){
if(read)
data = *p;
else
*p = data;
} else {
data = -1;
}
return data;
}
int
pcicfgrw8(int tbdf, int rno, int data, int read)
{
u8int *p;
if((p = cfgaddr(tbdf, rno)) != nil){
if(read)
data = *p;
else
*p = data;
} else {
data = -1;
}
return data;
}
static u16int msimsg;
#define MSI_TARGET_ADDR PADDR(&msimsg)
enum {
MSI_CAP_ID = 0x50/4,
PCI_MSI_ENABLE = 1<<16,
MSI_CTRL_ADDR = 0x820/4,
MSI_CTRL_UPPER_ADDR = 0x824/4,
MSI_CTRL_INT_0_EN = 0x828/4,
MSI_CTRL_INT_0_MASK = 0x82C/4,
MSI_CTRL_INT_0_STATUS = 0x830/4,
MISC_CONTROL_1 = 0x8BC/4,
DBI_RO_WR_EN = 1<<0,
};
static void
pciinterrupt(Ureg *ureg, void *arg)
{
Ctlr *ctlr = arg;
Intvec *vec;
u32int status, mask;
status = ctlr->dbi[MSI_CTRL_INT_0_STATUS];
if(status == 0)
return;
ctlr->dbi[MSI_CTRL_INT_0_STATUS] = status;
ilock(ctlr);
for(vec = ctlr->vec, mask = 1; vec < &ctlr->vec[nelem(ctlr->vec)]; vec++, mask <<= 1){
if((status & mask) != 0 && vec->f != nil)
(*vec->f)(ureg, vec->a);
}
iunlock(ctlr);
}
static void
pciintrinit(Ctlr *ctlr)
{
ctlr->dbi[MSI_CTRL_INT_0_EN] = 0;
ctlr->dbi[MSI_CTRL_INT_0_MASK] = 0;
ctlr->dbi[MSI_CTRL_INT_0_STATUS] = -1;
ctlr->dbi[MSI_CTRL_ADDR] = MSI_TARGET_ADDR;
ctlr->dbi[MSI_CTRL_UPPER_ADDR] = MSI_TARGET_ADDR >> 32;
intrenable(ctlr->irq+0, pciinterrupt, ctlr, BUSUNKNOWN, "pci");
intrenable(ctlr->irq+1, pciinterrupt, ctlr, BUSUNKNOWN, "pci");
intrenable(ctlr->irq+2, pciinterrupt, ctlr, BUSUNKNOWN, "pci");
intrenable(ctlr->irq+3, pciinterrupt, ctlr, BUSUNKNOWN, "pci");
ctlr->dbi[MSI_CAP_ID] |= PCI_MSI_ENABLE;
}
void
pciintrenable(int tbdf, void (*f)(Ureg*, void*), void *a)
{
Ctlr *ctlr;
Intvec *vec;
Pcidev *p;
ctlr = bus2ctlr(BUSBNO(tbdf));
if(ctlr == nil){
print("pciintrenable: %T: unknown controller\n", tbdf);
return;
}
if((p = pcimatchtbdf(tbdf)) == nil){
print("pciintrenable: %T: unknown device\n", tbdf);
return;
}
if(pcimsidisable(p) < 0){
print("pciintrenable: %T: device doesnt support vec\n", tbdf);
return;
}
ilock(ctlr);
for(vec = ctlr->vec; vec < &ctlr->vec[nelem(ctlr->vec)]; vec++){
if(vec->p == p){
ctlr->dbi[MSI_CTRL_INT_0_EN] &= ~(1 << (vec - ctlr->vec));
vec->p = nil;
break;
}
}
for(vec = ctlr->vec; vec < &ctlr->vec[nelem(ctlr->vec)]; vec++){
if(vec->p == nil){
vec->p = p;
vec->a = a;
vec->f = f;
break;
}
}
iunlock(ctlr);
if(vec >= &ctlr->vec[nelem(ctlr->vec)]){
print("pciintrenable: %T: out of isr slots\n", tbdf);
return;
}
ctlr->dbi[MSI_CTRL_INT_0_EN] |= (1 << (vec - ctlr->vec));
pcimsienable(p, MSI_TARGET_ADDR, vec - ctlr->vec);
}
void
pciintrdisable(int tbdf, void (*f)(Ureg*, void*), void *a)
{
Ctlr *ctlr;
Intvec *vec;
ctlr = bus2ctlr(BUSBNO(tbdf));
if(ctlr == nil){
print("pciintrenable: %T: unknown controller\n", tbdf);
return;
}
ilock(ctlr);
for(vec = ctlr->vec; vec < &ctlr->vec[nelem(ctlr->vec)]; vec++){
if(vec->p == nil)
continue;
if(vec->p->tbdf == tbdf && vec->f == f && vec->a == a){
ctlr->dbi[MSI_CTRL_INT_0_EN] &= ~(1 << (vec - ctlr->vec));
vec->f = nil;
vec->a = nil;
vec->p = nil;
break;
}
}
iunlock(ctlr);
}
static void
rootinit(Ctlr *ctlr)
{
uvlong base;
ulong ioa;
iatuinit(ctlr);
ctlr->cfg = vmap(ctlr->cfg_base, ctlr->cfg_size);
if(ctlr->cfg == nil)
return;
ctlr->dbi[MISC_CONTROL_1] |= DBI_RO_WR_EN;
/* bus number */
ctlr->dbi[PciPBN/4] &= ~0xFFFFFF;
ctlr->dbi[PciPBN/4] |= ctlr->bno | (ctlr->bno+1)<<8 | ctlr->ubn<<16;
/* command */
ctlr->dbi[PciPCR/4] &= ~0xFFFF;
ctlr->dbi[PciPCR/4] |= IOen | MEMen | MASen | SErrEn;
/* device class/subclass */
ctlr->dbi[PciRID/4] &= ~0xFFFF0000;
ctlr->dbi[PciRID/4] |= 0x06040000;
ctlr->dbi[PciBAR0/4] = 0;
ctlr->dbi[PciBAR1/4] = 0;
ctlr->dbi[MISC_CONTROL_1] &= ~DBI_RO_WR_EN;
ctlr->ubn = pciscan(ctlr->bno, &ctlr->bridge, nil);
if(ctlr->bridge == nil || ctlr->bridge->bridge == nil)
return;
pciintrinit(ctlr);
iatucfg(ctlr, 1<<IATU_INDEX_SHIFT, CTRL_1_TYPE_IO, ctlr->io_base, ctlr->io_base, ctlr->io_size);
iatucfg(ctlr, 2<<IATU_INDEX_SHIFT, CTRL_1_TYPE_MEM, ctlr->mem_base, ctlr->mem_base, ctlr->mem_size);
ioa = ctlr->io_base;
base = ctlr->mem_base;
pcibusmap(ctlr->bridge, &base, &ioa, 1);
pcihinv(ctlr->bridge);
}
static void
pcicfginit(void)
{
fmtinstall('T', tbdffmt);
rootinit(&ctlrs[0]);
rootinit(&ctlrs[1]);
}
enum {
SRC_PCIEPHY_RCR = 0x2C/4,
SRC_PCIE2_RCR = 0x48/4,
PCIE_CTRL_APP_XFER_PENDING = 1<<16,
PCIE_CTRL_APP_UNLOCK_MSG = 1<<15,
PCIE_CTRL_SYS_INT = 1<<14,
PCIE_CTRL_CFG_L1_AUX = 1<<12,
PCIE_CTRL_APPS_TURNOFF = 1<<11,
PCIE_CTRL_APPS_PME = 1<<10,
PCIE_CTRL_APPS_EXIT = 1<<9,
PCIE_CTRL_APPS_ENTER = 1<<8,
PCIE_CTRL_APPS_READY = 1<<7,
PCIE_CTRL_APPS_EN = 1<<6,
PCIE_CTRL_APPS_RST = 1<<5,
PCIE_CTRL_APPS_CLK_REQ = 1<<4,
PCIE_PERST = 1<<3,
PCIE_BTN = 1<<2,
PCIE_G_RST = 1<<1,
PCIE_PHY_POWER_ON_RESET_N = 1<<0,
};
static u32int *resetc = (u32int*)(VIRTIO + 0x390000);
void
pciimxlink(void)
{
resetc[SRC_PCIEPHY_RCR] |= PCIE_BTN | PCIE_G_RST;
resetc[SRC_PCIE2_RCR] |= PCIE_BTN | PCIE_G_RST;
resetc[SRC_PCIEPHY_RCR] |= PCIE_CTRL_APPS_EN;
resetc[SRC_PCIE2_RCR] |= PCIE_CTRL_APPS_EN;
setclkgate("pcie_clk_rst.auxclk", 0);
setclkgate("pcie2_clk_rst.auxclk", 0);
iomuxpad("pad_ecspi1_mosi", "gpio5_io07", "~LVTTL ~HYS ~PUE ~ODE FAST 45_OHM");
iomuxpad("pad_sai5_rxd2", "gpio3_io23", "~LVTTL ~HYS ~PUE ~ODE FAST 45_OHM");
gpioout(GPIO_PIN(5, 7), 0);
gpioout(GPIO_PIN(3, 23), 0);
powerup("pcie");
powerup("pcie2");
/* configure monitor CLK2 output internal reference clock for PCIE1 */
setclkrate("ccm_analog_pllout", "system_pll1_clk", 100*Mhz);
delay(10);
/* PCIE1_REF_USE_PAD=0 */
iomuxgpr(14, 0<<9, 1<<9);
/* PCIE2_REF_USE_PAD=1 */
iomuxgpr(16, 1<<9, 1<<9);
/* PCIE1_CTRL_DEVICE_TYPE=ROOT, PCIE2_CTRL_DEVICE_TYPE=ROOT */
iomuxgpr(12, 4<<12 | 4<<8, 0xF<<12 | 0xF<<8);
setclkrate("ccm_pcie1_ctrl_clk_root", "system_pll2_div4", 250*Mhz);
setclkrate("ccm_pcie2_ctrl_clk_root", "system_pll2_div4", 250*Mhz);
setclkrate("pcie_clk_rst.auxclk", "system_pll2_div10", 100*Mhz);
setclkrate("pcie2_clk_rst.auxclk", "system_pll2_div10", 100*Mhz);
setclkrate("pcie_phy.ref_alt_clk_p", "system_pll2_div10", 100*Mhz);
setclkrate("pcie2_phy.ref_alt_clk_p", "system_pll2_div10", 100*Mhz);
setclkgate("pcie_clk_rst.auxclk", 1);
setclkgate("pcie2_clk_rst.auxclk", 1);
/* PCIE1_CLKREQ_B_OVERRIDE=0 PCIE1_CLKREQ_B_OVERRIDE_EN=1 */
iomuxgpr(14, 1<<10, 3<<10);
/* PCIE2_CLKREQ_B_OVERRIDE=0 PCIE2_CLKREQ_B_OVERRIDE_EN=1 */
iomuxgpr(16, 1<<10, 3<<10);
delay(100);
gpioout(GPIO_PIN(5, 7), 1);
gpioout(GPIO_PIN(3, 23), 1);
delay(1);
resetc[SRC_PCIEPHY_RCR] &= ~(PCIE_BTN | PCIE_G_RST);
resetc[SRC_PCIE2_RCR] &= ~(PCIE_BTN | PCIE_G_RST);
pcicfginit();
}

View file

@ -27,6 +27,7 @@ link
ethermedium ethermedium
loopbackmedium loopbackmedium
i2cimx devi2c i2cimx devi2c
pciimx pci
ip ip
tcp tcp
udp udp
@ -44,6 +45,7 @@ misc
uartimx uartimx
iomux iomux
sdmmc usdhc sdmmc usdhc
sdnvme pci
port port
int cpuserver = 0; int cpuserver = 0;
bootdir bootdir

View file

@ -16,6 +16,7 @@ struct Pcisiz
}; };
int pcimaxdno; int pcimaxdno;
Pcidev *pciparentdev;
static Lock pcicfglock; static Lock pcicfglock;
static Pcidev *pcilist, **pcitail; static Pcidev *pcilist, **pcitail;
@ -113,6 +114,8 @@ pcicfgr8(Pcidev* p, int rno)
int data; int data;
ilock(&pcicfglock); ilock(&pcicfglock);
pciparentdev = p->parent;
data = pcicfgrw8(p->tbdf, rno, 0, 1); data = pcicfgrw8(p->tbdf, rno, 0, 1);
iunlock(&pcicfglock); iunlock(&pcicfglock);
@ -122,6 +125,8 @@ void
pcicfgw8(Pcidev* p, int rno, int data) pcicfgw8(Pcidev* p, int rno, int data)
{ {
ilock(&pcicfglock); ilock(&pcicfglock);
pciparentdev = p->parent;
pcicfgrw8(p->tbdf, rno, data, 0); pcicfgrw8(p->tbdf, rno, data, 0);
iunlock(&pcicfglock); iunlock(&pcicfglock);
} }
@ -131,6 +136,8 @@ pcicfgr16(Pcidev* p, int rno)
int data; int data;
ilock(&pcicfglock); ilock(&pcicfglock);
pciparentdev = p->parent;
data = pcicfgrw16(p->tbdf, rno, 0, 1); data = pcicfgrw16(p->tbdf, rno, 0, 1);
iunlock(&pcicfglock); iunlock(&pcicfglock);
@ -140,6 +147,8 @@ void
pcicfgw16(Pcidev* p, int rno, int data) pcicfgw16(Pcidev* p, int rno, int data)
{ {
ilock(&pcicfglock); ilock(&pcicfglock);
pciparentdev = p->parent;
pcicfgrw16(p->tbdf, rno, data, 0); pcicfgrw16(p->tbdf, rno, data, 0);
iunlock(&pcicfglock); iunlock(&pcicfglock);
} }
@ -149,6 +158,8 @@ pcicfgr32(Pcidev* p, int rno)
int data; int data;
ilock(&pcicfglock); ilock(&pcicfglock);
pciparentdev = p->parent;
data = pcicfgrw32(p->tbdf, rno, 0, 1); data = pcicfgrw32(p->tbdf, rno, 0, 1);
iunlock(&pcicfglock); iunlock(&pcicfglock);
@ -158,6 +169,8 @@ void
pcicfgw32(Pcidev* p, int rno, int data) pcicfgw32(Pcidev* p, int rno, int data)
{ {
ilock(&pcicfglock); ilock(&pcicfglock);
pciparentdev = p->parent;
pcicfgrw32(p->tbdf, rno, data, 0); pcicfgrw32(p->tbdf, rno, data, 0);
iunlock(&pcicfglock); iunlock(&pcicfglock);
} }
@ -169,6 +182,7 @@ pcibarsize(Pcidev *p, int rno)
int v; int v;
ilock(&pcicfglock); ilock(&pcicfglock);
pciparentdev = p->parent;
v = pcicfgrw32(p->tbdf, rno, 0, 1); v = pcicfgrw32(p->tbdf, rno, 0, 1);
pcicfgrw32(p->tbdf, rno, -1, 0); pcicfgrw32(p->tbdf, rno, -1, 0);
@ -206,6 +220,8 @@ void
pcisetbar(Pcidev *p, int rno, uvlong bar) pcisetbar(Pcidev *p, int rno, uvlong bar)
{ {
ilock(&pcicfglock); ilock(&pcicfglock);
pciparentdev = p->parent;
pcicfgrw32(p->tbdf, rno, bar, 0); pcicfgrw32(p->tbdf, rno, bar, 0);
if((bar&7) == 4 && rno >= PciBAR0 && rno < PciBAR0+4*(nelem(p->mem)-1)) if((bar&7) == 4 && rno >= PciBAR0 && rno < PciBAR0+4*(nelem(p->mem)-1))
pcicfgrw32(p->tbdf, rno+4, bar>>32, 0); pcicfgrw32(p->tbdf, rno+4, bar>>32, 0);
@ -216,6 +232,8 @@ void
pcisetwin(Pcidev *p, uvlong base, uvlong limit) pcisetwin(Pcidev *p, uvlong base, uvlong limit)
{ {
ilock(&pcicfglock); ilock(&pcicfglock);
pciparentdev = p->parent;
if(base & 1){ if(base & 1){
pcicfgrw16(p->tbdf, PciIBR, (limit & 0xF000)|((base & 0xF000)>>8), 0); pcicfgrw16(p->tbdf, PciIBR, (limit & 0xF000)|((base & 0xF000)>>8), 0);
pcicfgrw32(p->tbdf, PciIUBR, (limit & 0xFFFF0000)|(base>>16), 0); pcicfgrw32(p->tbdf, PciIUBR, (limit & 0xFFFF0000)|(base>>16), 0);
@ -534,12 +552,15 @@ pciscan(int bno, Pcidev** list, Pcidev *parent)
tbdf = MKBUS(BusPCI, bno, dno, fno); tbdf = MKBUS(BusPCI, bno, dno, fno);
lock(&pcicfglock); lock(&pcicfglock);
pciparentdev = parent;
l = pcicfgrw32(tbdf, PciVID, 0, 1); l = pcicfgrw32(tbdf, PciVID, 0, 1);
unlock(&pcicfglock); unlock(&pcicfglock);
if(l == 0xFFFFFFFF || l == 0) if(l == 0xFFFFFFFF || l == 0)
continue; continue;
p = pcidevalloc(); p = pcidevalloc();
p->parent = parent;
p->tbdf = tbdf; p->tbdf = tbdf;
p->vid = l; p->vid = l;
p->did = l>>16; p->did = l>>16;
@ -622,7 +643,6 @@ pciscan(int bno, Pcidev** list, Pcidev *parent)
break; break;
} }
p->parent = parent;
if(head != nil) if(head != nil)
*tail = p; *tail = p;
else else

View file

@ -223,6 +223,7 @@ enum
}; };
extern int pcimaxdno; extern int pcimaxdno;
extern Pcidev *pciparentdev;
extern void pcidevfree(Pcidev* pcidev); extern void pcidevfree(Pcidev* pcidev);