forked from mirrors/linux
		
	PCI: designware: Move Root Complex setup code to dw_pcie_setup_rc()
dw_pcie_host_init() looks up host bridge resources, ioremaps them, creates IRQ domains, and enumerates devices below the bridge. dw_pcie_setup_rc() programs the Root Complex registers. The Root Complex may lose power during suspend-to-RAM, and when we resume, we want to redo the latter but not the former. Move some Root Complex programming from dw_pcie_host_init() to dw_pcie_setup_rc() where it belongs. DesignWare-based drivers can call dw_pcie_setup_rc() in their resume paths. [Niklas Cassel <niklas.cassel@axis.com>: This change moves outbound ATU programming, which uses pp->mem_base, to dw_pcie_setup_rc(). Apply the dra7xx pp->mem_base update before calling dw_pcie_setup_rc().] [bhelgaas: changelog, fold in dra7xx fix from Niklas] Signed-off-by: Jisheng Zhang <jszhang@marvell.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Pratyush Anand <pratyush.anand@gmail.com>
This commit is contained in:
		
							parent
							
								
									9735a22799
								
							
						
					
					
						commit
						7e57fd1444
					
				
					 2 changed files with 21 additions and 22 deletions
				
			
		|  | @ -142,13 +142,13 @@ static void dra7xx_pcie_enable_interrupts(struct pcie_port *pp) | ||||||
| 
 | 
 | ||||||
| static void dra7xx_pcie_host_init(struct pcie_port *pp) | static void dra7xx_pcie_host_init(struct pcie_port *pp) | ||||||
| { | { | ||||||
| 	dw_pcie_setup_rc(pp); |  | ||||||
| 
 |  | ||||||
| 	pp->io_base &= DRA7XX_CPU_TO_BUS_ADDR; | 	pp->io_base &= DRA7XX_CPU_TO_BUS_ADDR; | ||||||
| 	pp->mem_base &= DRA7XX_CPU_TO_BUS_ADDR; | 	pp->mem_base &= DRA7XX_CPU_TO_BUS_ADDR; | ||||||
| 	pp->cfg0_base &= DRA7XX_CPU_TO_BUS_ADDR; | 	pp->cfg0_base &= DRA7XX_CPU_TO_BUS_ADDR; | ||||||
| 	pp->cfg1_base &= DRA7XX_CPU_TO_BUS_ADDR; | 	pp->cfg1_base &= DRA7XX_CPU_TO_BUS_ADDR; | ||||||
| 
 | 
 | ||||||
|  | 	dw_pcie_setup_rc(pp); | ||||||
|  | 
 | ||||||
| 	dra7xx_pcie_establish_link(pp); | 	dra7xx_pcie_establish_link(pp); | ||||||
| 	if (IS_ENABLED(CONFIG_PCI_MSI)) | 	if (IS_ENABLED(CONFIG_PCI_MSI)) | ||||||
| 		dw_pcie_msi_init(pp); | 		dw_pcie_msi_init(pp); | ||||||
|  |  | ||||||
|  | @ -434,7 +434,6 @@ int dw_pcie_host_init(struct pcie_port *pp) | ||||||
| 	struct platform_device *pdev = to_platform_device(pp->dev); | 	struct platform_device *pdev = to_platform_device(pp->dev); | ||||||
| 	struct pci_bus *bus, *child; | 	struct pci_bus *bus, *child; | ||||||
| 	struct resource *cfg_res; | 	struct resource *cfg_res; | ||||||
| 	u32 val; |  | ||||||
| 	int i, ret; | 	int i, ret; | ||||||
| 	LIST_HEAD(res); | 	LIST_HEAD(res); | ||||||
| 	struct resource_entry *win; | 	struct resource_entry *win; | ||||||
|  | @ -544,25 +543,6 @@ int dw_pcie_host_init(struct pcie_port *pp) | ||||||
| 	if (pp->ops->host_init) | 	if (pp->ops->host_init) | ||||||
| 		pp->ops->host_init(pp); | 		pp->ops->host_init(pp); | ||||||
| 
 | 
 | ||||||
| 	/*
 |  | ||||||
| 	 * If the platform provides ->rd_other_conf, it means the platform |  | ||||||
| 	 * uses its own address translation component rather than ATU, so |  | ||||||
| 	 * we should not program the ATU here. |  | ||||||
| 	 */ |  | ||||||
| 	if (!pp->ops->rd_other_conf) |  | ||||||
| 		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1, |  | ||||||
| 					  PCIE_ATU_TYPE_MEM, pp->mem_base, |  | ||||||
| 					  pp->mem_bus_addr, pp->mem_size); |  | ||||||
| 
 |  | ||||||
| 	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0); |  | ||||||
| 
 |  | ||||||
| 	/* program correct class for RC */ |  | ||||||
| 	dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2, PCI_CLASS_BRIDGE_PCI); |  | ||||||
| 
 |  | ||||||
| 	dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val); |  | ||||||
| 	val |= PORT_LOGIC_SPEED_CHANGE; |  | ||||||
| 	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val); |  | ||||||
| 
 |  | ||||||
| 	pp->root_bus_nr = pp->busn->start; | 	pp->root_bus_nr = pp->busn->start; | ||||||
| 	if (IS_ENABLED(CONFIG_PCI_MSI)) { | 	if (IS_ENABLED(CONFIG_PCI_MSI)) { | ||||||
| 		bus = pci_scan_root_bus_msi(pp->dev, pp->root_bus_nr, | 		bus = pci_scan_root_bus_msi(pp->dev, pp->root_bus_nr, | ||||||
|  | @ -800,6 +780,25 @@ void dw_pcie_setup_rc(struct pcie_port *pp) | ||||||
| 	val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | | 	val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | | ||||||
| 		PCI_COMMAND_MASTER | PCI_COMMAND_SERR; | 		PCI_COMMAND_MASTER | PCI_COMMAND_SERR; | ||||||
| 	dw_pcie_writel_rc(pp, val, PCI_COMMAND); | 	dw_pcie_writel_rc(pp, val, PCI_COMMAND); | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * If the platform provides ->rd_other_conf, it means the platform | ||||||
|  | 	 * uses its own address translation component rather than ATU, so | ||||||
|  | 	 * we should not program the ATU here. | ||||||
|  | 	 */ | ||||||
|  | 	if (!pp->ops->rd_other_conf) | ||||||
|  | 		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1, | ||||||
|  | 					  PCIE_ATU_TYPE_MEM, pp->mem_base, | ||||||
|  | 					  pp->mem_bus_addr, pp->mem_size); | ||||||
|  | 
 | ||||||
|  | 	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0); | ||||||
|  | 
 | ||||||
|  | 	/* program correct class for RC */ | ||||||
|  | 	dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2, PCI_CLASS_BRIDGE_PCI); | ||||||
|  | 
 | ||||||
|  | 	dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val); | ||||||
|  | 	val |= PORT_LOGIC_SPEED_CHANGE; | ||||||
|  | 	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); | MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Jisheng Zhang
						Jisheng Zhang