diff options
| -rw-r--r-- | CHANGELOG | 15 | ||||
| -rw-r--r-- | board/amcc/yucca/yucca.c | 105 | ||||
| -rw-r--r-- | board/amcc/yucca/yucca.h | 3 | ||||
| -rw-r--r-- | cpu/ppc4xx/440spe_pcie.c | 414 | ||||
| -rw-r--r-- | cpu/ppc4xx/440spe_pcie.h | 11 | 
5 files changed, 516 insertions, 32 deletions
| @@ -2,6 +2,21 @@  Changes since U-Boot 1.1.4:  ====================================================================== +* PCIe endpoint support for AMCC Yucca 440SPe board +  Patch by Tirumala R Marri, 26 Aug 2006 + +* Improve DIMM detection for AMCC Yucca 440SPe board +  Improved the memory DIMM detection for the Yucca 440SPe board for +  the case where a memory DIMM is falsely detected as present. +  This issue is seen on some AMCC Yucca 440SPe validation boards if +  only one 512MB memory DIMM is installed, i.e. DIMM slot 0 is +  populated and DIMM slot 1 is empty.  In this case, U-Boot does +  not correctly detect that there is only one DIMM memory module +  installed and will falsely detect two DIMM memory modules are +  present and therefore U-Boot will not calculate the correct amount +  of total memory and u-boot will not booting up. +  Patch by Adam Graham, 24 Aug 2006 +  * Fix typo.  * Code cleanup diff --git a/board/amcc/yucca/yucca.c b/board/amcc/yucca/yucca.c index af12839c2..cd175265f 100644 --- a/board/amcc/yucca/yucca.c +++ b/board/amcc/yucca/yucca.c @@ -32,6 +32,10 @@  #include <asm-ppc/io.h>  #include "yucca.h" +#include "../cpu/ppc4xx/440spe_pcie.h" + +#undef PCIE_ENDPOINT +/* #define PCIE_ENDPOINT 1 */  void fpga_init (void); @@ -562,10 +566,11 @@ int checkboard (void)  static long int yucca_probe_for_dimms(void)  { -	long int 	dimm_installed[MAXDIMMS]; -	long int	dimm_num, probe_result; -	long int	dimms_found = 0; -	uchar		dimm_addr = IIC0_DIMM0_ADDR; +	int 	dimm_installed[MAXDIMMS]; +	int	dimm_num, result; +	int	dimms_found = 0; +	uchar	dimm_addr = IIC0_DIMM0_ADDR; +	uchar   dimm_spd_data[MAX_SPD_BYTES];  	for (dimm_num = 0; dimm_num < MAXDIMMS; dimm_num++) {  		/* check if there is a chip at the dimm address	*/ @@ -577,12 +582,28 @@ static long int yucca_probe_for_dimms(void)  				dimm_addr = IIC0_DIMM1_ADDR;  				break;  		} -		probe_result = i2c_probe(dimm_addr); -		if (probe_result == 0) { +		result = i2c_probe(dimm_addr); + +		memset(dimm_spd_data, 0, MAX_SPD_BYTES * sizeof(char)); +		if (result == 0) { +			/* read first byte of SPD data, if there is any data */ +			result = i2c_read(dimm_addr, 0, 1, dimm_spd_data, 1); + +			if (result == 0) { +				result = dimm_spd_data[0]; +				result = result > MAX_SPD_BYTES ? +						MAX_SPD_BYTES : result; +				result = i2c_read(dimm_addr, 0, 1, +							dimm_spd_data, result); +			} +		} + +		if ((result == 0) && +		    (dimm_spd_data[64] == MICRON_SPD_JEDEC_ID)) {  			dimm_installed[dimm_num] = TRUE;  			dimms_found++; -			debug("DIMM slot %d: DDR2 SDRAM detected\n",dimm_num); +			debug("DIMM slot %d: DDR2 SDRAM detected\n", dimm_num);  		} else {  			dimm_installed[dimm_num] = FALSE;  			debug("DIMM slot %d: Not populated or cannot sucessfully probe the DIMM\n", dimm_num); @@ -1012,6 +1033,57 @@ void yucca_setup_pcie_fpga_rootpoint(int port)  	out_be16((u16 *)FPGA_REG1C, reset_off | in_be16((u16 *)FPGA_REG1C));  } +/* + * For the given slot, set endpoint mode, send power to the slot, + * turn on the green LED and turn off the yellow LED, enable the clock + * .In end point mode reset bit is  read only. + */ +void yucca_setup_pcie_fpga_endpoint(int port) +{ +	u16 power, clock, green_led, yellow_led, reset_off, rootpoint, endpoint; + +	switch(port) { +	case 0: +		rootpoint   = FPGA_REG1C_PE0_ROOTPOINT; +		endpoint    = 0; +		power 	    = FPGA_REG1A_PE0_PWRON; +		green_led   = FPGA_REG1A_PE0_GLED; +		clock 	    = FPGA_REG1A_PE0_REFCLK_ENABLE; +		yellow_led  = FPGA_REG1A_PE0_YLED; +		reset_off   = FPGA_REG1C_PE0_PERST; +		break; +	case 1: +		rootpoint   = 0; +		endpoint    = FPGA_REG1C_PE1_ENDPOINT; +		power 	    = FPGA_REG1A_PE1_PWRON; +		green_led   = FPGA_REG1A_PE1_GLED; +		clock 	    = FPGA_REG1A_PE1_REFCLK_ENABLE; +		yellow_led  = FPGA_REG1A_PE1_YLED; +		reset_off   = FPGA_REG1C_PE1_PERST; +		break; +	case 2: +		rootpoint   = 0; +		endpoint    = FPGA_REG1C_PE2_ENDPOINT; +		power 	    = FPGA_REG1A_PE2_PWRON; +		green_led   = FPGA_REG1A_PE2_GLED; +		clock 	    = FPGA_REG1A_PE2_REFCLK_ENABLE; +		yellow_led  = FPGA_REG1A_PE2_YLED; +		reset_off   = FPGA_REG1C_PE2_PERST; +		break; + +	default: +		return; +	} + +	out_be16((u16 *)FPGA_REG1A, +		 ~(power | clock | green_led) & +		 (yellow_led | in_be16((u16 *)FPGA_REG1A))); + +	out_be16((u16 *)FPGA_REG1C, +		 ~(rootpoint | reset_off) & +		 (endpoint | in_be16((u16 *)FPGA_REG1C))); +} +  static struct pci_controller pcie_hose[3] = {{0},{0},{0}}; @@ -1031,9 +1103,13 @@ void pcie_setup_hoses(void)  		if (!yucca_pcie_card_present(i))  			continue; +#ifdef PCIE_ENDPOINT + 		yucca_setup_pcie_fpga_endpoint(i); + 		if (ppc440spe_init_pcie_endport(i)) { +#else  		yucca_setup_pcie_fpga_rootpoint(i); -  		if (ppc440spe_init_pcie_rootport(i)) { +#endif  			printf("PCIE%d: initialization failed\n", i);  			continue;  		} @@ -1053,8 +1129,19 @@ void pcie_setup_hoses(void)  		hose->region_count = 1;  		pci_register_hose(hose); -		ppc440spe_setup_pcie(hose, i); +#ifdef PCIE_ENDPOINT +		ppc440spe_setup_pcie_endpoint(hose, i); +		/* +		 * Reson for no scanning is endpoint can not generate +		 * upstream configuration accesses. +		 */ +#else +		ppc440spe_setup_pcie_rootpoint(hose, i); +		/* +		 * Config access can only go down stream +		 */  		hose->last_busno = pci_hose_scan(hose); +#endif  	}  }  #endif	/* defined(CONFIG_PCI) */ diff --git a/board/amcc/yucca/yucca.h b/board/amcc/yucca/yucca.h index 66f75847d..4d13021f3 100644 --- a/board/amcc/yucca/yucca.h +++ b/board/amcc/yucca/yucca.h @@ -60,6 +60,9 @@ extern "C" {  #define NUM_TLB_ENTRIES          64 +/* MICRON SPD JEDEC ID Code (first byte) - SPD data byte [64] */ +#define MICRON_SPD_JEDEC_ID 0x2c +  /*----------------------------------------------------------------------------+  | TLB specific defines.  +----------------------------------------------------------------------------*/ diff --git a/cpu/ppc4xx/440spe_pcie.c b/cpu/ppc4xx/440spe_pcie.c index b2621c2ec..6130cd283 100644 --- a/cpu/ppc4xx/440spe_pcie.c +++ b/cpu/ppc4xx/440spe_pcie.c @@ -270,7 +270,7 @@ int ppc440spe_init_pcie(void)  	SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) & ~(1 << 24));  	udelay(3); -	while(time_out) { +	while (time_out) {  		if (!(SDR_READ(PESDR0_PLLLCT3) & 0x10000000)) {  			time_out--;  			udelay(1); @@ -284,6 +284,40 @@ int ppc440spe_init_pcie(void)  	return 0;  } +/* + *  Yucca board as End point and root point setup + *                    and + *    testing inbound and out bound windows + * + *  YUCCA board can be plugged into another yucca board 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 Yucca board to any + *  host or another yucca 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 ?(yucca to yucca) + *  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 yucca 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 ppc440spe_init_pcie_rootport(int port)  {  	static int core_init; @@ -326,7 +360,7 @@ int ppc440spe_init_pcie_rootport(int port)  		SDR_WRITE(PESDR0_HSSL6SET1, 0x35000000);  		SDR_WRITE(PESDR0_HSSL7SET1, 0x35000000);  		SDR_WRITE(PESDR0_RCSSET, -			(SDR_READ(PESDR0_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12); +			  (SDR_READ(PESDR0_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);  		break;  	case 1: @@ -339,7 +373,7 @@ int ppc440spe_init_pcie_rootport(int port)  		SDR_WRITE(PESDR1_HSSL2SET1, 0x35000000);  		SDR_WRITE(PESDR1_HSSL3SET1, 0x35000000);  		SDR_WRITE(PESDR1_RCSSET, -			(SDR_READ(PESDR1_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12); +			  (SDR_READ(PESDR1_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);  		break;  	case 2: @@ -352,6 +386,225 @@ int ppc440spe_init_pcie_rootport(int port)  		SDR_WRITE(PESDR2_HSSL2SET1, 0x35000000);  		SDR_WRITE(PESDR2_HSSL3SET1, 0x35000000);  		SDR_WRITE(PESDR2_RCSSET, +			  (SDR_READ(PESDR2_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12); +		break; +	} +	/* +	 * Notice: the following delay has critical impact on device +	 * initialization - if too short (<50ms) the link doesn't get up. +	 */ +	mdelay(100); + +	switch (port) { +	case 0: +		val = SDR_READ(PESDR0_RCSSTS); +		break; +	case 1: +		val = SDR_READ(PESDR1_RCSSTS); +		break; +	case 2: +		val = SDR_READ(PESDR2_RCSSTS); +		break; +	} + +	if (val & (1 << 20)) { +		printf("PCIE%d: PGRST failed %08x\n", port, val); +		return -1; +	} + +	/* +	 * Verify link is up +	 */ +	val = 0; +	switch (port) { +	case 0: +		val = SDR_READ(PESDR0_LOOP); +		break; +	case 1: +		val = SDR_READ(PESDR1_LOOP); +		break; +	case 2: +		val = SDR_READ(PESDR2_LOOP); +		break; +	} +	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()) +		ppc440spe_setup_utl(port); + +	/* +	 * 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 revA: +	 *     PCIE0: 0xc_4000_0000 +	 *     PCIE1: 0xc_8000_0000 +	 *     PCIE2: 0xc_c000_0000 +	 * +	 * For revB: +	 *     PCIE0: 0xd_0000_0000 +	 *     PCIE1: 0xd_2000_0000 +	 *     PCIE2: 0xd_4000_0000 +	 */ + +	switch (port) { +	case 0: +		if (ppc440spe_revB()) { +			mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000d); +			mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x00000000); +		} else { +			/* revA */ +			mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000c); +			mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x40000000); +		} +		mtdcr(DCRN_PEGPL_CFGMSK(PCIE0), 0xe0000001); /* 512MB region, valid */ +		break; + +	case 1: +		if (ppc440spe_revB()) { +			mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000d); +			mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x20000000); +		} else { +			mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000c); +			mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x80000000); +		} +		mtdcr(DCRN_PEGPL_CFGMSK(PCIE1), 0xe0000001); /* 512MB region, valid */ +		break; + +	case 2: +		if (ppc440spe_revB()) { +			mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000d); +			mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0x40000000); +		} else { +			mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000c); +			mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0xc0000000); +		} +		mtdcr(DCRN_PEGPL_CFGMSK(PCIE2), 0xe0000001); /* 512MB region, valid */ +		break; +	} + +	/* +	 * Check for VC0 active and assert RDY. +	 */ +	attempts = 10; +	switch (port) { +	case 0: +		while(!(SDR_READ(PESDR0_RCSSTS) & (1 << 16))) { +			if (!(attempts--)) { +				printf("PCIE0: VC0 not active\n"); +				return -1; +			} +			mdelay(1000); +		} +		SDR_WRITE(PESDR0_RCSSET, SDR_READ(PESDR0_RCSSET) | 1 << 20); +		break; +	case 1: +		while(!(SDR_READ(PESDR1_RCSSTS) & (1 << 16))) { +			if (!(attempts--)) { +				printf("PCIE1: VC0 not active\n"); +				return -1; +			} +			mdelay(1000); +		} + +		SDR_WRITE(PESDR1_RCSSET, SDR_READ(PESDR1_RCSSET) | 1 << 20); +		break; +	case 2: +		while(!(SDR_READ(PESDR2_RCSSTS) & (1 << 16))) { +			if (!(attempts--)) { +				printf("PCIE2: VC0 not active\n"); +				return -1; +			} +			mdelay(1000); +		} + +		SDR_WRITE(PESDR2_RCSSET, SDR_READ(PESDR2_RCSSET) | 1 << 20); +		break; +	} +	mdelay(100); + +	return 0; +} + +int ppc440spe_init_pcie_endport(int port) +{ +	static int core_init; +	volatile u32 val = 0; +	int attempts; + +	if (!core_init) { +		++core_init; +		if (ppc440spe_init_pcie()) +			return -1; +	} + +	/* +	 * Initialize various parts of the PCI Express core for our port: +	 * +	 * - Set as a end 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 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. +	 */ +	switch (port) { +	case 0: +		SDR_WRITE(PESDR0_DLPSET,  1 << 24 | PTYPE_LEGACY_ENDPOINT << 20 | LNKW_X8 << 12); + +		SDR_WRITE(PESDR0_UTLSET1, 0x20222222); +		if (!ppc440spe_revB()) +			SDR_WRITE(PESDR0_UTLSET2, 0x11000000); +		SDR_WRITE(PESDR0_HSSL0SET1, 0x35000000); +		SDR_WRITE(PESDR0_HSSL1SET1, 0x35000000); +		SDR_WRITE(PESDR0_HSSL2SET1, 0x35000000); +		SDR_WRITE(PESDR0_HSSL3SET1, 0x35000000); +		SDR_WRITE(PESDR0_HSSL4SET1, 0x35000000); +		SDR_WRITE(PESDR0_HSSL5SET1, 0x35000000); +		SDR_WRITE(PESDR0_HSSL6SET1, 0x35000000); +		SDR_WRITE(PESDR0_HSSL7SET1, 0x35000000); +		SDR_WRITE(PESDR0_RCSSET, +			(SDR_READ(PESDR0_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12); +		break; + +	case 1: +		SDR_WRITE(PESDR1_DLPSET, 1 << 24 | PTYPE_LEGACY_ENDPOINT << 20 | LNKW_X4 << 12); +		SDR_WRITE(PESDR1_UTLSET1, 0x20222222); +		if (!ppc440spe_revB()) +			SDR_WRITE(PESDR1_UTLSET2, 0x11000000); +		SDR_WRITE(PESDR1_HSSL0SET1, 0x35000000); +		SDR_WRITE(PESDR1_HSSL1SET1, 0x35000000); +		SDR_WRITE(PESDR1_HSSL2SET1, 0x35000000); +		SDR_WRITE(PESDR1_HSSL3SET1, 0x35000000); +		SDR_WRITE(PESDR1_RCSSET, +			(SDR_READ(PESDR1_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12); +		break; + +	case 2: +		SDR_WRITE(PESDR2_DLPSET, 1 << 24 | PTYPE_LEGACY_ENDPOINT << 20 | LNKW_X4 << 12); +		SDR_WRITE(PESDR2_UTLSET1, 0x20222222); +		if (!ppc440spe_revB()) +			SDR_WRITE(PESDR2_UTLSET2, 0x11000000); +		SDR_WRITE(PESDR2_HSSL0SET1, 0x35000000); +		SDR_WRITE(PESDR2_HSSL1SET1, 0x35000000); +		SDR_WRITE(PESDR2_HSSL2SET1, 0x35000000); +		SDR_WRITE(PESDR2_HSSL3SET1, 0x35000000); +		SDR_WRITE(PESDR2_RCSSET,  			(SDR_READ(PESDR2_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);  		break;  	} @@ -418,7 +671,6 @@ int ppc440spe_init_pcie_rootport(int port)  	 *     PCIE1: 0xd_2000_0000  	 *     PCIE2: 0xd_4000_0000  	 */ -  	switch (port) {  	case 0:  		if (ppc440spe_revB()) { @@ -498,29 +750,33 @@ int ppc440spe_init_pcie_rootport(int port)  	return 0;  } -void ppc440spe_setup_pcie(struct pci_controller *hose, int port) +void ppc440spe_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); +		    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) { +	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;  	case 2:  		mbase = (u32 *)CFG_PCIE2_XCFGBASE; +		rmbase = (u32 *)CFG_PCIE2_CFGBASE;  		hose->cfg_data = (u8 *)CFG_PCIE2_CFGBASE;  		break;  	} @@ -528,14 +784,9 @@ void ppc440spe_setup_pcie(struct pci_controller *hose, int port)  	/*  	 * Set bus numbers on our root port  	 */ -	if (ppc440spe_revB()) { -		out_8((u8 *)mbase + PCI_PRIMARY_BUS, 0); -		out_8((u8 *)mbase + PCI_SECONDARY_BUS, 1); -		out_8((u8 *)mbase + PCI_SUBORDINATE_BUS, 1); -	} else { -		out_8((u8 *)mbase + PCI_PRIMARY_BUS, 0); -		out_8((u8 *)mbase + PCI_SECONDARY_BUS, 0); -	} +	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 @@ -544,8 +795,7 @@ void ppc440spe_setup_pcie(struct pci_controller *hose, int port)  	 * 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)); +	out_le32(mbase + PECFG_POM0LAL, 0x00000000);  	switch (port) {  	case 0: @@ -579,14 +829,134 @@ void ppc440spe_setup_pcie(struct pci_controller *hose, int port)  	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); +	printf("PCIE:%d successfully set as rootpoint\n",port); +} + +int ppc440spe_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; +	case 2: +		mbase = (u32 *)CFG_PCIE2_XCFGBASE; +		hose->cfg_data = (u8 *)CFG_PCIE2_CFGBASE; +		break; +	} + +	/* +	 * 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),  0x0000000d); +		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),  0x0000000d); +		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; +	case 2: +		mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2),  0x0000000d); +		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; +	} + +	/* 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_PIM0LAL, 0x00000000); +	out_le32(mbase + PECFG_PIM0LAH, 0x00000004);	/* pointing to SRAM */ +	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 */ +	attempts = 10; +	switch (port) { +	case 0: +		while (!(SDR_READ(PESDR0_RCSSTS) & (1 << 8))) { +			if (!(attempts--)) { +				printf("PCIE0: BMEN is  not active\n"); +				return -1; +			} +			mdelay(1000); +		} +		break; +	case 1: +		while (!(SDR_READ(PESDR1_RCSSTS) & (1 << 8))) { +			if (!(attempts--)) { +				printf("PCIE1: BMEN is not active\n"); +				return -1; +			} +			mdelay(1000); +		} +		break; +	case 2: +		while (!(SDR_READ(PESDR2_RCSSTS) & (1 << 8))) { +			if (!(attempts--)) { +				printf("PCIE2: BMEN is  not active\n"); +				return -1; +			} +			mdelay(1000); +		} +		break; +	} +	printf("PCIE:%d successfully set as endpoint\n",port); + +	return 0;  }  #endif /* CONFIG_PCI */  #endif /* CONFIG_440SPE */ diff --git a/cpu/ppc4xx/440spe_pcie.h b/cpu/ppc4xx/440spe_pcie.h index 47df7620a..2becc7772 100644 --- a/cpu/ppc4xx/440spe_pcie.h +++ b/cpu/ppc4xx/440spe_pcie.h @@ -139,9 +139,17 @@   */  #define PECFG_BAR0LMPA		0x210  #define PECFG_BAR0HMPA		0x214 +#define PECFG_BAR1MPA		0x218 +#define PECFG_BAR2MPA		0x220 +  #define PECFG_PIMEN		0x33c  #define PECFG_PIM0LAL		0x340  #define PECFG_PIM0LAH		0x344 +#define PECFG_PIM1LAL     	0x348 +#define PECFG_PIM1LAH     	0x34c +#define PECFG_PIM01SAL		0x350 +#define PECFG_PIM01SAH		0x354 +  #define PECFG_POM0LAL		0x380  #define PECFG_POM0LAH		0x384 @@ -156,7 +164,8 @@  int ppc440spe_init_pcie(void);  int ppc440spe_init_pcie_rootport(int port);  void yucca_setup_pcie_fpga_rootpoint(int port); -void ppc440spe_setup_pcie(struct pci_controller *hose, int port); +void ppc440spe_setup_pcie_rootpoint(struct pci_controller *hose, int port); +int ppc440spe_setup_pcie_endpoint(struct pci_controller *hose, int port);  int yucca_pcie_card_present(int port);  int pcie_hose_scan(struct pci_controller *hose, int bus);  #endif /* __440SPE_PCIE_H */ |