4xx_pcie.c

来自「最新版的u-boot,2008-10-18发布」· C语言 代码 · 共 1,172 行 · 第 1/3 页

C
1,172
字号
			time_out--;			udelay(1);		} else			break;	}	if (!time_out) {		printf("PCIE: VCO output not locked\n");		return -1;	}	return 0;}#endif#if defined(CONFIG_460EX) || defined(CONFIG_460GT)static void ppc4xx_setup_utl(u32 port){	volatile void *utl_base = NULL;	/*	 * Map UTL registers at 0x0801_n000 (4K 0xfff mask) PEGPLn_REGMSK	 */	switch (port) {	case 0:		mtdcr(DCRN_PEGPL_REGBAH(PCIE0), U64_TO_U32_HIGH(CFG_PCIE0_UTLBASE));		mtdcr(DCRN_PEGPL_REGBAL(PCIE0), U64_TO_U32_LOW(CFG_PCIE0_UTLBASE));		mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001);	/* BAM 11100000=4KB */		mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0);		break;	case 1:		mtdcr(DCRN_PEGPL_REGBAH(PCIE1), U64_TO_U32_HIGH(CFG_PCIE0_UTLBASE));		mtdcr(DCRN_PEGPL_REGBAL(PCIE1), U64_TO_U32_LOW(CFG_PCIE0_UTLBASE)			+ 0x1000);		mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001);	/* BAM 11100000=4KB */		mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0);		break;	}	utl_base = (unsigned int *)(CFG_PCIE_BASE + 0x1000 * port);	/*	 * Set buffer allocations and then assert VRB and TXE.	 */	out_be32(utl_base + PEUTL_PBCTL, 0x0800000c);	/* PLBME, CRRE */	out_be32(utl_base + PEUTL_OUTTR, 0x08000000);	out_be32(utl_base + PEUTL_INTR, 0x02000000);	out_be32(utl_base + PEUTL_OPDBSZ, 0x04000000);	/* OPD = 512 Bytes */	out_be32(utl_base + PEUTL_PBBSZ, 0x00000000);	/* Max 512 Bytes */	out_be32(utl_base + PEUTL_IPHBSZ, 0x02000000);	out_be32(utl_base + PEUTL_IPDBSZ, 0x04000000);	/* IPD = 512 Bytes */	out_be32(utl_base + PEUTL_RCIRQEN, 0x00f00000);	out_be32(utl_base + PEUTL_PCTL, 0x80800066);	/* VRB,TXE,timeout=default */}/* * TODO: double check PCI express SDR based on the latest user manual *		 Some registers specified here no longer exist.. has to be *		 updated based on the final EAS spec. */static int check_error(void){	u32 valPE0, valPE1;	int err = 0;	valPE0 = SDR_READ(SDRN_PESDR_RCSSET(0));	valPE1 = SDR_READ(SDRN_PESDR_RCSSET(1));	/* SDR0_PExRCSSET rstgu */	if (!(valPE0 & PESDRx_RCSSET_RSTGU) || !(valPE1 & PESDRx_RCSSET_RSTGU)) {		printf("PCIE:  SDR0_PExRCSSET rstgu error\n");		err = -1;	}	/* SDR0_PExRCSSET rstdl */	if (!(valPE0 & PESDRx_RCSSET_RSTDL) || !(valPE1 & PESDRx_RCSSET_RSTDL)) {		printf("PCIE:  SDR0_PExRCSSET rstdl error\n");		err = -1;	}	/* SDR0_PExRCSSET rstpyn */	if ((valPE0 & PESDRx_RCSSET_RSTPYN) || (valPE1 & PESDRx_RCSSET_RSTPYN)) {		printf("PCIE:  SDR0_PExRCSSET rstpyn error\n");		err = -1;	}	/* SDR0_PExRCSSET hldplb */	if ((valPE0 & PESDRx_RCSSET_HLDPLB) || (valPE1 & PESDRx_RCSSET_HLDPLB)) {		printf("PCIE:  SDR0_PExRCSSET hldplb error\n");		err = -1;	}	/* SDR0_PExRCSSET rdy */	if ((valPE0 & PESDRx_RCSSET_RDY) || (valPE1 & PESDRx_RCSSET_RDY)) {		printf("PCIE:  SDR0_PExRCSSET rdy error\n");		err = -1;	}	return err;}/* * Initialize PCI Express core as described in User Manual * TODO: double check PE SDR PLL Register with the updated user manual. */int ppc4xx_init_pcie(void){	if (check_error())		return -1;	return 0;}#endif /* CONFIG_460EX */#if defined(CONFIG_405EX)static void ppc4xx_setup_utl(u32 port){	u32 utl_base;	/*	 * Map UTL registers at 0xef4f_n000 (4K 0xfff mask) PEGPLn_REGMSK	 */	switch (port) {	case 0:		mtdcr(DCRN_PEGPL_REGBAH(PCIE0), 0x00000000);		mtdcr(DCRN_PEGPL_REGBAL(PCIE0), CFG_PCIE0_UTLBASE);		mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001); /* 4k region, valid */		mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0);		break;	case 1:		mtdcr(DCRN_PEGPL_REGBAH(PCIE1), 0x00000000);		mtdcr(DCRN_PEGPL_REGBAL(PCIE1), CFG_PCIE1_UTLBASE);		mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001); /* 4k region, valid */		mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0);		break;	}	utl_base = (port==0) ? CFG_PCIE0_UTLBASE : CFG_PCIE1_UTLBASE;	/*	 * Set buffer allocations and then assert VRB and TXE.	 */	out_be32((u32 *)(utl_base + PEUTL_OUTTR),   0x02000000);	out_be32((u32 *)(utl_base + PEUTL_INTR),    0x02000000);	out_be32((u32 *)(utl_base + PEUTL_OPDBSZ),  0x04000000);	out_be32((u32 *)(utl_base + PEUTL_PBBSZ),   0x21000000);	out_be32((u32 *)(utl_base + PEUTL_IPHBSZ),  0x02000000);	out_be32((u32 *)(utl_base + PEUTL_IPDBSZ),  0x04000000);	out_be32((u32 *)(utl_base + PEUTL_RCIRQEN), 0x00f00000);	out_be32((u32 *)(utl_base + PEUTL_PCTL),    0x80800066);	out_be32((u32 *)(utl_base + PEUTL_PBCTL),   0x0800000c);	out_be32((u32 *)(utl_base + PEUTL_RCSTA),		 in_be32((u32 *)(utl_base + PEUTL_RCSTA)) | 0x000040000);}int ppc4xx_init_pcie(void){	/*	 * Nothing to do on 405EX	 */	return 0;}#endif /* CONFIG_405EX *//* * Board-specific pcie initialization * Platform code can reimplement ppc4xx_init_pcie_port_hw() if needed *//* * Initialize various parts of the PCI Express core for our port: * * - Set as a root port and enable max width *   (PXIE0 -> X8, PCIE1 and PCIE2 -> X4). * - Set up UTL configuration. * - Increase SERDES drive strength to levels suggested by AMCC. * - De-assert RSTPYN, RSTDL and RSTGU. * * NOTICE for 440SPE revB chip: PESDRn_UTLSET2 is not set - we leave it * with default setting 0x11310000. The register has new fields, * PESDRn_UTLSET2[LKINE] in particular: clearing it leads to PCIE core * hang. */#if defined(CONFIG_440SPE)int __ppc4xx_init_pcie_port_hw(int port, int rootport){	u32 val = 1 << 24;	u32 utlset1;	if (rootport) {		val = PTYPE_ROOT_PORT << 20;		utlset1 = 0x21222222;	} else {		val = PTYPE_LEGACY_ENDPOINT << 20;		utlset1 = 0x20222222;	}	if (port == 0)		val |= LNKW_X8 << 12;	else		val |= LNKW_X4 << 12;	SDR_WRITE(SDRN_PESDR_DLPSET(port), val);	SDR_WRITE(SDRN_PESDR_UTLSET1(port), utlset1);	if (!ppc440spe_revB())		SDR_WRITE(SDRN_PESDR_UTLSET2(port), 0x11000000);	SDR_WRITE(SDRN_PESDR_HSSL0SET1(port), 0x35000000);	SDR_WRITE(SDRN_PESDR_HSSL1SET1(port), 0x35000000);	SDR_WRITE(SDRN_PESDR_HSSL2SET1(port), 0x35000000);	SDR_WRITE(SDRN_PESDR_HSSL3SET1(port), 0x35000000);	if (port == 0) {		SDR_WRITE(PESDR0_HSSL4SET1, 0x35000000);		SDR_WRITE(PESDR0_HSSL5SET1, 0x35000000);		SDR_WRITE(PESDR0_HSSL6SET1, 0x35000000);		SDR_WRITE(PESDR0_HSSL7SET1, 0x35000000);	}	SDR_WRITE(SDRN_PESDR_RCSSET(port), (SDR_READ(SDRN_PESDR_RCSSET(port)) &					    ~(1 << 24 | 1 << 16)) | 1 << 12);	return 0;}#endif /* CONFIG_440SPE */#if defined(CONFIG_460EX) || defined(CONFIG_460GT)int __ppc4xx_init_pcie_port_hw(int port, int rootport){	u32 val;	u32 utlset1;	if (rootport)		val = PTYPE_ROOT_PORT << 20;	else		val = PTYPE_LEGACY_ENDPOINT << 20;	if (port == 0) {		val |= LNKW_X1 << 12;		utlset1 = 0x20000000;	} else {		val |= LNKW_X4 << 12;		utlset1 = 0x20101101;	}	SDR_WRITE(SDRN_PESDR_DLPSET(port), val);	SDR_WRITE(SDRN_PESDR_UTLSET1(port), utlset1);	SDR_WRITE(SDRN_PESDR_UTLSET2(port), 0x01210000);	switch (port) {	case 0:		SDR_WRITE(PESDR0_L0CDRCTL, 0x00003230);		SDR_WRITE(PESDR0_L0DRV, 0x00000130);		SDR_WRITE(PESDR0_L0CLK, 0x00000006);		SDR_WRITE(PESDR0_PHY_CTL_RST,0x10000000);		break;	case 1:		SDR_WRITE(PESDR1_L0CDRCTL, 0x00003230);		SDR_WRITE(PESDR1_L1CDRCTL, 0x00003230);		SDR_WRITE(PESDR1_L2CDRCTL, 0x00003230);		SDR_WRITE(PESDR1_L3CDRCTL, 0x00003230);		SDR_WRITE(PESDR1_L0DRV, 0x00000130);		SDR_WRITE(PESDR1_L1DRV, 0x00000130);		SDR_WRITE(PESDR1_L2DRV, 0x00000130);		SDR_WRITE(PESDR1_L3DRV, 0x00000130);		SDR_WRITE(PESDR1_L0CLK, 0x00000006);		SDR_WRITE(PESDR1_L1CLK, 0x00000006);		SDR_WRITE(PESDR1_L2CLK, 0x00000006);		SDR_WRITE(PESDR1_L3CLK, 0x00000006);		SDR_WRITE(PESDR1_PHY_CTL_RST,0x10000000);		break;	}	SDR_WRITE(SDRN_PESDR_RCSSET(port), SDR_READ(SDRN_PESDR_RCSSET(port)) |		  (PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTPYN));	/* Poll for PHY reset */	switch (port) {	case 0:		while (!(SDR_READ(PESDR0_RSTSTA) & 0x1))			udelay(10);		break;	case 1:		while (!(SDR_READ(PESDR1_RSTSTA) & 0x1))			udelay(10);		break;	}	SDR_WRITE(SDRN_PESDR_RCSSET(port),		  (SDR_READ(SDRN_PESDR_RCSSET(port)) &		   ~(PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL)) |		  PESDRx_RCSSET_RSTPYN);	return 0;}#endif /* CONFIG_440SPE */#if defined(CONFIG_405EX)int __ppc4xx_init_pcie_port_hw(int port, int rootport){	u32 val;	if (rootport)		val = 0x00401000;	else		val = 0x00101000;	SDR_WRITE(SDRN_PESDR_DLPSET(port), val);	SDR_WRITE(SDRN_PESDR_UTLSET1(port), 0x00000000);	SDR_WRITE(SDRN_PESDR_UTLSET2(port), 0x01010000);	SDR_WRITE(SDRN_PESDR_PHYSET1(port), 0x720F0000);	SDR_WRITE(SDRN_PESDR_PHYSET2(port), 0x70600003);	/* Assert the PE0_PHY reset */	SDR_WRITE(SDRN_PESDR_RCSSET(port), 0x01010000);	udelay(1000);	/* deassert the PE0_hotreset */	if (is_end_point(port))		SDR_WRITE(SDRN_PESDR_RCSSET(port), 0x01111000);	else		SDR_WRITE(SDRN_PESDR_RCSSET(port), 0x01101000);	/* poll for phy !reset */	while (!(SDR_READ(SDRN_PESDR_PHYSTA(port)) & 0x00001000))		;	/* deassert the PE0_gpl_utl_reset */	SDR_WRITE(SDRN_PESDR_RCSSET(port), 0x00101000);	if (port == 0)		mtdcr(DCRN_PEGPL_CFG(PCIE0), 0x10000000);  /* guarded on */	else		mtdcr(DCRN_PEGPL_CFG(PCIE1), 0x10000000);  /* guarded on */	return 0;}#endif /* CONFIG_405EX */int ppc4xx_init_pcie_port_hw(int port, int rootport)__attribute__((weak, alias("__ppc4xx_init_pcie_port_hw")));/* * We map PCI Express configuration access into the 512MB regions * * NOTICE: revB is very strict about PLB real addressess and ranges to * be mapped for config space; it seems to only work with d_nnnn_nnnn * range (hangs the core upon config transaction attempts when set * otherwise) while revA uses c_nnnn_nnnn. * * For 440SPe revA: *     PCIE0: 0xc_4000_0000 *     PCIE1: 0xc_8000_0000 *     PCIE2: 0xc_c000_0000 * * For 440SPe revB: *     PCIE0: 0xd_0000_0000 *     PCIE1: 0xd_2000_0000 *     PCIE2: 0xd_4000_0000 * * For 405EX: *     PCIE0: 0xa000_0000 *     PCIE1: 0xc000_0000 * * For 460EX/GT: *     PCIE0: 0xd_0000_0000 *     PCIE1: 0xd_2000_0000 */static inline u64 ppc4xx_get_cfgaddr(int port){#if defined(CONFIG_405EX)	if (port == 0)		return (u64)CFG_PCIE0_CFGBASE;	else		return (u64)CFG_PCIE1_CFGBASE;#endif#if defined(CONFIG_440SPE)	if (ppc440spe_revB()) {		switch (port) {		default:	/* to satisfy compiler */		case 0:			return 0x0000000d00000000ULL;		case 1:			return 0x0000000d20000000ULL;		case 2:			return 0x0000000d40000000ULL;		}	} else {		switch (port) {		default:	/* to satisfy compiler */		case 0:

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?