diff options
Diffstat (limited to 'drivers/pci/controller/dwc/pcie-designware-host.c')
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-designware-host.c | 157 | 
1 files changed, 62 insertions, 95 deletions
| diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index 25087d3c9a82..77db32529319 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -126,18 +126,12 @@ static void dw_pci_setup_msi_msg(struct irq_data *d, struct msi_msg *msg)  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);  	u64 msi_target; -	if (pp->ops->get_msi_addr) -		msi_target = pp->ops->get_msi_addr(pp); -	else -		msi_target = (u64)pp->msi_data; +	msi_target = (u64)pp->msi_data;  	msg->address_lo = lower_32_bits(msi_target);  	msg->address_hi = upper_32_bits(msi_target); -	if (pp->ops->get_msi_data) -		msg->data = pp->ops->get_msi_data(pp, d->hwirq); -	else -		msg->data = d->hwirq; +	msg->data = d->hwirq;  	dev_dbg(pci->dev, "msi#%d address_hi %#x address_lo %#x\n",  		(int)d->hwirq, msg->address_hi, msg->address_lo); @@ -157,17 +151,13 @@ static void dw_pci_bottom_mask(struct irq_data *d)  	raw_spin_lock_irqsave(&pp->lock, flags); -	if (pp->ops->msi_clear_irq) { -		pp->ops->msi_clear_irq(pp, d->hwirq); -	} else { -		ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL; -		res = ctrl * MSI_REG_CTRL_BLOCK_SIZE; -		bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL; +	ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL; +	res = ctrl * MSI_REG_CTRL_BLOCK_SIZE; +	bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL; -		pp->irq_mask[ctrl] |= BIT(bit); -		dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + res, 4, -				    pp->irq_mask[ctrl]); -	} +	pp->irq_mask[ctrl] |= BIT(bit); +	dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + res, 4, +			    pp->irq_mask[ctrl]);  	raw_spin_unlock_irqrestore(&pp->lock, flags);  } @@ -180,17 +170,13 @@ static void dw_pci_bottom_unmask(struct irq_data *d)  	raw_spin_lock_irqsave(&pp->lock, flags); -	if (pp->ops->msi_set_irq) { -		pp->ops->msi_set_irq(pp, d->hwirq); -	} else { -		ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL; -		res = ctrl * MSI_REG_CTRL_BLOCK_SIZE; -		bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL; +	ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL; +	res = ctrl * MSI_REG_CTRL_BLOCK_SIZE; +	bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL; -		pp->irq_mask[ctrl] &= ~BIT(bit); -		dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + res, 4, -				    pp->irq_mask[ctrl]); -	} +	pp->irq_mask[ctrl] &= ~BIT(bit); +	dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + res, 4, +			    pp->irq_mask[ctrl]);  	raw_spin_unlock_irqrestore(&pp->lock, flags);  } @@ -199,20 +185,12 @@ static void dw_pci_bottom_ack(struct irq_data *d)  {  	struct pcie_port *pp  = irq_data_get_irq_chip_data(d);  	unsigned int res, bit, ctrl; -	unsigned long flags;  	ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL;  	res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;  	bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL; -	raw_spin_lock_irqsave(&pp->lock, flags); -  	dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_STATUS + res, 4, BIT(bit)); - -	if (pp->ops->msi_irq_ack) -		pp->ops->msi_irq_ack(d->hwirq, pp); - -	raw_spin_unlock_irqrestore(&pp->lock, flags);  }  static struct irq_chip dw_pci_msi_bottom_irq_chip = { @@ -245,7 +223,7 @@ static int dw_pcie_irq_domain_alloc(struct irq_domain *domain,  	for (i = 0; i < nr_irqs; i++)  		irq_domain_set_info(domain, virq + i, bit + i, -				    &dw_pci_msi_bottom_irq_chip, +				    pp->msi_irq_chip,  				    pp, handle_edge_irq,  				    NULL, NULL); @@ -298,25 +276,31 @@ int dw_pcie_allocate_domains(struct pcie_port *pp)  void dw_pcie_free_msi(struct pcie_port *pp)  { -	irq_set_chained_handler(pp->msi_irq, NULL); -	irq_set_handler_data(pp->msi_irq, NULL); +	if (pp->msi_irq) { +		irq_set_chained_handler(pp->msi_irq, NULL); +		irq_set_handler_data(pp->msi_irq, NULL); +	}  	irq_domain_remove(pp->msi_domain);  	irq_domain_remove(pp->irq_domain); + +	if (pp->msi_page) +		__free_page(pp->msi_page);  }  void dw_pcie_msi_init(struct pcie_port *pp)  {  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);  	struct device *dev = pci->dev; -	struct page *page;  	u64 msi_target; -	page = alloc_page(GFP_KERNEL); -	pp->msi_data = dma_map_page(dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE); +	pp->msi_page = alloc_page(GFP_KERNEL); +	pp->msi_data = dma_map_page(dev, pp->msi_page, 0, PAGE_SIZE, +				    DMA_FROM_DEVICE);  	if (dma_mapping_error(dev, pp->msi_data)) {  		dev_err(dev, "Failed to map MSI data\n"); -		__free_page(page); +		__free_page(pp->msi_page); +		pp->msi_page = NULL;  		return;  	}  	msi_target = (u64)pp->msi_data; @@ -335,7 +319,7 @@ int dw_pcie_host_init(struct pcie_port *pp)  	struct device_node *np = dev->of_node;  	struct platform_device *pdev = to_platform_device(dev);  	struct resource_entry *win, *tmp; -	struct pci_bus *bus, *child; +	struct pci_bus *child;  	struct pci_host_bridge *bridge;  	struct resource *cfg_res;  	int ret; @@ -352,7 +336,7 @@ int dw_pcie_host_init(struct pcie_port *pp)  		dev_err(dev, "Missing *config* reg space\n");  	} -	bridge = pci_alloc_host_bridge(0); +	bridge = devm_pci_alloc_host_bridge(dev, 0);  	if (!bridge)  		return -ENOMEM; @@ -363,7 +347,7 @@ int dw_pcie_host_init(struct pcie_port *pp)  	ret = devm_request_pci_bus_resources(dev, &bridge->windows);  	if (ret) -		goto error; +		return ret;  	/* Get the I/O and memory ranges from DT */  	resource_list_for_each_entry_safe(win, tmp, &bridge->windows) { @@ -407,8 +391,7 @@ int dw_pcie_host_init(struct pcie_port *pp)  						resource_size(pp->cfg));  		if (!pci->dbi_base) {  			dev_err(dev, "Error with ioremap\n"); -			ret = -ENOMEM; -			goto error; +			return -ENOMEM;  		}  	} @@ -419,8 +402,7 @@ int dw_pcie_host_init(struct pcie_port *pp)  					pp->cfg0_base, pp->cfg0_size);  		if (!pp->va_cfg0_base) {  			dev_err(dev, "Error with ioremap in function\n"); -			ret = -ENOMEM; -			goto error; +			return -ENOMEM;  		}  	} @@ -430,8 +412,7 @@ int dw_pcie_host_init(struct pcie_port *pp)  						pp->cfg1_size);  		if (!pp->va_cfg1_base) {  			dev_err(dev, "Error with ioremap\n"); -			ret = -ENOMEM; -			goto error; +			return -ENOMEM;  		}  	} @@ -439,7 +420,7 @@ int dw_pcie_host_init(struct pcie_port *pp)  	if (ret)  		pci->num_viewport = 2; -	if (IS_ENABLED(CONFIG_PCI_MSI) && pci_msi_enabled()) { +	if (pci_msi_enabled()) {  		/*  		 * If a specific SoC driver needs to change the  		 * default number of vectors, it needs to implement @@ -454,14 +435,16 @@ int dw_pcie_host_init(struct pcie_port *pp)  			    pp->num_vectors == 0) {  				dev_err(dev,  					"Invalid number of vectors\n"); -				goto error; +				return -EINVAL;  			}  		}  		if (!pp->ops->msi_host_init) { +			pp->msi_irq_chip = &dw_pci_msi_bottom_irq_chip; +  			ret = dw_pcie_allocate_domains(pp);  			if (ret) -				goto error; +				return ret;  			if (pp->msi_irq)  				irq_set_chained_handler_and_data(pp->msi_irq, @@ -470,14 +453,14 @@ int dw_pcie_host_init(struct pcie_port *pp)  		} else {  			ret = pp->ops->msi_host_init(pp);  			if (ret < 0) -				goto error; +				return ret;  		}  	}  	if (pp->ops->host_init) {  		ret = pp->ops->host_init(pp);  		if (ret) -			goto error; +			goto err_free_msi;  	}  	pp->root_bus_nr = pp->busn->start; @@ -491,24 +474,25 @@ int dw_pcie_host_init(struct pcie_port *pp)  	ret = pci_scan_root_bus_bridge(bridge);  	if (ret) -		goto error; +		goto err_free_msi; -	bus = bridge->bus; +	pp->root_bus = bridge->bus;  	if (pp->ops->scan_bus)  		pp->ops->scan_bus(pp); -	pci_bus_size_bridges(bus); -	pci_bus_assign_resources(bus); +	pci_bus_size_bridges(pp->root_bus); +	pci_bus_assign_resources(pp->root_bus); -	list_for_each_entry(child, &bus->children, node) +	list_for_each_entry(child, &pp->root_bus->children, node)  		pcie_bus_configure_settings(child); -	pci_bus_add_devices(bus); +	pci_bus_add_devices(pp->root_bus);  	return 0; -error: -	pci_free_host_bridge(bridge); +err_free_msi: +	if (pci_msi_enabled() && !pp->ops->msi_host_init) +		dw_pcie_free_msi(pp);  	return ret;  } @@ -628,17 +612,6 @@ static struct pci_ops dw_pcie_ops = {  	.write = dw_pcie_wr_conf,  }; -static u8 dw_pcie_iatu_unroll_enabled(struct dw_pcie *pci) -{ -	u32 val; - -	val = dw_pcie_readl_dbi(pci, PCIE_ATU_VIEWPORT); -	if (val == 0xffffffff) -		return 1; - -	return 0; -} -  void dw_pcie_setup_rc(struct pcie_port *pp)  {  	u32 val, ctrl, num_ctrls; @@ -646,17 +619,19 @@ void dw_pcie_setup_rc(struct pcie_port *pp)  	dw_pcie_setup(pci); -	num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL; - -	/* Initialize IRQ Status array */ -	for (ctrl = 0; ctrl < num_ctrls; ctrl++) { -		pp->irq_mask[ctrl] = ~0; -		dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + -					(ctrl * MSI_REG_CTRL_BLOCK_SIZE), -				    4, pp->irq_mask[ctrl]); -		dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + -					(ctrl * MSI_REG_CTRL_BLOCK_SIZE), -				    4, ~0); +	if (!pp->ops->msi_host_init) { +		num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL; + +		/* Initialize IRQ Status array */ +		for (ctrl = 0; ctrl < num_ctrls; ctrl++) { +			pp->irq_mask[ctrl] = ~0; +			dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + +					    (ctrl * MSI_REG_CTRL_BLOCK_SIZE), +					    4, pp->irq_mask[ctrl]); +			dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + +					    (ctrl * MSI_REG_CTRL_BLOCK_SIZE), +					    4, ~0); +		}  	}  	/* Setup RC BARs */ @@ -690,14 +665,6 @@ void dw_pcie_setup_rc(struct pcie_port *pp)  	 * we should not program the ATU here.  	 */  	if (!pp->ops->rd_other_conf) { -		/* Get iATU unroll support */ -		pci->iatu_unroll_enabled = dw_pcie_iatu_unroll_enabled(pci); -		dev_dbg(pci->dev, "iATU unroll: %s\n", -			pci->iatu_unroll_enabled ? "enabled" : "disabled"); - -		if (pci->iatu_unroll_enabled && !pci->atu_base) -			pci->atu_base = pci->dbi_base + DEFAULT_DBI_ATU_OFFSET; -  		dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX0,  					  PCIE_ATU_TYPE_MEM, pp->mem_base,  					  pp->mem_bus_addr, pp->mem_size); |