diff options
Diffstat (limited to 'drivers/pci/controller/dwc/pcie-designware.c')
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-designware.c | 121 | 
1 files changed, 72 insertions, 49 deletions
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c index 250cf7f40b85..1b5aba1f0c92 100644 --- a/drivers/pci/controller/dwc/pcie-designware.c +++ b/drivers/pci/controller/dwc/pcie-designware.c @@ -465,56 +465,61 @@ static inline u32 dw_pcie_enable_ecrc(u32 val)  	return val | PCIE_ATU_TD;  } -static int __dw_pcie_prog_outbound_atu(struct dw_pcie *pci, u8 func_no, -				       int index, int type, u64 cpu_addr, -				       u64 pci_addr, u64 size) +int dw_pcie_prog_outbound_atu(struct dw_pcie *pci, +			      const struct dw_pcie_ob_atu_cfg *atu)  { +	u64 cpu_addr = atu->cpu_addr;  	u32 retries, val;  	u64 limit_addr;  	if (pci->ops && pci->ops->cpu_addr_fixup)  		cpu_addr = pci->ops->cpu_addr_fixup(pci, cpu_addr); -	limit_addr = cpu_addr + size - 1; +	limit_addr = cpu_addr + atu->size - 1;  	if ((limit_addr & ~pci->region_limit) != (cpu_addr & ~pci->region_limit) ||  	    !IS_ALIGNED(cpu_addr, pci->region_align) || -	    !IS_ALIGNED(pci_addr, pci->region_align) || !size) { +	    !IS_ALIGNED(atu->pci_addr, pci->region_align) || !atu->size) {  		return -EINVAL;  	} -	dw_pcie_writel_atu_ob(pci, index, PCIE_ATU_LOWER_BASE, +	dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_LOWER_BASE,  			      lower_32_bits(cpu_addr)); -	dw_pcie_writel_atu_ob(pci, index, PCIE_ATU_UPPER_BASE, +	dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_UPPER_BASE,  			      upper_32_bits(cpu_addr)); -	dw_pcie_writel_atu_ob(pci, index, PCIE_ATU_LIMIT, +	dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_LIMIT,  			      lower_32_bits(limit_addr));  	if (dw_pcie_ver_is_ge(pci, 460A)) -		dw_pcie_writel_atu_ob(pci, index, PCIE_ATU_UPPER_LIMIT, +		dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_UPPER_LIMIT,  				      upper_32_bits(limit_addr)); -	dw_pcie_writel_atu_ob(pci, index, PCIE_ATU_LOWER_TARGET, -			      lower_32_bits(pci_addr)); -	dw_pcie_writel_atu_ob(pci, index, PCIE_ATU_UPPER_TARGET, -			      upper_32_bits(pci_addr)); +	dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_LOWER_TARGET, +			      lower_32_bits(atu->pci_addr)); +	dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_UPPER_TARGET, +			      upper_32_bits(atu->pci_addr)); -	val = type | PCIE_ATU_FUNC_NUM(func_no); +	val = atu->type | atu->routing | PCIE_ATU_FUNC_NUM(atu->func_no);  	if (upper_32_bits(limit_addr) > upper_32_bits(cpu_addr) &&  	    dw_pcie_ver_is_ge(pci, 460A))  		val |= PCIE_ATU_INCREASE_REGION_SIZE;  	if (dw_pcie_ver_is(pci, 490A))  		val = dw_pcie_enable_ecrc(val); -	dw_pcie_writel_atu_ob(pci, index, PCIE_ATU_REGION_CTRL1, val); +	dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_REGION_CTRL1, val); -	dw_pcie_writel_atu_ob(pci, index, PCIE_ATU_REGION_CTRL2, PCIE_ATU_ENABLE); +	val = PCIE_ATU_ENABLE; +	if (atu->type == PCIE_ATU_TYPE_MSG) { +		/* The data-less messages only for now */ +		val |= PCIE_ATU_INHIBIT_PAYLOAD | atu->code; +	} +	dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_REGION_CTRL2, val);  	/*  	 * Make sure ATU enable takes effect before any subsequent config  	 * and I/O accesses.  	 */  	for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) { -		val = dw_pcie_readl_atu_ob(pci, index, PCIE_ATU_REGION_CTRL2); +		val = dw_pcie_readl_atu_ob(pci, atu->index, PCIE_ATU_REGION_CTRL2);  		if (val & PCIE_ATU_ENABLE)  			return 0; @@ -526,21 +531,6 @@ static int __dw_pcie_prog_outbound_atu(struct dw_pcie *pci, u8 func_no,  	return -ETIMEDOUT;  } -int dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type, -			      u64 cpu_addr, u64 pci_addr, u64 size) -{ -	return __dw_pcie_prog_outbound_atu(pci, 0, index, type, -					   cpu_addr, pci_addr, size); -} - -int dw_pcie_prog_ep_outbound_atu(struct dw_pcie *pci, u8 func_no, int index, -				 int type, u64 cpu_addr, u64 pci_addr, -				 u64 size) -{ -	return __dw_pcie_prog_outbound_atu(pci, func_no, index, type, -					   cpu_addr, pci_addr, size); -} -  static inline u32 dw_pcie_readl_atu_ib(struct dw_pcie *pci, u32 index, u32 reg)  {  	return dw_pcie_readl_atu(pci, PCIE_ATU_REGION_DIR_IB, index, reg); @@ -655,7 +645,7 @@ int dw_pcie_wait_for_link(struct dw_pcie *pci)  		if (dw_pcie_link_up(pci))  			break; -		usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX); +		msleep(LINK_WAIT_SLEEP_MS);  	}  	if (retries >= LINK_WAIT_MAX_RETRIES) { @@ -880,30 +870,40 @@ static struct dw_edma_plat_ops dw_pcie_edma_ops = {  	.irq_vector = dw_pcie_edma_irq_vector,  }; -static int dw_pcie_edma_find_chip(struct dw_pcie *pci) +static void dw_pcie_edma_init_data(struct dw_pcie *pci) +{ +	pci->edma.dev = pci->dev; + +	if (!pci->edma.ops) +		pci->edma.ops = &dw_pcie_edma_ops; + +	pci->edma.flags |= DW_EDMA_CHIP_LOCAL; +} + +static int dw_pcie_edma_find_mf(struct dw_pcie *pci)  {  	u32 val;  	/* +	 * Bail out finding the mapping format if it is already set by the glue +	 * driver. Also ensure that the edma.reg_base is pointing to a valid +	 * memory region. +	 */ +	if (pci->edma.mf != EDMA_MF_EDMA_LEGACY) +		return pci->edma.reg_base ? 0 : -ENODEV; + +	/*  	 * Indirect eDMA CSRs access has been completely removed since v5.40a  	 * thus no space is now reserved for the eDMA channels viewport and  	 * former DMA CTRL register is no longer fixed to FFs. -	 * -	 * Note that Renesas R-Car S4-8's PCIe controllers for unknown reason -	 * have zeros in the eDMA CTRL register even though the HW-manual -	 * explicitly states there must FFs if the unrolled mapping is enabled. -	 * For such cases the low-level drivers are supposed to manually -	 * activate the unrolled mapping to bypass the auto-detection procedure.  	 */ -	if (dw_pcie_ver_is_ge(pci, 540A) || dw_pcie_cap_is(pci, EDMA_UNROLL)) +	if (dw_pcie_ver_is_ge(pci, 540A))  		val = 0xFFFFFFFF;  	else  		val = dw_pcie_readl_dbi(pci, PCIE_DMA_VIEWPORT_BASE + PCIE_DMA_CTRL);  	if (val == 0xFFFFFFFF && pci->edma.reg_base) {  		pci->edma.mf = EDMA_MF_EDMA_UNROLL; - -		val = dw_pcie_readl_dma(pci, PCIE_DMA_CTRL);  	} else if (val != 0xFFFFFFFF) {  		pci->edma.mf = EDMA_MF_EDMA_LEGACY; @@ -912,15 +912,25 @@ static int dw_pcie_edma_find_chip(struct dw_pcie *pci)  		return -ENODEV;  	} -	pci->edma.dev = pci->dev; +	return 0; +} -	if (!pci->edma.ops) -		pci->edma.ops = &dw_pcie_edma_ops; +static int dw_pcie_edma_find_channels(struct dw_pcie *pci) +{ +	u32 val; -	pci->edma.flags |= DW_EDMA_CHIP_LOCAL; +	/* +	 * Autodetect the read/write channels count only for non-HDMA platforms. +	 * HDMA platforms with native CSR mapping doesn't support autodetect, +	 * so the glue drivers should've passed the valid count already. If not, +	 * the below sanity check will catch it. +	 */ +	if (pci->edma.mf != EDMA_MF_HDMA_NATIVE) { +		val = dw_pcie_readl_dma(pci, PCIE_DMA_CTRL); -	pci->edma.ll_wr_cnt = FIELD_GET(PCIE_DMA_NUM_WR_CHAN, val); -	pci->edma.ll_rd_cnt = FIELD_GET(PCIE_DMA_NUM_RD_CHAN, val); +		pci->edma.ll_wr_cnt = FIELD_GET(PCIE_DMA_NUM_WR_CHAN, val); +		pci->edma.ll_rd_cnt = FIELD_GET(PCIE_DMA_NUM_RD_CHAN, val); +	}  	/* Sanity check the channels count if the mapping was incorrect */  	if (!pci->edma.ll_wr_cnt || pci->edma.ll_wr_cnt > EDMA_MAX_WR_CH || @@ -930,6 +940,19 @@ static int dw_pcie_edma_find_chip(struct dw_pcie *pci)  	return 0;  } +static int dw_pcie_edma_find_chip(struct dw_pcie *pci) +{ +	int ret; + +	dw_pcie_edma_init_data(pci); + +	ret = dw_pcie_edma_find_mf(pci); +	if (ret) +		return ret; + +	return dw_pcie_edma_find_channels(pci); +} +  static int dw_pcie_edma_irq_verify(struct dw_pcie *pci)  {  	struct platform_device *pdev = to_platform_device(pci->dev);  |