4xx_pcie.c

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

C
1,172
字号
			return 0x0000000c40000000ULL;		case 1:			return 0x0000000c80000000ULL;		case 2:			return 0x0000000cc0000000ULL;		}	}#endif#if defined(CONFIG_460EX) || defined(CONFIG_460GT)	if (port == 0)		return 0x0000000d00000000ULL;	else		return 0x0000000d20000000ULL;#endif}/* *  4xx boards as end point and root point setup *                    and *    testing inbound and out bound windows * *  4xx boards can be plugged into another 4xx boards or you can get PCI-E *  cable which can be used to setup loop back from one port to another port. *  Please rememeber that unless there is a endpoint plugged in to root port it *  will not initialize. It is the same in case of endpoint , unless there is *  root port attached it will not initialize. * *  In this release of software all the PCI-E ports are configured as either *  endpoint or rootpoint.In future we will have support for selective ports *  setup as endpoint and root point in single board. * *  Once your board came up as root point , you can verify by reading *  /proc/bus/pci/devices. Where you can see the configuration registers *  of end point device attached to the port. * *  Enpoint cofiguration can be verified by connecting 4xx board to any *  host or another 4xx board. Then try to scan the device. In case of *  linux use "lspci" or appripriate os command. * *  How do I verify the inbound and out bound windows ? (4xx to 4xx) *  in this configuration inbound and outbound windows are setup to access *  sram memroy area. SRAM is at 0x4 0000 0000 , on PLB bus. This address *  is mapped at 0x90000000. From u-boot prompt write data 0xb000 0000, *  This is waere your POM(PLB out bound memory window) mapped. then *  read the data from other 4xx board's u-boot prompt at address *  0x9000 0000(SRAM). Data should match. *  In case of inbound , write data to u-boot command prompt at 0xb000 0000 *  which is mapped to 0x4 0000 0000. Now on rootpoint yucca u-boot prompt check *  data at 0x9000 0000(SRAM).Data should match. */int ppc4xx_init_pcie_port(int port, int rootport){	static int core_init;	volatile u32 val = 0;	int attempts;	u64 addr;	u32 low, high;	if (!core_init) {		if (ppc4xx_init_pcie())			return -1;		++core_init;	}	/*	 * Initialize various parts of the PCI Express core for our port	 */	ppc4xx_init_pcie_port_hw(port, rootport);	/*	 * Notice: the following delay has critical impact on device	 * initialization - if too short (<50ms) the link doesn't get up.	 */	mdelay(100);	val = SDR_READ(SDRN_PESDR_RCSSTS(port));	if (val & (1 << 20)) {		printf("PCIE%d: PGRST failed %08x\n", port, val);		return -1;	}	/*	 * Verify link is up	 */	val = SDR_READ(SDRN_PESDR_LOOP(port));	if (!(val & 0x00001000)) {		printf("PCIE%d: link is not up.\n", port);		return -1;	}	/*	 * Setup UTL registers - but only on revA!	 * We use default settings for revB chip.	 */	if (!ppc440spe_revB())		ppc4xx_setup_utl(port);	/*	 * We map PCI Express configuration access into the 512MB regions	 */	addr = ppc4xx_get_cfgaddr(port);	low = U64_TO_U32_LOW(addr);	high = U64_TO_U32_HIGH(addr);	switch (port) {	case 0:		mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), high);		mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), low);		mtdcr(DCRN_PEGPL_CFGMSK(PCIE0), 0xe0000001); /* 512MB region, valid */		break;	case 1:		mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), high);		mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), low);		mtdcr(DCRN_PEGPL_CFGMSK(PCIE1), 0xe0000001); /* 512MB region, valid */		break;#if CFG_PCIE_NR_PORTS > 2	case 2:		mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), high);		mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), low);		mtdcr(DCRN_PEGPL_CFGMSK(PCIE2), 0xe0000001); /* 512MB region, valid */		break;#endif	}	/*	 * Check for VC0 active and assert RDY.	 */	attempts = 10;	while(!(SDR_READ(SDRN_PESDR_RCSSTS(port)) & (1 << 16))) {		if (!(attempts--)) {			printf("PCIE%d: VC0 not active\n", port);			return -1;		}		mdelay(1000);	}	SDR_WRITE(SDRN_PESDR_RCSSET(port),		  SDR_READ(SDRN_PESDR_RCSSET(port)) | 1 << 20);	mdelay(100);	return 0;}int ppc4xx_init_pcie_rootport(int port){	return ppc4xx_init_pcie_port(port, 1);}int ppc4xx_init_pcie_endport(int port){	return ppc4xx_init_pcie_port(port, 0);}void ppc4xx_setup_pcie_rootpoint(struct pci_controller *hose, int port){	volatile void *mbase = NULL;	volatile void *rmbase = NULL;	pci_set_ops(hose,		    pcie_read_config_byte,		    pcie_read_config_word,		    pcie_read_config_dword,		    pcie_write_config_byte,		    pcie_write_config_word,		    pcie_write_config_dword);	switch (port) {	case 0:		mbase = (u32 *)CFG_PCIE0_XCFGBASE;		rmbase = (u32 *)CFG_PCIE0_CFGBASE;		hose->cfg_data = (u8 *)CFG_PCIE0_CFGBASE;		break;	case 1:		mbase = (u32 *)CFG_PCIE1_XCFGBASE;		rmbase = (u32 *)CFG_PCIE1_CFGBASE;		hose->cfg_data = (u8 *)CFG_PCIE1_CFGBASE;		break;#if CFG_PCIE_NR_PORTS > 2	case 2:		mbase = (u32 *)CFG_PCIE2_XCFGBASE;		rmbase = (u32 *)CFG_PCIE2_CFGBASE;		hose->cfg_data = (u8 *)CFG_PCIE2_CFGBASE;		break;#endif	}	/*	 * Set bus numbers on our root port	 */	out_8((u8 *)mbase + PCI_PRIMARY_BUS, 0);	out_8((u8 *)mbase + PCI_SECONDARY_BUS, 1);	out_8((u8 *)mbase + PCI_SUBORDINATE_BUS, 1);	/*	 * Set up outbound translation to hose->mem_space from PLB	 * addresses at an offset of 0xd_0000_0000.  We set the low	 * bits of the mask to 11 to turn off splitting into 8	 * subregions and to enable the outbound translation.	 */	out_le32(mbase + PECFG_POM0LAH, 0x00000000);	out_le32(mbase + PECFG_POM0LAL, CFG_PCIE_MEMBASE +		 port * CFG_PCIE_MEMSIZE);	debug("PECFG_POM0LA=%08x.%08x\n", in_le32(mbase + PECFG_POM0LAH),	      in_le32(mbase + PECFG_POM0LAL));	switch (port) {	case 0:		mtdcr(DCRN_PEGPL_OMR1BAH(PCIE0), CFG_PCIE_ADDR_HIGH);		mtdcr(DCRN_PEGPL_OMR1BAL(PCIE0), CFG_PCIE_MEMBASE +		      port * CFG_PCIE_MEMSIZE);		mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE0), 0x7fffffff);		mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE0),		      ~(CFG_PCIE_MEMSIZE - 1) | 3);		debug("0:PEGPL_OMR1BA=%08x.%08x MSK=%08x.%08x\n",		      mfdcr(DCRN_PEGPL_OMR1BAH(PCIE0)),		      mfdcr(DCRN_PEGPL_OMR1BAL(PCIE0)),		      mfdcr(DCRN_PEGPL_OMR1MSKH(PCIE0)),		      mfdcr(DCRN_PEGPL_OMR1MSKL(PCIE0)));		break;	case 1:		mtdcr(DCRN_PEGPL_OMR1BAH(PCIE1), CFG_PCIE_ADDR_HIGH);		mtdcr(DCRN_PEGPL_OMR1BAL(PCIE1), CFG_PCIE_MEMBASE +		      port * CFG_PCIE_MEMSIZE);		mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE1), 0x7fffffff);		mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE1),		      ~(CFG_PCIE_MEMSIZE - 1) | 3);		debug("1:PEGPL_OMR1BA=%08x.%08x MSK=%08x.%08x\n",		      mfdcr(DCRN_PEGPL_OMR1BAH(PCIE1)),		      mfdcr(DCRN_PEGPL_OMR1BAL(PCIE1)),		      mfdcr(DCRN_PEGPL_OMR1MSKH(PCIE1)),		      mfdcr(DCRN_PEGPL_OMR1MSKL(PCIE1)));		break;#if CFG_PCIE_NR_PORTS > 2	case 2:		mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2), CFG_PCIE_ADDR_HIGH);		mtdcr(DCRN_PEGPL_OMR1BAL(PCIE2), CFG_PCIE_MEMBASE +		      port * CFG_PCIE_MEMSIZE);		mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE2), 0x7fffffff);		mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE2),		      ~(CFG_PCIE_MEMSIZE - 1) | 3);		debug("2:PEGPL_OMR1BA=%08x.%08x MSK=%08x.%08x\n",		      mfdcr(DCRN_PEGPL_OMR1BAH(PCIE2)),		      mfdcr(DCRN_PEGPL_OMR1BAL(PCIE2)),		      mfdcr(DCRN_PEGPL_OMR1MSKH(PCIE2)),		      mfdcr(DCRN_PEGPL_OMR1MSKL(PCIE2)));		break;#endif	}	/* Set up 16GB inbound memory window at 0 */	out_le32(mbase + PCI_BASE_ADDRESS_0, 0);	out_le32(mbase + PCI_BASE_ADDRESS_1, 0);	out_le32(mbase + PECFG_BAR0HMPA, 0x7fffffc);	out_le32(mbase + PECFG_BAR0LMPA, 0);	out_le32(mbase + PECFG_PIM01SAH, 0xffff0000);	out_le32(mbase + PECFG_PIM01SAL, 0x00000000);	out_le32(mbase + PECFG_PIM0LAL, 0);	out_le32(mbase + PECFG_PIM0LAH, 0);	out_le32(mbase + PECFG_PIM1LAL, 0x00000000);	out_le32(mbase + PECFG_PIM1LAH, 0x00000004);	out_le32(mbase + PECFG_PIMEN, 0x1);	/* Enable I/O, Mem, and Busmaster cycles */	out_le16((u16 *)(mbase + PCI_COMMAND),		 in_le16((u16 *)(mbase + PCI_COMMAND)) |		 PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);	/* Set Device and Vendor Id */	out_le16(mbase + 0x200, 0xaaa0 + port);	out_le16(mbase + 0x202, 0xbed0 + port);	/* Set Class Code to PCI-PCI bridge and Revision Id to 1 */	out_le32(mbase + 0x208, 0x06040001);	printf("PCIE%d: successfully set as root-complex\n", port);}int ppc4xx_setup_pcie_endpoint(struct pci_controller *hose, int port){	volatile void *mbase = NULL;	int attempts = 0;	pci_set_ops(hose,		    pcie_read_config_byte,		    pcie_read_config_word,		    pcie_read_config_dword,		    pcie_write_config_byte,		    pcie_write_config_word,		    pcie_write_config_dword);	switch (port) {	case 0:		mbase = (u32 *)CFG_PCIE0_XCFGBASE;		hose->cfg_data = (u8 *)CFG_PCIE0_CFGBASE;		break;	case 1:		mbase = (u32 *)CFG_PCIE1_XCFGBASE;		hose->cfg_data = (u8 *)CFG_PCIE1_CFGBASE;		break;#if defined(CFG_PCIE2_CFGBASE)	case 2:		mbase = (u32 *)CFG_PCIE2_XCFGBASE;		hose->cfg_data = (u8 *)CFG_PCIE2_CFGBASE;		break;#endif	}	/*	 * Set up outbound translation to hose->mem_space from PLB	 * addresses at an offset of 0xd_0000_0000.  We set the low	 * bits of the mask to 11 to turn off splitting into 8	 * subregions and to enable the outbound translation.	 */	out_le32(mbase + PECFG_POM0LAH, 0x00001ff8);	out_le32(mbase + PECFG_POM0LAL, 0x00001000);	switch (port) {	case 0:		mtdcr(DCRN_PEGPL_OMR1BAH(PCIE0), CFG_PCIE_ADDR_HIGH);		mtdcr(DCRN_PEGPL_OMR1BAL(PCIE0), CFG_PCIE_MEMBASE +		      port * CFG_PCIE_MEMSIZE);		mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE0), 0x7fffffff);		mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE0),		      ~(CFG_PCIE_MEMSIZE - 1) | 3);		break;	case 1:		mtdcr(DCRN_PEGPL_OMR1BAH(PCIE1), CFG_PCIE_ADDR_HIGH);		mtdcr(DCRN_PEGPL_OMR1BAL(PCIE1), CFG_PCIE_MEMBASE +		      port * CFG_PCIE_MEMSIZE);		mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE1), 0x7fffffff);		mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE1),		      ~(CFG_PCIE_MEMSIZE - 1) | 3);		break;#if CFG_PCIE_NR_PORTS > 2	case 2:		mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2), CFG_PCIE_ADDR_HIGH);		mtdcr(DCRN_PEGPL_OMR1BAL(PCIE2), CFG_PCIE_MEMBASE +		      port * CFG_PCIE_MEMSIZE);		mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE2), 0x7fffffff);		mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE2),		      ~(CFG_PCIE_MEMSIZE - 1) | 3);		break;#endif	}	/* Set up 64MB inbound memory window at 0 */	out_le32(mbase + PCI_BASE_ADDRESS_0, 0);	out_le32(mbase + PCI_BASE_ADDRESS_1, 0);	out_le32(mbase + PECFG_PIM01SAH, 0xffffffff);	out_le32(mbase + PECFG_PIM01SAL, 0xfc000000);	/* Setup BAR0 */	out_le32(mbase + PECFG_BAR0HMPA, 0x7fffffff);	out_le32(mbase + PECFG_BAR0LMPA, 0xfc000000 | PCI_BASE_ADDRESS_MEM_TYPE_64);	/* Disable BAR1 & BAR2 */	out_le32(mbase + PECFG_BAR1MPA, 0);	out_le32(mbase + PECFG_BAR2HMPA, 0);	out_le32(mbase + PECFG_BAR2LMPA, 0);	out_le32(mbase + PECFG_PIM0LAL, U64_TO_U32_LOW(CFG_PCIE_INBOUND_BASE));	out_le32(mbase + PECFG_PIM0LAH, U64_TO_U32_HIGH(CFG_PCIE_INBOUND_BASE));	out_le32(mbase + PECFG_PIMEN, 0x1);	/* Enable I/O, Mem, and Busmaster cycles */	out_le16((u16 *)(mbase + PCI_COMMAND),		 in_le16((u16 *)(mbase + PCI_COMMAND)) |		 PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);	out_le16(mbase + 0x200, 0xcaad);		/* Setting vendor ID */	out_le16(mbase + 0x202, 0xfeed);		/* Setting device ID */	/* Set Class Code to Processor/PPC */	out_le32(mbase + 0x208, 0x0b200001);	attempts = 10;	while(!(SDR_READ(SDRN_PESDR_RCSSTS(port)) & (1 << 8))) {		if (!(attempts--)) {			printf("PCIE%d: BME not active\n", port);			return -1;		}		mdelay(1000);	}	printf("PCIE%d: successfully set as endpoint\n", port);	return 0;}#endif /* CONFIG_440SPE && CONFIG_PCI */

⌨️ 快捷键说明

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