📄 pci_core.c
字号:
*/ if( write ) { /* Avoid writes to DeviceID and ClassCode regs */ if (reg != PCI_ID && reg != PCI_CCREV) { BONITO_PCI_REG(reg) = *(UINT32 *)data; } } else { *(UINT32 *)data = BONITO_PCI_REG(reg); } return OK; } } /* Clear cause register bits */ BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR | BONITO_PCICMD_MTABORT_CLR); /* Setup pattern to be used as PCI "address" for Type 0 cycle */ if( busnum == PCI_BUS_LOCAL ) { /* IDSEL */ data32 = 1 << PCI_DEVNUM2IDSEL(devnum); } else { /* Bus number */ data32 = busnum << PCI_CFG_TYPE1_BUS_SHF; /* Device number */ data32 |= devnum << PCI_CFG_TYPE1_DEV_SHF; } /* Function (same for Type 0/1) */ data32 |= func << PCI_CFG_TYPE0_FUNC_SHF; /* Register number (same for Type 0/1) */ data32 |= reg << PCI_CFG_TYPE0_REG_SHF; if( busnum == PCI_BUS_LOCAL ) { /* Type 0 */ BONITO_PCIMAP_CFG = data32 >> 16; } else { /* Type 1 */ BONITO_PCIMAP_CFG = (data32 >> 16) | 0x10000; } /* Flush Bonito register block */ BONITO_PCIMAP_CFG; sys_sync(); /* Perform access */ if( write ) { REG32( KSEG1(BONITO_PCICFG_BASE) + (data32 & 0xFFFF) ) = *(UINT32 *)data; /* Wait till done */ while( BONITO_PCIMSTAT & 0xF ); } else { *(UINT32 *)data = REG32( KSEG1(BONITO_PCICFG_BASE) + (data32 & 0xFFFF) ); } /* Detect Master/Target abort */ if( BONITO_PCICMD & (BONITO_PCICMD_MABORT_CLR | BONITO_PCICMD_MTABORT_CLR) ) { /* Error occurred */ /* Clear bits */ BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR | BONITO_PCICMD_MTABORT_CLR); return ERROR_PCI_ABORT; } return OK; case MIPS_REVISION_CORID_QED_RM5261 : case MIPS_REVISION_CORID_CORE_LV : case MIPS_REVISION_CORID_CORE_FPGA : case MIPS_REVISION_CORID_CORE_FPGAr2 : /**** Galileo system controller ****/ /* Workaround : Galileo seems to stall if requested to access * device 31 */ if( (busnum == PCI_BUS_LOCAL) && (devnum == 31) ) return ERROR_PCI_ABORT; /* Clear cause register bits */ GT_W32( sys_nb_base, GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT) ); /* Setup address */ GT_W32( sys_nb_base, GT_PCI0_CFGADDR_OFS, (busnum << GT_PCI0_CFGADDR_BUSNUM_SHF) | (devnum << GT_PCI0_CFGADDR_DEVNUM_SHF) | (func << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | ((reg >> 2) << GT_PCI0_CFGADDR_REGNUM_SHF) | GT_PCI0_CFGADDR_CONFIGEN_BIT ); /* Perform the access */ if( write ) GT_W32( sys_nb_base, GT_PCI0_CFGDATA_OFS, *(UINT32 *)data ); else GT_L32( sys_nb_base, GT_PCI0_CFGDATA_OFS, *(UINT32 *)data ); /* Check for master or target abort */ GT_L32( sys_nb_base, GT_INTRCAUSE_OFS, intr ); if( intr & (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT) ) { /* Error occurred */ /* Clear bits */ GT_W32( sys_nb_base, GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT) ); return ERROR_PCI_ABORT; } return OK; case MIPS_REVISION_CORID_CORE_SYS : case MIPS_REVISION_CORID_CORE_FPGA2 : case MIPS_REVISION_CORID_CORE_EMUL_SYS : /**** MIPS system controller ****/ /* Clear cause register bits */ REG(MSC01_PCI_REG_BASE, MSC01_PCI_INTSTAT) = MSC01_PCI_INTSTAT_MA_BIT | MSC01_PCI_INTSTAT_TA_BIT; /* Setup address */ REG(MSC01_PCI_REG_BASE, MSC01_PCI_CFGADDR) = (busnum << MSC01_PCI_CFGADDR_BNUM_SHF) | (devnum << MSC01_PCI_CFGADDR_DNUM_SHF) | (func << MSC01_PCI_CFGADDR_FNUM_SHF) | ((reg >> 2) << MSC01_PCI_CFGADDR_RNUM_SHF); sys_sync(); /* Perform the access */ if( write ) { REG(MSC01_PCI_REG_BASE, MSC01_PCI_CFGDATA) = *(UINT32 *)data; sys_sync(); } else *(UINT32 *)data = REG(MSC01_PCI_REG_BASE, MSC01_PCI_CFGDATA); /* Check for master or target abort */ intr = REG(MSC01_PCI_REG_BASE, MSC01_PCI_INTSTAT); if( intr & (MSC01_PCI_INTSTAT_MA_BIT | MSC01_PCI_INTSTAT_TA_BIT) ) { /* Error occurred */ /* Clear bits */ REG(MSC01_PCI_REG_BASE, MSC01_PCI_INTSTAT) = MSC01_PCI_INTSTAT_MA_BIT | MSC01_PCI_INTSTAT_TA_BIT ; return ERROR_PCI_ABORT; } return OK; /* Add new core cards here */ default : /* Should never happen */ return ERROR_PCI_ABORT; }}/************************************************************************ * * arch_pci_lattim * Description : * ------------- * * Latency timer value to be written to PCI device (Max_Lat) * * Return values : * --------------- * * Value to be written to Max_Lat. * ************************************************************************/UINT8arch_pci_lattim( t_pci_cfg_dev *dev ) /* PCI device structure */{ /* Determine latency timer * Special handling of Galileo System Controller. */ return ((dev->vendorid == PCI_VENDID_GALILEO ) && (dev->devid == PCI_DEVID_64120)) ? MAX( dev->min_gnt, MAX(GT_LATTIM_MIN, PCI_LATTIM_FIXED) ) : MAX( dev->min_gnt, PCI_LATTIM_FIXED );}/************************************************************************ * * arch_pci_multi * Description : * ------------- * * Extract multi field from PCI configuration word 0xc * (Word holding Bist/Header Type/Latency Timer/Cache Line Size) * * Return values : * --------------- * * multi field * ************************************************************************/UINT8arch_pci_multi( t_pci_cfg_dev *dev, UINT32 bhlc ){ /* Special handling of Galileo System Controller : * It is a multi function device, but we only use function 0. */ if( (dev->vendorid == PCI_VENDID_GALILEO ) && (dev->devid == PCI_DEVID_64120) ) { return 0; } else return (bhlc & PCI_BHLC_MULTI_MSK) >> PCI_BHLC_MULTI_SHF;}/************************************************************************ * Implementation : Static functions ************************************************************************//************************************************************************ * config_bonito64 ************************************************************************/static UINT32config_bonito64( void ){ UINT32 cmd; UINT32 line; UINT32 mask, trans; /* Map PCI addresses transparently */ mask = ~((sys_ramsize >> (BONITO_PCIMEMBASECFG_ASHIFT+1)) - 1); trans = ~mask + 1; mask &= (BONITO_PCIMEMBASECFG_MEMBASE0_MASK >> BONITO_PCIMEMBASECFG_MEMBASE0_MASK_SHIFT); trans &= (BONITO_PCIMEMBASECFG_MEMBASE0_TRANS >> BONITO_PCIMEMBASECFG_MEMBASE0_TRANS_SHIFT); BONITO_PCIMEMBASECFG = (mask << BONITO_PCIMEMBASECFG_MEMBASE0_MASK_SHIFT) | (0 << BONITO_PCIMEMBASECFG_MEMBASE0_TRANS_SHIFT) | (mask << BONITO_PCIMEMBASECFG_MEMBASE1_MASK_SHIFT) | (trans << BONITO_PCIMEMBASECFG_MEMBASE1_TRANS_SHIFT) | (sys_cpu_cache_coherency ? (BONITO_PCIMEMBASECFG_MEMBASE0_CACHED | BONITO_PCIMEMBASECFG_MEMBASE1_CACHED) : 0); /* If CPU is big endian, we need to handle endianness due to * PCI being little endian. * * We have chosen the following setup of Bonito64 * (through BONGENCFG register) : * * PCI device doing DMA : * * Bonito64 swaps byte lanes. * * CPU accesses PCI device : * * Bonito64 does NOT swap byte lanes. * * This means that software must do the following : * * Word access : Do nothing. * Halfword access : Software must invert bit 1 of address. * Byte access : Software must invert 2 msb of address. */ /* Enable IOBC and configure byteswapping */ BONITO_BONGENCFG = BONITO_BONGENCFG |#ifdef EB BONITO_BONGENCFG_BYTESWAP |#endif BONITO_BONGENCFG_UNCACHED | BONITO_BONGENCFG_SNOOPEN | (sys_cpu_cache_coherency ? (BONITO_BONGENCFG_WBEHINDEN | BONITO_BONGENCFG_PREFETCHEN) : 0); /* Invalidate lines */ for( line = 0; line < 4; line ++ ) { cmd = (0 << BONITO_PCICACHECTRL_CACHECMD_SHIFT) | (line << BONITO_PCICACHECTRL_CACHECMDLINE_SHIFT); BONITO_PCICACHECTRL = cmd; BONITO_PCICACHECTRL = cmd | BONITO_PCICACHECTRL_CMDEXEC; while(BONITO_PCICACHECTRL & BONITO_PCICACHECTRL_CMDEXEC) { ; } BONITO_PCICACHECTRL = cmd; } return OK;}/************************************************************************ * config_gt64120 ************************************************************************/static UINT32config_gt64120( void ){ UINT32 rc; UINT32 data, bare; /**** Setup GT64120 BAR ****/ /* Disable all BARs except SCS30 and SCS10 */ bare = GT_PCI0_BARE_SWSCS3BOOTDIS_BIT | GT_PCI0_BARE_SWSCS32DIS_BIT | GT_PCI0_BARE_SWSCS10DIS_BIT | GT_PCI0_BARE_INTIODIS_BIT | GT_PCI0_BARE_INTMEMDIS_BIT | GT_PCI0_BARE_CS3BOOTDIS_BIT | GT_PCI0_BARE_CS20DIS_BIT; /* Check range and calc mask for GT bank size registers */ if( scs10_size != 0 ) { rc = pci_check_range( scs10_start, scs10_size, &data ); if( rc != OK ) return rc; /* Write BAR size register */ GT_W32( sys_nb_base, GT_PCI0_BS_SCS10_OFS, data ); } else bare |= GT_PCI0_BARE_SCS10DIS_BIT; if( scs32_size != 0 ) { rc = pci_check_range( scs32_start, scs32_size, &data ); if( rc != OK ) return rc; /* Write BAR size register */ GT_W32( sys_nb_base, GT_PCI0_BS_SCS32_OFS, data ); } else bare |= GT_PCI0_BARE_SCS32DIS_BIT; GT_W32( sys_nb_base, GT_PCI0_BARE_OFS, bare ); return OK;}/************************************************************************ * gt_calc_range ************************************************************************/static voidgt_calc_range( UINT32 ld, UINT32 hd, UINT32 *start, UINT32 *size ){ UINT32 end; GT_L32( sys_nb_base, ld, *start ); GT_L32( sys_nb_base, hd, end ); /* TBD : Remove "magic" numbers */ *start = (*start & 0x7FFF) << 21; end = ((end & 0x7F) + 1) << 21; *size = (end > *start) ? end - *start : 0;}/************************************************************************ * config_sysctrl ************************************************************************/static UINT32config_sysctrl( void ){ /* If CPU is big endian, we need to handle endianness due to * PCI being little endian. * * We have chosen the following setup of MSC01 * * PCI device doing DMA : * MSC01 swaps byte lanes. * * CPU accesses PCI device : * MSC01 does NOT swap byte lanes. * * This means that software must do the following : * * Word access : Do nothing. * Halfword access : Software must invert bit 1 of address. * Byte access : Software must invert 2 msb of address. * * Above setup has been completed in msc01_core.S */ /* Set up changes since early setup in msc01_core.S */ REG(MSC01_PCI_REG_BASE, MSC01_PCI_BAR0) = -sc_calc_pwr2(sys_ramsize); return OK;}/************************************************************************ * sc_calc_pwr2ramsize * Calculate least size in power of 2 that can hold arg ************************************************************************/static UINT32sc_calc_pwr2( UINT32 arg ){ UINT32 mysize; for ( mysize = 1; mysize < arg; mysize <<= 1) ; return mysize;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -