diff options
Diffstat (limited to 'arch/powerpc/sysdev/ppc4xx_pci.c')
| -rw-r--r-- | arch/powerpc/sysdev/ppc4xx_pci.c | 434 | 
1 files changed, 330 insertions, 104 deletions
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c index 156aa7d3625..df6e2fc4ff9 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.c +++ b/arch/powerpc/sysdev/ppc4xx_pci.c @@ -176,8 +176,12 @@ static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose,  		return -ENXIO;  	} -	/* Check that we are fully contained within 32 bits space */ -	if (res->end > 0xffffffff) { +	/* Check that we are fully contained within 32 bits space if we are not +	 * running on a 460sx or 476fpe which have 64 bit bus addresses. +	 */ +	if (res->end > 0xffffffff && +	    !(of_device_is_compatible(hose->dn, "ibm,plb-pciex-460sx") +	      || of_device_is_compatible(hose->dn, "ibm,plb-pciex-476fpe"))) {  		printk(KERN_ERR "%s: dma-ranges outside of 32 bits space\n",  		       hose->dn->full_name);  		return -ENXIO; @@ -185,9 +189,15 @@ static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose,   out:  	dma_offset_set = 1;  	pci_dram_offset = res->start; +	hose->dma_window_base_cur = res->start; +	hose->dma_window_size = resource_size(res);  	printk(KERN_INFO "4xx PCI DMA offset set to 0x%08lx\n",  	       pci_dram_offset); +	printk(KERN_INFO "4xx PCI DMA window base to 0x%016llx\n", +	       (unsigned long long)hose->dma_window_base_cur); +	printk(KERN_INFO "DMA window size 0x%016llx\n", +	       (unsigned long long)hose->dma_window_size);  	return 0;  } @@ -251,6 +261,7 @@ static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose,  	/* Setup outbound memory windows */  	for (i = j = 0; i < 3; i++) {  		struct resource *res = &hose->mem_resources[i]; +		resource_size_t offset = hose->mem_offset[i];  		/* we only care about memory windows */  		if (!(res->flags & IORESOURCE_MEM)) @@ -264,8 +275,8 @@ static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose,  		/* Configure the resource */  		if (ppc4xx_setup_one_pci_PMM(hose, reg,  					     res->start, -					     res->start - hose->pci_mem_offset, -					     res->end + 1 - res->start, +					     res->start - offset, +					     resource_size(res),  					     res->flags,  					     j) == 0) {  			j++; @@ -273,7 +284,7 @@ static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose,  			/* If the resource PCI address is 0 then we have our  			 * ISA memory hole  			 */ -			if (res->start == hose->pci_mem_offset) +			if (res->start == offset)  				found_isa_hole = 1;  		}  	} @@ -290,7 +301,7 @@ static void __init ppc4xx_configure_pci_PTMs(struct pci_controller *hose,  					     void __iomem *reg,  					     const struct resource *res)  { -	resource_size_t size = res->end - res->start + 1; +	resource_size_t size = resource_size(res);  	u32 sa;  	/* Calculate window size */ @@ -349,7 +360,7 @@ static void __init ppc4xx_probe_pci_bridge(struct device_node *np)  	bus_range = of_get_property(np, "bus-range", NULL);  	/* Map registers */ -	reg = ioremap(rsrc_reg.start, rsrc_reg.end + 1 - rsrc_reg.start); +	reg = ioremap(rsrc_reg.start, resource_size(&rsrc_reg));  	if (reg == NULL) {  		printk(KERN_ERR "%s: Can't map registers !", np->full_name);  		goto fail; @@ -451,6 +462,7 @@ static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose,  	/* Setup outbound memory windows */  	for (i = j = 0; i < 3; i++) {  		struct resource *res = &hose->mem_resources[i]; +		resource_size_t offset = hose->mem_offset[i];  		/* we only care about memory windows */  		if (!(res->flags & IORESOURCE_MEM)) @@ -464,8 +476,8 @@ static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose,  		/* Configure the resource */  		if (ppc4xx_setup_one_pcix_POM(hose, reg,  					      res->start, -					      res->start - hose->pci_mem_offset, -					      res->end + 1 - res->start, +					      res->start - offset, +					      resource_size(res),  					      res->flags,  					      j) == 0) {  			j++; @@ -473,7 +485,7 @@ static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose,  			/* If the resource PCI address is 0 then we have our  			 * ISA memory hole  			 */ -			if (res->start == hose->pci_mem_offset) +			if (res->start == offset)  				found_isa_hole = 1;  		}  	} @@ -492,7 +504,7 @@ static void __init ppc4xx_configure_pcix_PIMs(struct pci_controller *hose,  					      int big_pim,  					      int enable_msi_hole)  { -	resource_size_t size = res->end - res->start + 1; +	resource_size_t size = resource_size(res);  	u32 sa;  	/* RAM is always at 0 */ @@ -555,7 +567,7 @@ static void __init ppc4xx_probe_pcix_bridge(struct device_node *np)  	bus_range = of_get_property(np, "bus-range", NULL);  	/* Map registers */ -	reg = ioremap(rsrc_reg.start, rsrc_reg.end + 1 - rsrc_reg.start); +	reg = ioremap(rsrc_reg.start, resource_size(&rsrc_reg));  	if (reg == NULL) {  		printk(KERN_ERR "%s: Can't map registers !", np->full_name);  		goto fail; @@ -647,13 +659,77 @@ static unsigned int ppc4xx_pciex_port_count;  struct ppc4xx_pciex_hwops  { +	bool want_sdr;  	int (*core_init)(struct device_node *np);  	int (*port_init_hw)(struct ppc4xx_pciex_port *port);  	int (*setup_utl)(struct ppc4xx_pciex_port *port); +	void (*check_link)(struct ppc4xx_pciex_port *port);  };  static struct ppc4xx_pciex_hwops *ppc4xx_pciex_hwops; +static int __init ppc4xx_pciex_wait_on_sdr(struct ppc4xx_pciex_port *port, +					   unsigned int sdr_offset, +					   unsigned int mask, +					   unsigned int value, +					   int timeout_ms) +{ +	u32 val; + +	while(timeout_ms--) { +		val = mfdcri(SDR0, port->sdr_base + sdr_offset); +		if ((val & mask) == value) { +			pr_debug("PCIE%d: Wait on SDR %x success with tm %d (%08x)\n", +				 port->index, sdr_offset, timeout_ms, val); +			return 0; +		} +		msleep(1); +	} +	return -1; +} + +static int __init ppc4xx_pciex_port_reset_sdr(struct ppc4xx_pciex_port *port) +{ +	/* Wait for reset to complete */ +	if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS, 1 << 20, 0, 10)) { +		printk(KERN_WARNING "PCIE%d: PGRST failed\n", +		       port->index); +		return -1; +	} +	return 0; +} + + +static void __init ppc4xx_pciex_check_link_sdr(struct ppc4xx_pciex_port *port) +{ +	printk(KERN_INFO "PCIE%d: Checking link...\n", port->index); + +	/* Check for card presence detect if supported, if not, just wait for +	 * link unconditionally. +	 * +	 * note that we don't fail if there is no link, we just filter out +	 * config space accesses. That way, it will be easier to implement +	 * hotplug later on. +	 */ +	if (!port->has_ibpre || +	    !ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP, +				      1 << 28, 1 << 28, 100)) { +		printk(KERN_INFO +		       "PCIE%d: Device detected, waiting for link...\n", +		       port->index); +		if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP, +					     0x1000, 0x1000, 2000)) +			printk(KERN_WARNING +			       "PCIE%d: Link up failed\n", port->index); +		else { +			printk(KERN_INFO +			       "PCIE%d: link is up !\n", port->index); +			port->link = 1; +		} +	} else +		printk(KERN_INFO "PCIE%d: No device detected.\n", port->index); +} +  #ifdef CONFIG_44x  /* Check various reset bits of the 440SPe PCIe core */ @@ -771,7 +847,7 @@ static int __init ppc440spe_pciex_core_init(struct device_node *np)  	return 3;  } -static int ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port) +static int __init ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port)  {  	u32 val = 1 << 24; @@ -806,15 +882,15 @@ static int ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port)  	dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET,  			(1 << 24) | (1 << 16), 1 << 12); -	return 0; +	return ppc4xx_pciex_port_reset_sdr(port);  } -static int ppc440speA_pciex_init_port_hw(struct ppc4xx_pciex_port *port) +static int __init ppc440speA_pciex_init_port_hw(struct ppc4xx_pciex_port *port)  {  	return ppc440spe_pciex_init_port_hw(port);  } -static int ppc440speB_pciex_init_port_hw(struct ppc4xx_pciex_port *port) +static int __init ppc440speB_pciex_init_port_hw(struct ppc4xx_pciex_port *port)  {  	int rc = ppc440spe_pciex_init_port_hw(port); @@ -853,16 +929,20 @@ static int ppc440speB_pciex_init_utl(struct ppc4xx_pciex_port *port)  static struct ppc4xx_pciex_hwops ppc440speA_pcie_hwops __initdata =  { +	.want_sdr	= true,  	.core_init	= ppc440spe_pciex_core_init,  	.port_init_hw	= ppc440speA_pciex_init_port_hw,  	.setup_utl	= ppc440speA_pciex_init_utl, +	.check_link	= ppc4xx_pciex_check_link_sdr,  };  static struct ppc4xx_pciex_hwops ppc440speB_pcie_hwops __initdata =  { +	.want_sdr	= true,  	.core_init	= ppc440spe_pciex_core_init,  	.port_init_hw	= ppc440speB_pciex_init_port_hw,  	.setup_utl	= ppc440speB_pciex_init_utl, +	.check_link	= ppc4xx_pciex_check_link_sdr,  };  static int __init ppc460ex_pciex_core_init(struct device_node *np) @@ -871,7 +951,7 @@ static int __init ppc460ex_pciex_core_init(struct device_node *np)  	return 2;  } -static int ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port) +static int __init ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)  {  	u32 val;  	u32 utlset1; @@ -944,7 +1024,7 @@ static int ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)  	port->has_ibpre = 1; -	return 0; +	return ppc4xx_pciex_port_reset_sdr(port);  }  static int ppc460ex_pciex_init_utl(struct ppc4xx_pciex_port *port) @@ -969,9 +1049,79 @@ static int ppc460ex_pciex_init_utl(struct ppc4xx_pciex_port *port)  static struct ppc4xx_pciex_hwops ppc460ex_pcie_hwops __initdata =  { +	.want_sdr	= true,  	.core_init	= ppc460ex_pciex_core_init,  	.port_init_hw	= ppc460ex_pciex_init_port_hw,  	.setup_utl	= ppc460ex_pciex_init_utl, +	.check_link	= ppc4xx_pciex_check_link_sdr, +}; + +static int __init apm821xx_pciex_core_init(struct device_node *np) +{ +	/* Return the number of pcie port */ +	return 1; +} + +static int __init apm821xx_pciex_init_port_hw(struct ppc4xx_pciex_port *port) +{ +	u32 val; + +	/* +	 * Do a software reset on PCIe ports. +	 * This code is to fix the issue that pci drivers doesn't re-assign +	 * bus number for PCIE devices after Uboot +	 * scanned and configured all the buses (eg. PCIE NIC IntelPro/1000 +	 * PT quad port, SAS LSI 1064E) +	 */ + +	mtdcri(SDR0, PESDR0_460EX_PHY_CTL_RST, 0x0); +	mdelay(10); + +	if (port->endpoint) +		val = PTYPE_LEGACY_ENDPOINT << 20; +	else +		val = PTYPE_ROOT_PORT << 20; + +	val |= LNKW_X1 << 12; + +	mtdcri(SDR0, port->sdr_base + PESDRn_DLPSET, val); +	mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET1, 0x00000000); +	mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET2, 0x01010000); + +	mtdcri(SDR0, PESDR0_460EX_L0CDRCTL, 0x00003230); +	mtdcri(SDR0, PESDR0_460EX_L0DRV, 0x00000130); +	mtdcri(SDR0, PESDR0_460EX_L0CLK, 0x00000006); + +	mtdcri(SDR0, PESDR0_460EX_PHY_CTL_RST, 0x10000000); +	mdelay(50); +	mtdcri(SDR0, PESDR0_460EX_PHY_CTL_RST, 0x30000000); + +	mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, +		mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET) | +		(PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTPYN)); + +	/* Poll for PHY reset */ +	val = PESDR0_460EX_RSTSTA - port->sdr_base; +	if (ppc4xx_pciex_wait_on_sdr(port, val, 0x1, 1,	100)) { +		printk(KERN_WARNING "%s: PCIE: Can't reset PHY\n", __func__); +		return -EBUSY; +	} else { +		mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, +			(mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET) & +			~(PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL)) | +			PESDRx_RCSSET_RSTPYN); + +		port->has_ibpre = 1; +		return 0; +	} +} + +static struct ppc4xx_pciex_hwops apm821xx_pcie_hwops __initdata = { +	.want_sdr   = true, +	.core_init	= apm821xx_pciex_core_init, +	.port_init_hw	= apm821xx_pciex_init_port_hw, +	.setup_utl	= ppc460ex_pciex_init_utl, +	.check_link = ppc4xx_pciex_check_link_sdr,  };  static int __init ppc460sx_pciex_core_init(struct device_node *np) @@ -1026,6 +1176,10 @@ static int __init ppc460sx_pciex_core_init(struct device_node *np)  	mtdcri(SDR0, PESDR1_460SX_HSSSLEW, 0xFFFF0000);  	mtdcri(SDR0, PESDR2_460SX_HSSSLEW, 0xFFFF0000); +	/* Set HSS PRBS enabled */ +	mtdcri(SDR0, PESDR0_460SX_HSSCTLSET, 0x00001130); +	mtdcri(SDR0, PESDR2_460SX_HSSCTLSET, 0x00001130); +  	udelay(100);  	/* De-assert PLLRESET */ @@ -1056,7 +1210,7 @@ static int __init ppc460sx_pciex_core_init(struct device_node *np)  	return 2;  } -static int ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port) +static int __init ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)  {  	if (port->endpoint) @@ -1066,29 +1220,56 @@ static int ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)  		dcri_clrset(SDR0, port->sdr_base + PESDRn_UTLSET2,  				0, 0x01000000); -	/*Gen-1*/ -	mtdcri(SDR0, port->sdr_base + PESDRn_460SX_RCEI, 0x08000000); -  	dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET,  			(PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL),  			PESDRx_RCSSET_RSTPYN);  	port->has_ibpre = 1; -	return 0; +	return ppc4xx_pciex_port_reset_sdr(port);  }  static int ppc460sx_pciex_init_utl(struct ppc4xx_pciex_port *port)  {  	/* Max 128 Bytes */  	out_be32 (port->utl_base + PEUTL_PBBSZ,   0x00000000); +	/* Assert VRB and TXE - per datasheet turn off addr validation */ +	out_be32(port->utl_base + PEUTL_PCTL,  0x80800000);  	return 0;  } +static void __init ppc460sx_pciex_check_link(struct ppc4xx_pciex_port *port) +{ +	void __iomem *mbase; +	int attempt = 50; + +	port->link = 0; + +	mbase = ioremap(port->cfg_space.start + 0x10000000, 0x1000); +	if (mbase == NULL) { +		printk(KERN_ERR "%s: Can't map internal config space !", +			port->node->full_name); +		goto done; +	} + +	while (attempt && (0 == (in_le32(mbase + PECFG_460SX_DLLSTA) +			& PECFG_460SX_DLLSTA_LINKUP))) { +		attempt--; +		mdelay(10); +	} +	if (attempt) +		port->link = 1; +done: +	iounmap(mbase); + +} +  static struct ppc4xx_pciex_hwops ppc460sx_pcie_hwops __initdata = { +	.want_sdr	= true,  	.core_init	= ppc460sx_pciex_core_init,  	.port_init_hw	= ppc460sx_pciex_init_port_hw,  	.setup_utl	= ppc460sx_pciex_init_utl, +	.check_link	= ppc460sx_pciex_check_link,  };  #endif /* CONFIG_44x */ @@ -1122,7 +1303,7 @@ static void ppc405ex_pcie_phy_reset(struct ppc4xx_pciex_port *port)  	mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, 0x00101000);  } -static int ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port) +static int __init ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)  {  	u32 val; @@ -1154,7 +1335,7 @@ static int ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)  	port->has_ibpre = 1; -	return 0; +	return ppc4xx_pciex_port_reset_sdr(port);  }  static int ppc405ex_pciex_init_utl(struct ppc4xx_pciex_port *port) @@ -1180,13 +1361,60 @@ static int ppc405ex_pciex_init_utl(struct ppc4xx_pciex_port *port)  static struct ppc4xx_pciex_hwops ppc405ex_pcie_hwops __initdata =  { +	.want_sdr	= true,  	.core_init	= ppc405ex_pciex_core_init,  	.port_init_hw	= ppc405ex_pciex_init_port_hw,  	.setup_utl	= ppc405ex_pciex_init_utl, +	.check_link	= ppc4xx_pciex_check_link_sdr,  };  #endif /* CONFIG_40x */ +#ifdef CONFIG_476FPE +static int __init ppc_476fpe_pciex_core_init(struct device_node *np) +{ +	return 4; +} + +static void __init ppc_476fpe_pciex_check_link(struct ppc4xx_pciex_port *port) +{ +	u32 timeout_ms = 20; +	u32 val = 0, mask = (PECFG_TLDLP_LNKUP|PECFG_TLDLP_PRESENT); +	void __iomem *mbase = ioremap(port->cfg_space.start + 0x10000000, +	                              0x1000); + +	printk(KERN_INFO "PCIE%d: Checking link...\n", port->index); + +	if (mbase == NULL) { +		printk(KERN_WARNING "PCIE%d: failed to get cfg space\n", +		                    port->index); +		return; +	} +		 +	while (timeout_ms--) { +		val = in_le32(mbase + PECFG_TLDLP); + +		if ((val & mask) == mask) +			break; +		msleep(10); +	} + +	if (val & PECFG_TLDLP_PRESENT) { +		printk(KERN_INFO "PCIE%d: link is up !\n", port->index); +		port->link = 1; +	} else +		printk(KERN_WARNING "PCIE%d: Link up failed\n", port->index); + +	iounmap(mbase); +	return; +} + +static struct ppc4xx_pciex_hwops ppc_476fpe_pcie_hwops __initdata = +{ +	.core_init	= ppc_476fpe_pciex_core_init, +	.check_link	= ppc_476fpe_pciex_check_link, +}; +#endif /* CONFIG_476FPE */  /* Check that the core has been initied and if not, do it */  static int __init ppc4xx_pciex_check_core_init(struct device_node *np) @@ -1208,11 +1436,18 @@ static int __init ppc4xx_pciex_check_core_init(struct device_node *np)  		ppc4xx_pciex_hwops = &ppc460ex_pcie_hwops;  	if (of_device_is_compatible(np, "ibm,plb-pciex-460sx"))  		ppc4xx_pciex_hwops = &ppc460sx_pcie_hwops; +	if (of_device_is_compatible(np, "ibm,plb-pciex-apm821xx")) +		ppc4xx_pciex_hwops = &apm821xx_pcie_hwops;  #endif /* CONFIG_44x    */  #ifdef CONFIG_40x  	if (of_device_is_compatible(np, "ibm,plb-pciex-405ex"))  		ppc4xx_pciex_hwops = &ppc405ex_pcie_hwops;  #endif +#ifdef CONFIG_476FPE +	if (of_device_is_compatible(np, "ibm,plb-pciex-476fpe") +		|| of_device_is_compatible(np, "ibm,plb-pciex-476gtr")) +		ppc4xx_pciex_hwops = &ppc_476fpe_pcie_hwops; +#endif  	if (ppc4xx_pciex_hwops == NULL) {  		printk(KERN_WARNING "PCIE: unknown host type %s\n",  		       np->full_name); @@ -1261,26 +1496,6 @@ static void __init ppc4xx_pciex_port_init_mapping(struct ppc4xx_pciex_port *port  	dcr_write(port->dcrs, DCRO_PEGPL_MSGMSK, 0);  } -static int __init ppc4xx_pciex_wait_on_sdr(struct ppc4xx_pciex_port *port, -					   unsigned int sdr_offset, -					   unsigned int mask, -					   unsigned int value, -					   int timeout_ms) -{ -	u32 val; - -	while(timeout_ms--) { -		val = mfdcri(SDR0, port->sdr_base + sdr_offset); -		if ((val & mask) == value) { -			pr_debug("PCIE%d: Wait on SDR %x success with tm %d (%08x)\n", -				 port->index, sdr_offset, timeout_ms, val); -			return 0; -		} -		msleep(1); -	} -	return -1; -} -  static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port)  {  	int rc = 0; @@ -1291,47 +1506,15 @@ static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port)  	if (rc != 0)  		return rc; -	printk(KERN_INFO "PCIE%d: Checking link...\n", -	       port->index); - -	/* Wait for reset to complete */ -	if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS, 1 << 20, 0, 10)) { -		printk(KERN_WARNING "PCIE%d: PGRST failed\n", -		       port->index); -		return -1; -	} - -	/* Check for card presence detect if supported, if not, just wait for -	 * link unconditionally. -	 * -	 * note that we don't fail if there is no link, we just filter out -	 * config space accesses. That way, it will be easier to implement -	 * hotplug later on. -	 */ -	if (!port->has_ibpre || -	    !ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP, -				      1 << 28, 1 << 28, 100)) { -		printk(KERN_INFO -		       "PCIE%d: Device detected, waiting for link...\n", -		       port->index); -		if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP, -					     0x1000, 0x1000, 2000)) -			printk(KERN_WARNING -			       "PCIE%d: Link up failed\n", port->index); -		else { -			printk(KERN_INFO -			       "PCIE%d: link is up !\n", port->index); -			port->link = 1; -		} -	} else -		printk(KERN_INFO "PCIE%d: No device detected.\n", port->index); -  	/*  	 * Initialize mapping: disable all regions and configure  	 * CFG and REG regions based on resources in the device tree  	 */  	ppc4xx_pciex_port_init_mapping(port); +	if (ppc4xx_pciex_hwops->check_link) +		ppc4xx_pciex_hwops->check_link(port); +  	/*  	 * Map UTL  	 */ @@ -1345,16 +1528,29 @@ static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port)  		ppc4xx_pciex_hwops->setup_utl(port);  	/* -	 * Check for VC0 active and assert RDY. +	 * Check for VC0 active or PLL Locked and assert RDY.  	 */ -	if (port->link && -	    ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS, -				     1 << 16, 1 << 16, 5000)) { -		printk(KERN_INFO "PCIE%d: VC0 not active\n", port->index); -		port->link = 0; +	if (port->sdr_base) { +		if (of_device_is_compatible(port->node, +				"ibm,plb-pciex-460sx")){ +			if (port->link && ppc4xx_pciex_wait_on_sdr(port, +					PESDRn_RCSSTS, +					1 << 12, 1 << 12, 5000)) { +				printk(KERN_INFO "PCIE%d: PLL not locked\n", +						port->index); +				port->link = 0; +			} +		} else if (port->link && +			ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS, +				1 << 16, 1 << 16, 5000)) { +			printk(KERN_INFO "PCIE%d: VC0 not active\n", +					port->index); +			port->link = 0; +		} + +		dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET, 0, 1 << 20);  	} -	dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET, 0, 1 << 20);  	msleep(100);  	return 0; @@ -1555,8 +1751,22 @@ static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port	*port,  		dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAH, lah);  		dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAL, lal);  		dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKH, 0x7fffffff); -		/* Note that 3 here means enabled | single region */ -		dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, sa | 3); +		/*Enabled and single region */ +		if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx")) +			dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, +				sa | DCRO_PEGPL_460SX_OMR1MSKL_UOT +					| DCRO_PEGPL_OMRxMSKL_VAL); +		else if (of_device_is_compatible( +				port->node, "ibm,plb-pciex-476fpe") || +			of_device_is_compatible( +				port->node, "ibm,plb-pciex-476gtr")) +			dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, +				sa | DCRO_PEGPL_476FPE_OMR1MSKL_UOT +					| DCRO_PEGPL_OMRxMSKL_VAL); +		else +			dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, +				sa | DCRO_PEGPL_OMR1MSKL_UOT +					| DCRO_PEGPL_OMRxMSKL_VAL);  		break;  	case 1:  		out_le32(mbase + PECFG_POM1LAH, pciah); @@ -1564,8 +1774,8 @@ static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port	*port,  		dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAH, lah);  		dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAL, lal);  		dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKH, 0x7fffffff); -		/* Note that 3 here means enabled | single region */ -		dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, sa | 3); +		dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, +				sa | DCRO_PEGPL_OMRxMSKL_VAL);  		break;  	case 2:  		out_le32(mbase + PECFG_POM2LAH, pciah); @@ -1574,7 +1784,9 @@ static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port	*port,  		dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAL, lal);  		dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKH, 0x7fffffff);  		/* Note that 3 here means enabled | IO space !!! */ -		dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, sa | 3); +		dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, +				sa | DCRO_PEGPL_OMR3MSKL_IO +					| DCRO_PEGPL_OMRxMSKL_VAL);  		break;  	} @@ -1590,6 +1802,7 @@ static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port,  	/* Setup outbound memory windows */  	for (i = j = 0; i < 3; i++) {  		struct resource *res = &hose->mem_resources[i]; +		resource_size_t offset = hose->mem_offset[i];  		/* we only care about memory windows */  		if (!(res->flags & IORESOURCE_MEM)) @@ -1603,8 +1816,8 @@ static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port,  		/* Configure the resource */  		if (ppc4xx_setup_one_pciex_POM(port, hose, mbase,  					       res->start, -					       res->start - hose->pci_mem_offset, -					       res->end + 1 - res->start, +					       res->start - offset, +					       resource_size(res),  					       res->flags,  					       j) == 0) {  			j++; @@ -1612,7 +1825,7 @@ static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port,  			/* If the resource PCI address is 0 then we have our  			 * ISA memory hole  			 */ -			if (res->start == hose->pci_mem_offset) +			if (res->start == offset)  				found_isa_hole = 1;  		}  	} @@ -1639,7 +1852,7 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port,  					       void __iomem *mbase,  					       struct resource *res)  { -	resource_size_t size = res->end - res->start + 1; +	resource_size_t size = resource_size(res);  	u64 sa;  	if (port->endpoint) { @@ -1673,7 +1886,14 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port,  		/* Calculate window size */  		sa = (0xffffffffffffffffull << ilog2(size));  		if (res->flags & IORESOURCE_PREFETCH) -			sa |= 0x8; +			sa |= PCI_BASE_ADDRESS_MEM_PREFETCH; + +		if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx") || +		    of_device_is_compatible( +			    port->node, "ibm,plb-pciex-476fpe") || +		    of_device_is_compatible( +			    port->node, "ibm,plb-pciex-476gtr")) +			sa |= PCI_BASE_ADDRESS_MEM_TYPE_64;  		out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa));  		out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa)); @@ -1836,6 +2056,10 @@ static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port)  	}  	out_le16(mbase + 0x202, val); +	/* Enable Bus master, memory, and io space */ +	if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx")) +		out_le16(mbase + 0x204, 0x7); +  	if (!port->endpoint) {  		/* Set Class Code to PCI-PCI bridge and Revision Id to 1 */  		out_le32(mbase + 0x208, 0x06040001); @@ -1899,13 +2123,15 @@ static void __init ppc4xx_probe_pciex_bridge(struct device_node *np)  	}  	port->node = of_node_get(np); -	pval = of_get_property(np, "sdr-base", NULL); -	if (pval == NULL) { -		printk(KERN_ERR "PCIE: missing sdr-base for %s\n", -		       np->full_name); -		return; +	if (ppc4xx_pciex_hwops->want_sdr) { +		pval = of_get_property(np, "sdr-base", NULL); +		if (pval == NULL) { +			printk(KERN_ERR "PCIE: missing sdr-base for %s\n", +			       np->full_name); +			return; +		} +		port->sdr_base = *pval;  	} -	port->sdr_base = *pval;  	/* Check if device_type property is set to "pci" or "pci-endpoint".  	 * Resulting from this setup this PCIe port will be configured @@ -1960,7 +2186,7 @@ static int __init ppc4xx_pci_find_bridges(void)  {  	struct device_node *np; -	ppc_pci_flags |= PPC_PCI_ENABLE_PROC_DOMAINS | PPC_PCI_COMPAT_DOMAIN_0; +	pci_add_flags(PCI_ENABLE_PROC_DOMAINS | PCI_COMPAT_DOMAIN_0);  #ifdef CONFIG_PPC4xx_PCI_EXPRESS  	for_each_compatible_node(np, NULL, "ibm,plb-pciex")  | 
