xref: /linux/drivers/pci/controller/plda/pcie-plda-host.c (revision 39bd5f8225d5fea9d5a14f21bd4dc4e6fc310e4a)
1*39bd5f82SMinda Chen // SPDX-License-Identifier: GPL-2.0
2*39bd5f82SMinda Chen /*
3*39bd5f82SMinda Chen  * PLDA PCIe XpressRich host controller driver
4*39bd5f82SMinda Chen  *
5*39bd5f82SMinda Chen  * Copyright (C) 2023 Microchip Co. Ltd
6*39bd5f82SMinda Chen  *
7*39bd5f82SMinda Chen  * Author: Daire McNamara <daire.mcnamara@microchip.com>
8*39bd5f82SMinda Chen  */
9*39bd5f82SMinda Chen 
10*39bd5f82SMinda Chen #include <linux/pci-ecam.h>
11*39bd5f82SMinda Chen 
12*39bd5f82SMinda Chen #include "pcie-plda.h"
13*39bd5f82SMinda Chen 
14*39bd5f82SMinda Chen void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
15*39bd5f82SMinda Chen 			    phys_addr_t axi_addr, phys_addr_t pci_addr,
16*39bd5f82SMinda Chen 			    size_t size)
17*39bd5f82SMinda Chen {
18*39bd5f82SMinda Chen 	u32 atr_sz = ilog2(size) - 1;
19*39bd5f82SMinda Chen 	u32 val;
20*39bd5f82SMinda Chen 
21*39bd5f82SMinda Chen 	if (index == 0)
22*39bd5f82SMinda Chen 		val = PCIE_CONFIG_INTERFACE;
23*39bd5f82SMinda Chen 	else
24*39bd5f82SMinda Chen 		val = PCIE_TX_RX_INTERFACE;
25*39bd5f82SMinda Chen 
26*39bd5f82SMinda Chen 	writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
27*39bd5f82SMinda Chen 	       ATR0_AXI4_SLV0_TRSL_PARAM);
28*39bd5f82SMinda Chen 
29*39bd5f82SMinda Chen 	val = lower_32_bits(axi_addr) | (atr_sz << ATR_SIZE_SHIFT) |
30*39bd5f82SMinda Chen 			    ATR_IMPL_ENABLE;
31*39bd5f82SMinda Chen 	writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
32*39bd5f82SMinda Chen 	       ATR0_AXI4_SLV0_SRCADDR_PARAM);
33*39bd5f82SMinda Chen 
34*39bd5f82SMinda Chen 	val = upper_32_bits(axi_addr);
35*39bd5f82SMinda Chen 	writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
36*39bd5f82SMinda Chen 	       ATR0_AXI4_SLV0_SRC_ADDR);
37*39bd5f82SMinda Chen 
38*39bd5f82SMinda Chen 	val = lower_32_bits(pci_addr);
39*39bd5f82SMinda Chen 	writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
40*39bd5f82SMinda Chen 	       ATR0_AXI4_SLV0_TRSL_ADDR_LSB);
41*39bd5f82SMinda Chen 
42*39bd5f82SMinda Chen 	val = upper_32_bits(pci_addr);
43*39bd5f82SMinda Chen 	writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
44*39bd5f82SMinda Chen 	       ATR0_AXI4_SLV0_TRSL_ADDR_UDW);
45*39bd5f82SMinda Chen 
46*39bd5f82SMinda Chen 	val = readl(bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM);
47*39bd5f82SMinda Chen 	val |= (ATR0_PCIE_ATR_SIZE << ATR0_PCIE_ATR_SIZE_SHIFT);
48*39bd5f82SMinda Chen 	writel(val, bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM);
49*39bd5f82SMinda Chen 	writel(0, bridge_base_addr + ATR0_PCIE_WIN0_SRC_ADDR);
50*39bd5f82SMinda Chen }
51*39bd5f82SMinda Chen EXPORT_SYMBOL_GPL(plda_pcie_setup_window);
52*39bd5f82SMinda Chen 
53*39bd5f82SMinda Chen int plda_pcie_setup_iomems(struct platform_device *pdev,
54*39bd5f82SMinda Chen 			   struct plda_pcie_rp *port)
55*39bd5f82SMinda Chen {
56*39bd5f82SMinda Chen 	void __iomem *bridge_base_addr = port->bridge_addr;
57*39bd5f82SMinda Chen 	struct pci_host_bridge *bridge = platform_get_drvdata(pdev);
58*39bd5f82SMinda Chen 	struct resource_entry *entry;
59*39bd5f82SMinda Chen 	u64 pci_addr;
60*39bd5f82SMinda Chen 	u32 index = 1;
61*39bd5f82SMinda Chen 
62*39bd5f82SMinda Chen 	resource_list_for_each_entry(entry, &bridge->windows) {
63*39bd5f82SMinda Chen 		if (resource_type(entry->res) == IORESOURCE_MEM) {
64*39bd5f82SMinda Chen 			pci_addr = entry->res->start - entry->offset;
65*39bd5f82SMinda Chen 			plda_pcie_setup_window(bridge_base_addr, index,
66*39bd5f82SMinda Chen 					       entry->res->start, pci_addr,
67*39bd5f82SMinda Chen 					       resource_size(entry->res));
68*39bd5f82SMinda Chen 			index++;
69*39bd5f82SMinda Chen 		}
70*39bd5f82SMinda Chen 	}
71*39bd5f82SMinda Chen 
72*39bd5f82SMinda Chen 	return 0;
73*39bd5f82SMinda Chen }
74*39bd5f82SMinda Chen EXPORT_SYMBOL_GPL(plda_pcie_setup_iomems);
75