diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2016-12-12 12:25:08 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2016-12-12 12:25:08 -0500 |
commit | f887e24e0544cb239531c171f835e7e7aac4863b (patch) | |
tree | c360bf63afc707a70951fc3deaa45ac50b4e304a /drivers/pci | |
parent | 36e649f3bb8859c4b498b27a4d1a01df6964e1bd (diff) | |
parent | ffbd796821472c6571b09962cdbd13cd2815e2c1 (diff) |
Merge branch 'pci/host-iproc' into next
* pci/host-iproc:
PCI: iproc: Skip check for legacy IRQ on PAXC buses
PCI: iproc: Fix incorrect MSI address alignment
PCI: iproc: Add support for the next-gen PAXB controller
PCI: iproc: Add PAXBv2 binding info
PCI: iproc: Add inbound DMA mapping support
PCI: iproc: Add optional dma-ranges
PCI: iproc: Make outbound mapping code more generic
PCI: iproc: Remove redundant outbound properties
PCI: iproc: Add PAXC v2 support
PCI: iproc: Add PAXCv2 related binding
PCI: iproc: Fix exception with multi-function devices
PCI: iproc: Add BCMA type
PCI: iproc: Do not reset PAXC when initializing the driver
PCI: iproc: Improve core register population
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/host/pcie-iproc-bcma.c | 1 | ||||
-rw-r--r-- | drivers/pci/host/pcie-iproc-msi.c | 1 | ||||
-rw-r--r-- | drivers/pci/host/pcie-iproc-platform.c | 28 | ||||
-rw-r--r-- | drivers/pci/host/pcie-iproc.c | 949 | ||||
-rw-r--r-- | drivers/pci/host/pcie-iproc.h | 45 |
5 files changed, 902 insertions, 122 deletions
diff --git a/drivers/pci/host/pcie-iproc-bcma.c b/drivers/pci/host/pcie-iproc-bcma.c index 8ce089043a27..bd4c9ec25edc 100644 --- a/drivers/pci/host/pcie-iproc-bcma.c +++ b/drivers/pci/host/pcie-iproc-bcma.c | |||
@@ -54,6 +54,7 @@ static int iproc_pcie_bcma_probe(struct bcma_device *bdev) | |||
54 | 54 | ||
55 | pcie->dev = dev; | 55 | pcie->dev = dev; |
56 | 56 | ||
57 | pcie->type = IPROC_PCIE_PAXB_BCMA; | ||
57 | pcie->base = bdev->io_addr; | 58 | pcie->base = bdev->io_addr; |
58 | if (!pcie->base) { | 59 | if (!pcie->base) { |
59 | dev_err(dev, "no controller registers\n"); | 60 | dev_err(dev, "no controller registers\n"); |
diff --git a/drivers/pci/host/pcie-iproc-msi.c b/drivers/pci/host/pcie-iproc-msi.c index 9a2973bdc78a..9fad7915f82a 100644 --- a/drivers/pci/host/pcie-iproc-msi.c +++ b/drivers/pci/host/pcie-iproc-msi.c | |||
@@ -563,6 +563,7 @@ int iproc_msi_init(struct iproc_pcie *pcie, struct device_node *node) | |||
563 | } | 563 | } |
564 | 564 | ||
565 | switch (pcie->type) { | 565 | switch (pcie->type) { |
566 | case IPROC_PCIE_PAXB_BCMA: | ||
566 | case IPROC_PCIE_PAXB: | 567 | case IPROC_PCIE_PAXB: |
567 | msi->reg_offsets = iproc_msi_reg_paxb; | 568 | msi->reg_offsets = iproc_msi_reg_paxb; |
568 | msi->nr_eq_region = 1; | 569 | msi->nr_eq_region = 1; |
diff --git a/drivers/pci/host/pcie-iproc-platform.c b/drivers/pci/host/pcie-iproc-platform.c index a3de087976b3..22d814a78a78 100644 --- a/drivers/pci/host/pcie-iproc-platform.c +++ b/drivers/pci/host/pcie-iproc-platform.c | |||
@@ -31,8 +31,14 @@ static const struct of_device_id iproc_pcie_of_match_table[] = { | |||
31 | .compatible = "brcm,iproc-pcie", | 31 | .compatible = "brcm,iproc-pcie", |
32 | .data = (int *)IPROC_PCIE_PAXB, | 32 | .data = (int *)IPROC_PCIE_PAXB, |
33 | }, { | 33 | }, { |
34 | .compatible = "brcm,iproc-pcie-paxb-v2", | ||
35 | .data = (int *)IPROC_PCIE_PAXB_V2, | ||
36 | }, { | ||
34 | .compatible = "brcm,iproc-pcie-paxc", | 37 | .compatible = "brcm,iproc-pcie-paxc", |
35 | .data = (int *)IPROC_PCIE_PAXC, | 38 | .data = (int *)IPROC_PCIE_PAXC, |
39 | }, { | ||
40 | .compatible = "brcm,iproc-pcie-paxc-v2", | ||
41 | .data = (int *)IPROC_PCIE_PAXC_V2, | ||
36 | }, | 42 | }, |
37 | { /* sentinel */ } | 43 | { /* sentinel */ } |
38 | }; | 44 | }; |
@@ -84,19 +90,6 @@ static int iproc_pcie_pltfm_probe(struct platform_device *pdev) | |||
84 | return ret; | 90 | return ret; |
85 | } | 91 | } |
86 | pcie->ob.axi_offset = val; | 92 | pcie->ob.axi_offset = val; |
87 | |||
88 | ret = of_property_read_u32(np, "brcm,pcie-ob-window-size", | ||
89 | &val); | ||
90 | if (ret) { | ||
91 | dev_err(dev, | ||
92 | "missing brcm,pcie-ob-window-size property\n"); | ||
93 | return ret; | ||
94 | } | ||
95 | pcie->ob.window_size = (resource_size_t)val * SZ_1M; | ||
96 | |||
97 | if (of_property_read_bool(np, "brcm,pcie-ob-oarr-size")) | ||
98 | pcie->ob.set_oarr_size = true; | ||
99 | |||
100 | pcie->need_ob_cfg = true; | 93 | pcie->need_ob_cfg = true; |
101 | } | 94 | } |
102 | 95 | ||
@@ -115,7 +108,14 @@ static int iproc_pcie_pltfm_probe(struct platform_device *pdev) | |||
115 | return ret; | 108 | return ret; |
116 | } | 109 | } |
117 | 110 | ||
118 | pcie->map_irq = of_irq_parse_and_map_pci; | 111 | /* PAXC doesn't support legacy IRQs, skip mapping */ |
112 | switch (pcie->type) { | ||
113 | case IPROC_PCIE_PAXC: | ||
114 | case IPROC_PCIE_PAXC_V2: | ||
115 | break; | ||
116 | default: | ||
117 | pcie->map_irq = of_irq_parse_and_map_pci; | ||
118 | } | ||
119 | 119 | ||
120 | ret = iproc_pcie_setup(pcie, &res); | 120 | ret = iproc_pcie_setup(pcie, &res); |
121 | if (ret) | 121 | if (ret) |
diff --git a/drivers/pci/host/pcie-iproc.c b/drivers/pci/host/pcie-iproc.c index 0b999a9fb843..3ebc025499b9 100644 --- a/drivers/pci/host/pcie-iproc.c +++ b/drivers/pci/host/pcie-iproc.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/irqchip/arm-gic-v3.h> | ||
24 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
25 | #include <linux/of_address.h> | 26 | #include <linux/of_address.h> |
26 | #include <linux/of_pci.h> | 27 | #include <linux/of_pci.h> |
@@ -38,6 +39,12 @@ | |||
38 | #define RC_PCIE_RST_OUTPUT BIT(RC_PCIE_RST_OUTPUT_SHIFT) | 39 | #define RC_PCIE_RST_OUTPUT BIT(RC_PCIE_RST_OUTPUT_SHIFT) |
39 | #define PAXC_RESET_MASK 0x7f | 40 | #define PAXC_RESET_MASK 0x7f |
40 | 41 | ||
42 | #define GIC_V3_CFG_SHIFT 0 | ||
43 | #define GIC_V3_CFG BIT(GIC_V3_CFG_SHIFT) | ||
44 | |||
45 | #define MSI_ENABLE_CFG_SHIFT 0 | ||
46 | #define MSI_ENABLE_CFG BIT(MSI_ENABLE_CFG_SHIFT) | ||
47 | |||
41 | #define CFG_IND_ADDR_MASK 0x00001ffc | 48 | #define CFG_IND_ADDR_MASK 0x00001ffc |
42 | 49 | ||
43 | #define CFG_ADDR_BUS_NUM_SHIFT 20 | 50 | #define CFG_ADDR_BUS_NUM_SHIFT 20 |
@@ -58,59 +65,319 @@ | |||
58 | #define PCIE_DL_ACTIVE_SHIFT 2 | 65 | #define PCIE_DL_ACTIVE_SHIFT 2 |
59 | #define PCIE_DL_ACTIVE BIT(PCIE_DL_ACTIVE_SHIFT) | 66 | #define PCIE_DL_ACTIVE BIT(PCIE_DL_ACTIVE_SHIFT) |
60 | 67 | ||
68 | #define APB_ERR_EN_SHIFT 0 | ||
69 | #define APB_ERR_EN BIT(APB_ERR_EN_SHIFT) | ||
70 | |||
71 | /* derive the enum index of the outbound/inbound mapping registers */ | ||
72 | #define MAP_REG(base_reg, index) ((base_reg) + (index) * 2) | ||
73 | |||
74 | /* | ||
75 | * Maximum number of outbound mapping window sizes that can be supported by any | ||
76 | * OARR/OMAP mapping pair | ||
77 | */ | ||
78 | #define MAX_NUM_OB_WINDOW_SIZES 4 | ||
79 | |||
61 | #define OARR_VALID_SHIFT 0 | 80 | #define OARR_VALID_SHIFT 0 |
62 | #define OARR_VALID BIT(OARR_VALID_SHIFT) | 81 | #define OARR_VALID BIT(OARR_VALID_SHIFT) |
63 | #define OARR_SIZE_CFG_SHIFT 1 | 82 | #define OARR_SIZE_CFG_SHIFT 1 |
64 | #define OARR_SIZE_CFG BIT(OARR_SIZE_CFG_SHIFT) | ||
65 | 83 | ||
66 | #define PCI_EXP_CAP 0xac | 84 | /* |
85 | * Maximum number of inbound mapping region sizes that can be supported by an | ||
86 | * IARR | ||
87 | */ | ||
88 | #define MAX_NUM_IB_REGION_SIZES 9 | ||
89 | |||
90 | #define IMAP_VALID_SHIFT 0 | ||
91 | #define IMAP_VALID BIT(IMAP_VALID_SHIFT) | ||
67 | 92 | ||
68 | #define MAX_NUM_OB_WINDOWS 2 | 93 | #define PCI_EXP_CAP 0xac |
69 | 94 | ||
70 | #define IPROC_PCIE_REG_INVALID 0xffff | 95 | #define IPROC_PCIE_REG_INVALID 0xffff |
71 | 96 | ||
97 | /** | ||
98 | * iProc PCIe outbound mapping controller specific parameters | ||
99 | * | ||
100 | * @window_sizes: list of supported outbound mapping window sizes in MB | ||
101 | * @nr_sizes: number of supported outbound mapping window sizes | ||
102 | */ | ||
103 | struct iproc_pcie_ob_map { | ||
104 | resource_size_t window_sizes[MAX_NUM_OB_WINDOW_SIZES]; | ||
105 | unsigned int nr_sizes; | ||
106 | }; | ||
107 | |||
108 | static const struct iproc_pcie_ob_map paxb_ob_map[] = { | ||
109 | { | ||
110 | /* OARR0/OMAP0 */ | ||
111 | .window_sizes = { 128, 256 }, | ||
112 | .nr_sizes = 2, | ||
113 | }, | ||
114 | { | ||
115 | /* OARR1/OMAP1 */ | ||
116 | .window_sizes = { 128, 256 }, | ||
117 | .nr_sizes = 2, | ||
118 | }, | ||
119 | }; | ||
120 | |||
121 | static const struct iproc_pcie_ob_map paxb_v2_ob_map[] = { | ||
122 | { | ||
123 | /* OARR0/OMAP0 */ | ||
124 | .window_sizes = { 128, 256 }, | ||
125 | .nr_sizes = 2, | ||
126 | }, | ||
127 | { | ||
128 | /* OARR1/OMAP1 */ | ||
129 | .window_sizes = { 128, 256 }, | ||
130 | .nr_sizes = 2, | ||
131 | }, | ||
132 | { | ||
133 | /* OARR2/OMAP2 */ | ||
134 | .window_sizes = { 128, 256, 512, 1024 }, | ||
135 | .nr_sizes = 4, | ||
136 | }, | ||
137 | { | ||
138 | /* OARR3/OMAP3 */ | ||
139 | .window_sizes = { 128, 256, 512, 1024 }, | ||
140 | .nr_sizes = 4, | ||
141 | }, | ||
142 | }; | ||
143 | |||
144 | /** | ||
145 | * iProc PCIe inbound mapping type | ||
146 | */ | ||
147 | enum iproc_pcie_ib_map_type { | ||
148 | /* for DDR memory */ | ||
149 | IPROC_PCIE_IB_MAP_MEM = 0, | ||
150 | |||
151 | /* for device I/O memory */ | ||
152 | IPROC_PCIE_IB_MAP_IO, | ||
153 | |||
154 | /* invalid or unused */ | ||
155 | IPROC_PCIE_IB_MAP_INVALID | ||
156 | }; | ||
157 | |||
158 | /** | ||
159 | * iProc PCIe inbound mapping controller specific parameters | ||
160 | * | ||
161 | * @type: inbound mapping region type | ||
162 | * @size_unit: inbound mapping region size unit, could be SZ_1K, SZ_1M, or | ||
163 | * SZ_1G | ||
164 | * @region_sizes: list of supported inbound mapping region sizes in KB, MB, or | ||
165 | * GB, depedning on the size unit | ||
166 | * @nr_sizes: number of supported inbound mapping region sizes | ||
167 | * @nr_windows: number of supported inbound mapping windows for the region | ||
168 | * @imap_addr_offset: register offset between the upper and lower 32-bit | ||
169 | * IMAP address registers | ||
170 | * @imap_window_offset: register offset between each IMAP window | ||
171 | */ | ||
172 | struct iproc_pcie_ib_map { | ||
173 | enum iproc_pcie_ib_map_type type; | ||
174 | unsigned int size_unit; | ||
175 | resource_size_t region_sizes[MAX_NUM_IB_REGION_SIZES]; | ||
176 | unsigned int nr_sizes; | ||
177 | unsigned int nr_windows; | ||
178 | u16 imap_addr_offset; | ||
179 | u16 imap_window_offset; | ||
180 | }; | ||
181 | |||
182 | static const struct iproc_pcie_ib_map paxb_v2_ib_map[] = { | ||
183 | { | ||
184 | /* IARR0/IMAP0 */ | ||
185 | .type = IPROC_PCIE_IB_MAP_IO, | ||
186 | .size_unit = SZ_1K, | ||
187 | .region_sizes = { 32 }, | ||
188 | .nr_sizes = 1, | ||
189 | .nr_windows = 8, | ||
190 | .imap_addr_offset = 0x40, | ||
191 | .imap_window_offset = 0x4, | ||
192 | }, | ||
193 | { | ||
194 | /* IARR1/IMAP1 (currently unused) */ | ||
195 | .type = IPROC_PCIE_IB_MAP_INVALID, | ||
196 | }, | ||
197 | { | ||
198 | /* IARR2/IMAP2 */ | ||
199 | .type = IPROC_PCIE_IB_MAP_MEM, | ||
200 | .size_unit = SZ_1M, | ||
201 | .region_sizes = { 64, 128, 256, 512, 1024, 2048, 4096, 8192, | ||
202 | 16384 }, | ||
203 | .nr_sizes = 9, | ||
204 | .nr_windows = 1, | ||
205 | .imap_addr_offset = 0x4, | ||
206 | .imap_window_offset = 0x8, | ||
207 | }, | ||
208 | { | ||
209 | /* IARR3/IMAP3 */ | ||
210 | .type = IPROC_PCIE_IB_MAP_MEM, | ||
211 | .size_unit = SZ_1G, | ||
212 | .region_sizes = { 1, 2, 4, 8, 16, 32 }, | ||
213 | .nr_sizes = 6, | ||
214 | .nr_windows = 8, | ||
215 | .imap_addr_offset = 0x4, | ||
216 | .imap_window_offset = 0x8, | ||
217 | }, | ||
218 | { | ||
219 | /* IARR4/IMAP4 */ | ||
220 | .type = IPROC_PCIE_IB_MAP_MEM, | ||
221 | .size_unit = SZ_1G, | ||
222 | .region_sizes = { 32, 64, 128, 256, 512 }, | ||
223 | .nr_sizes = 5, | ||
224 | .nr_windows = 8, | ||
225 | .imap_addr_offset = 0x4, | ||
226 | .imap_window_offset = 0x8, | ||
227 | }, | ||
228 | }; | ||
229 | |||
230 | /* | ||
231 | * iProc PCIe host registers | ||
232 | */ | ||
72 | enum iproc_pcie_reg { | 233 | enum iproc_pcie_reg { |
234 | /* clock/reset signal control */ | ||
73 | IPROC_PCIE_CLK_CTRL = 0, | 235 | IPROC_PCIE_CLK_CTRL = 0, |
236 | |||
237 | /* | ||
238 | * To allow MSI to be steered to an external MSI controller (e.g., ARM | ||
239 | * GICv3 ITS) | ||
240 | */ | ||
241 | IPROC_PCIE_MSI_GIC_MODE, | ||
242 | |||
243 | /* | ||
244 | * IPROC_PCIE_MSI_BASE_ADDR and IPROC_PCIE_MSI_WINDOW_SIZE define the | ||
245 | * window where the MSI posted writes are written, for the writes to be | ||
246 | * interpreted as MSI writes. | ||
247 | */ | ||
248 | IPROC_PCIE_MSI_BASE_ADDR, | ||
249 | IPROC_PCIE_MSI_WINDOW_SIZE, | ||
250 | |||
251 | /* | ||
252 | * To hold the address of the register where the MSI writes are | ||
253 | * programed. When ARM GICv3 ITS is used, this should be programmed | ||
254 | * with the address of the GITS_TRANSLATER register. | ||
255 | */ | ||
256 | IPROC_PCIE_MSI_ADDR_LO, | ||
257 | IPROC_PCIE_MSI_ADDR_HI, | ||
258 | |||
259 | /* enable MSI */ | ||
260 | IPROC_PCIE_MSI_EN_CFG, | ||
261 | |||
262 | /* allow access to root complex configuration space */ | ||
74 | IPROC_PCIE_CFG_IND_ADDR, | 263 | IPROC_PCIE_CFG_IND_ADDR, |
75 | IPROC_PCIE_CFG_IND_DATA, | 264 | IPROC_PCIE_CFG_IND_DATA, |
265 | |||
266 | /* allow access to device configuration space */ | ||
76 | IPROC_PCIE_CFG_ADDR, | 267 | IPROC_PCIE_CFG_ADDR, |
77 | IPROC_PCIE_CFG_DATA, | 268 | IPROC_PCIE_CFG_DATA, |
269 | |||
270 | /* enable INTx */ | ||
78 | IPROC_PCIE_INTX_EN, | 271 | IPROC_PCIE_INTX_EN, |
79 | IPROC_PCIE_OARR_LO, | 272 | |
80 | IPROC_PCIE_OARR_HI, | 273 | /* outbound address mapping */ |
81 | IPROC_PCIE_OMAP_LO, | 274 | IPROC_PCIE_OARR0, |
82 | IPROC_PCIE_OMAP_HI, | 275 | IPROC_PCIE_OMAP0, |
276 | IPROC_PCIE_OARR1, | ||
277 | IPROC_PCIE_OMAP1, | ||
278 | IPROC_PCIE_OARR2, | ||
279 | IPROC_PCIE_OMAP2, | ||
280 | IPROC_PCIE_OARR3, | ||
281 | IPROC_PCIE_OMAP3, | ||
282 | |||
283 | /* inbound address mapping */ | ||
284 | IPROC_PCIE_IARR0, | ||
285 | IPROC_PCIE_IMAP0, | ||
286 | IPROC_PCIE_IARR1, | ||
287 | IPROC_PCIE_IMAP1, | ||
288 | IPROC_PCIE_IARR2, | ||
289 | IPROC_PCIE_IMAP2, | ||
290 | IPROC_PCIE_IARR3, | ||
291 | IPROC_PCIE_IMAP3, | ||
292 | IPROC_PCIE_IARR4, | ||
293 | IPROC_PCIE_IMAP4, | ||
294 | |||
295 | /* link status */ | ||
83 | IPROC_PCIE_LINK_STATUS, | 296 | IPROC_PCIE_LINK_STATUS, |
297 | |||
298 | /* enable APB error for unsupported requests */ | ||
299 | IPROC_PCIE_APB_ERR_EN, | ||
300 | |||
301 | /* total number of core registers */ | ||
302 | IPROC_PCIE_MAX_NUM_REG, | ||
303 | }; | ||
304 | |||
305 | /* iProc PCIe PAXB BCMA registers */ | ||
306 | static const u16 iproc_pcie_reg_paxb_bcma[] = { | ||
307 | [IPROC_PCIE_CLK_CTRL] = 0x000, | ||
308 | [IPROC_PCIE_CFG_IND_ADDR] = 0x120, | ||
309 | [IPROC_PCIE_CFG_IND_DATA] = 0x124, | ||
310 | [IPROC_PCIE_CFG_ADDR] = 0x1f8, | ||
311 | [IPROC_PCIE_CFG_DATA] = 0x1fc, | ||
312 | [IPROC_PCIE_INTX_EN] = 0x330, | ||
313 | [IPROC_PCIE_LINK_STATUS] = 0xf0c, | ||
84 | }; | 314 | }; |
85 | 315 | ||
86 | /* iProc PCIe PAXB registers */ | 316 | /* iProc PCIe PAXB registers */ |
87 | static const u16 iproc_pcie_reg_paxb[] = { | 317 | static const u16 iproc_pcie_reg_paxb[] = { |
88 | [IPROC_PCIE_CLK_CTRL] = 0x000, | 318 | [IPROC_PCIE_CLK_CTRL] = 0x000, |
89 | [IPROC_PCIE_CFG_IND_ADDR] = 0x120, | 319 | [IPROC_PCIE_CFG_IND_ADDR] = 0x120, |
90 | [IPROC_PCIE_CFG_IND_DATA] = 0x124, | 320 | [IPROC_PCIE_CFG_IND_DATA] = 0x124, |
91 | [IPROC_PCIE_CFG_ADDR] = 0x1f8, | 321 | [IPROC_PCIE_CFG_ADDR] = 0x1f8, |
92 | [IPROC_PCIE_CFG_DATA] = 0x1fc, | 322 | [IPROC_PCIE_CFG_DATA] = 0x1fc, |
93 | [IPROC_PCIE_INTX_EN] = 0x330, | 323 | [IPROC_PCIE_INTX_EN] = 0x330, |
94 | [IPROC_PCIE_OARR_LO] = 0xd20, | 324 | [IPROC_PCIE_OARR0] = 0xd20, |
95 | [IPROC_PCIE_OARR_HI] = 0xd24, | 325 | [IPROC_PCIE_OMAP0] = 0xd40, |
96 | [IPROC_PCIE_OMAP_LO] = 0xd40, | 326 | [IPROC_PCIE_OARR1] = 0xd28, |
97 | [IPROC_PCIE_OMAP_HI] = 0xd44, | 327 | [IPROC_PCIE_OMAP1] = 0xd48, |
98 | [IPROC_PCIE_LINK_STATUS] = 0xf0c, | 328 | [IPROC_PCIE_LINK_STATUS] = 0xf0c, |
329 | [IPROC_PCIE_APB_ERR_EN] = 0xf40, | ||
330 | }; | ||
331 | |||
332 | /* iProc PCIe PAXB v2 registers */ | ||
333 | static const u16 iproc_pcie_reg_paxb_v2[] = { | ||
334 | [IPROC_PCIE_CLK_CTRL] = 0x000, | ||
335 | [IPROC_PCIE_CFG_IND_ADDR] = 0x120, | ||
336 | [IPROC_PCIE_CFG_IND_DATA] = 0x124, | ||
337 | [IPROC_PCIE_CFG_ADDR] = 0x1f8, | ||
338 | [IPROC_PCIE_CFG_DATA] = 0x1fc, | ||
339 | [IPROC_PCIE_INTX_EN] = 0x330, | ||
340 | [IPROC_PCIE_OARR0] = 0xd20, | ||
341 | [IPROC_PCIE_OMAP0] = 0xd40, | ||
342 | [IPROC_PCIE_OARR1] = 0xd28, | ||
343 | [IPROC_PCIE_OMAP1] = 0xd48, | ||
344 | [IPROC_PCIE_OARR2] = 0xd60, | ||
345 | [IPROC_PCIE_OMAP2] = 0xd68, | ||
346 | [IPROC_PCIE_OARR3] = 0xdf0, | ||
347 | [IPROC_PCIE_OMAP3] = 0xdf8, | ||
348 | [IPROC_PCIE_IARR0] = 0xd00, | ||
349 | [IPROC_PCIE_IMAP0] = 0xc00, | ||
350 | [IPROC_PCIE_IARR2] = 0xd10, | ||
351 | [IPROC_PCIE_IMAP2] = 0xcc0, | ||
352 | [IPROC_PCIE_IARR3] = 0xe00, | ||
353 | [IPROC_PCIE_IMAP3] = 0xe08, | ||
354 | [IPROC_PCIE_IARR4] = 0xe68, | ||
355 | [IPROC_PCIE_IMAP4] = 0xe70, | ||
356 | [IPROC_PCIE_LINK_STATUS] = 0xf0c, | ||
357 | [IPROC_PCIE_APB_ERR_EN] = 0xf40, | ||
99 | }; | 358 | }; |
100 | 359 | ||
101 | /* iProc PCIe PAXC v1 registers */ | 360 | /* iProc PCIe PAXC v1 registers */ |
102 | static const u16 iproc_pcie_reg_paxc[] = { | 361 | static const u16 iproc_pcie_reg_paxc[] = { |
103 | [IPROC_PCIE_CLK_CTRL] = 0x000, | 362 | [IPROC_PCIE_CLK_CTRL] = 0x000, |
104 | [IPROC_PCIE_CFG_IND_ADDR] = 0x1f0, | 363 | [IPROC_PCIE_CFG_IND_ADDR] = 0x1f0, |
105 | [IPROC_PCIE_CFG_IND_DATA] = 0x1f4, | 364 | [IPROC_PCIE_CFG_IND_DATA] = 0x1f4, |
106 | [IPROC_PCIE_CFG_ADDR] = 0x1f8, | 365 | [IPROC_PCIE_CFG_ADDR] = 0x1f8, |
107 | [IPROC_PCIE_CFG_DATA] = 0x1fc, | 366 | [IPROC_PCIE_CFG_DATA] = 0x1fc, |
108 | [IPROC_PCIE_INTX_EN] = IPROC_PCIE_REG_INVALID, | 367 | }; |
109 | [IPROC_PCIE_OARR_LO] = IPROC_PCIE_REG_INVALID, | 368 | |
110 | [IPROC_PCIE_OARR_HI] = IPROC_PCIE_REG_INVALID, | 369 | /* iProc PCIe PAXC v2 registers */ |
111 | [IPROC_PCIE_OMAP_LO] = IPROC_PCIE_REG_INVALID, | 370 | static const u16 iproc_pcie_reg_paxc_v2[] = { |
112 | [IPROC_PCIE_OMAP_HI] = IPROC_PCIE_REG_INVALID, | 371 | [IPROC_PCIE_MSI_GIC_MODE] = 0x050, |
113 | [IPROC_PCIE_LINK_STATUS] = IPROC_PCIE_REG_INVALID, | 372 | [IPROC_PCIE_MSI_BASE_ADDR] = 0x074, |
373 | [IPROC_PCIE_MSI_WINDOW_SIZE] = 0x078, | ||
374 | [IPROC_PCIE_MSI_ADDR_LO] = 0x07c, | ||
375 | [IPROC_PCIE_MSI_ADDR_HI] = 0x080, | ||
376 | [IPROC_PCIE_MSI_EN_CFG] = 0x09c, | ||
377 | [IPROC_PCIE_CFG_IND_ADDR] = 0x1f0, | ||
378 | [IPROC_PCIE_CFG_IND_DATA] = 0x1f4, | ||
379 | [IPROC_PCIE_CFG_ADDR] = 0x1f8, | ||
380 | [IPROC_PCIE_CFG_DATA] = 0x1fc, | ||
114 | }; | 381 | }; |
115 | 382 | ||
116 | static inline struct iproc_pcie *iproc_data(struct pci_bus *bus) | 383 | static inline struct iproc_pcie *iproc_data(struct pci_bus *bus) |
@@ -159,16 +426,26 @@ static inline void iproc_pcie_write_reg(struct iproc_pcie *pcie, | |||
159 | writel(val, pcie->base + offset); | 426 | writel(val, pcie->base + offset); |
160 | } | 427 | } |
161 | 428 | ||
162 | static inline void iproc_pcie_ob_write(struct iproc_pcie *pcie, | 429 | /** |
163 | enum iproc_pcie_reg reg, | 430 | * APB error forwarding can be disabled during access of configuration |
164 | unsigned window, u32 val) | 431 | * registers of the endpoint device, to prevent unsupported requests |
432 | * (typically seen during enumeration with multi-function devices) from | ||
433 | * triggering a system exception. | ||
434 | */ | ||
435 | static inline void iproc_pcie_apb_err_disable(struct pci_bus *bus, | ||
436 | bool disable) | ||
165 | { | 437 | { |
166 | u16 offset = iproc_pcie_reg_offset(pcie, reg); | 438 | struct iproc_pcie *pcie = iproc_data(bus); |
167 | 439 | u32 val; | |
168 | if (iproc_pcie_reg_is_invalid(offset)) | ||
169 | return; | ||
170 | 440 | ||
171 | writel(val, pcie->base + offset + (window * 8)); | 441 | if (bus->number && pcie->has_apb_err_disable) { |
442 | val = iproc_pcie_read_reg(pcie, IPROC_PCIE_APB_ERR_EN); | ||
443 | if (disable) | ||
444 | val &= ~APB_ERR_EN; | ||
445 | else | ||
446 | val |= APB_ERR_EN; | ||
447 | iproc_pcie_write_reg(pcie, IPROC_PCIE_APB_ERR_EN, val); | ||
448 | } | ||
172 | } | 449 | } |
173 | 450 | ||
174 | /** | 451 | /** |
@@ -204,7 +481,7 @@ static void __iomem *iproc_pcie_map_cfg_bus(struct pci_bus *bus, | |||
204 | * PAXC is connected to an internally emulated EP within the SoC. It | 481 | * PAXC is connected to an internally emulated EP within the SoC. It |
205 | * allows only one device. | 482 | * allows only one device. |
206 | */ | 483 | */ |
207 | if (pcie->type == IPROC_PCIE_PAXC) | 484 | if (pcie->ep_is_internal) |
208 | if (slot > 0) | 485 | if (slot > 0) |
209 | return NULL; | 486 | return NULL; |
210 | 487 | ||
@@ -222,26 +499,47 @@ static void __iomem *iproc_pcie_map_cfg_bus(struct pci_bus *bus, | |||
222 | return (pcie->base + offset); | 499 | return (pcie->base + offset); |
223 | } | 500 | } |
224 | 501 | ||
502 | static int iproc_pcie_config_read32(struct pci_bus *bus, unsigned int devfn, | ||
503 | int where, int size, u32 *val) | ||
504 | { | ||
505 | int ret; | ||
506 | |||
507 | iproc_pcie_apb_err_disable(bus, true); | ||
508 | ret = pci_generic_config_read32(bus, devfn, where, size, val); | ||
509 | iproc_pcie_apb_err_disable(bus, false); | ||
510 | |||
511 | return ret; | ||
512 | } | ||
513 | |||
514 | static int iproc_pcie_config_write32(struct pci_bus *bus, unsigned int devfn, | ||
515 | int where, int size, u32 val) | ||
516 | { | ||
517 | int ret; | ||
518 | |||
519 | iproc_pcie_apb_err_disable(bus, true); | ||
520 | ret = pci_generic_config_write32(bus, devfn, where, size, val); | ||
521 | iproc_pcie_apb_err_disable(bus, false); | ||
522 | |||
523 | return ret; | ||
524 | } | ||
525 | |||
225 | static struct pci_ops iproc_pcie_ops = { | 526 | static struct pci_ops iproc_pcie_ops = { |
226 | .map_bus = iproc_pcie_map_cfg_bus, | 527 | .map_bus = iproc_pcie_map_cfg_bus, |
227 | .read = pci_generic_config_read32, | 528 | .read = iproc_pcie_config_read32, |
228 | .write = pci_generic_config_write32, | 529 | .write = iproc_pcie_config_write32, |
229 | }; | 530 | }; |
230 | 531 | ||
231 | static void iproc_pcie_reset(struct iproc_pcie *pcie) | 532 | static void iproc_pcie_reset(struct iproc_pcie *pcie) |
232 | { | 533 | { |
233 | u32 val; | 534 | u32 val; |
234 | 535 | ||
235 | if (pcie->type == IPROC_PCIE_PAXC) { | 536 | /* |
236 | val = iproc_pcie_read_reg(pcie, IPROC_PCIE_CLK_CTRL); | 537 | * PAXC and the internal emulated endpoint device downstream should not |
237 | val &= ~PAXC_RESET_MASK; | 538 | * be reset. If firmware has been loaded on the endpoint device at an |
238 | iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val); | 539 | * earlier boot stage, reset here causes issues. |
239 | udelay(100); | 540 | */ |
240 | val |= PAXC_RESET_MASK; | 541 | if (pcie->ep_is_internal) |
241 | iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val); | ||
242 | udelay(100); | ||
243 | return; | 542 | return; |
244 | } | ||
245 | 543 | ||
246 | /* | 544 | /* |
247 | * Select perst_b signal as reset source. Put the device into reset, | 545 | * Select perst_b signal as reset source. Put the device into reset, |
@@ -270,7 +568,7 @@ static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus) | |||
270 | * PAXC connects to emulated endpoint devices directly and does not | 568 | * PAXC connects to emulated endpoint devices directly and does not |
271 | * have a Serdes. Therefore skip the link detection logic here. | 569 | * have a Serdes. Therefore skip the link detection logic here. |
272 | */ | 570 | */ |
273 | if (pcie->type == IPROC_PCIE_PAXC) | 571 | if (pcie->ep_is_internal) |
274 | return 0; | 572 | return 0; |
275 | 573 | ||
276 | val = iproc_pcie_read_reg(pcie, IPROC_PCIE_LINK_STATUS); | 574 | val = iproc_pcie_read_reg(pcie, IPROC_PCIE_LINK_STATUS); |
@@ -334,6 +632,58 @@ static void iproc_pcie_enable(struct iproc_pcie *pcie) | |||
334 | iproc_pcie_write_reg(pcie, IPROC_PCIE_INTX_EN, SYS_RC_INTX_MASK); | 632 | iproc_pcie_write_reg(pcie, IPROC_PCIE_INTX_EN, SYS_RC_INTX_MASK); |
335 | } | 633 | } |
336 | 634 | ||
635 | static inline bool iproc_pcie_ob_is_valid(struct iproc_pcie *pcie, | ||
636 | int window_idx) | ||
637 | { | ||
638 | u32 val; | ||
639 | |||
640 | val = iproc_pcie_read_reg(pcie, MAP_REG(IPROC_PCIE_OARR0, window_idx)); | ||
641 | |||
642 | return !!(val & OARR_VALID); | ||
643 | } | ||
644 | |||
645 | static inline int iproc_pcie_ob_write(struct iproc_pcie *pcie, int window_idx, | ||
646 | int size_idx, u64 axi_addr, u64 pci_addr) | ||
647 | { | ||
648 | struct device *dev = pcie->dev; | ||
649 | u16 oarr_offset, omap_offset; | ||
650 | |||
651 | /* | ||
652 | * Derive the OARR/OMAP offset from the first pair (OARR0/OMAP0) based | ||
653 | * on window index. | ||
654 | */ | ||
655 | oarr_offset = iproc_pcie_reg_offset(pcie, MAP_REG(IPROC_PCIE_OARR0, | ||
656 | window_idx)); | ||
657 | omap_offset = iproc_pcie_reg_offset(pcie, MAP_REG(IPROC_PCIE_OMAP0, | ||
658 | window_idx)); | ||
659 | if (iproc_pcie_reg_is_invalid(oarr_offset) || | ||
660 | iproc_pcie_reg_is_invalid(omap_offset)) | ||
661 | return -EINVAL; | ||
662 | |||
663 | /* | ||
664 | * Program the OARR registers. The upper 32-bit OARR register is | ||
665 | * always right after the lower 32-bit OARR register. | ||
666 | */ | ||
667 | writel(lower_32_bits(axi_addr) | (size_idx << OARR_SIZE_CFG_SHIFT) | | ||
668 | OARR_VALID, pcie->base + oarr_offset); | ||
669 | writel(upper_32_bits(axi_addr), pcie->base + oarr_offset + 4); | ||
670 | |||
671 | /* now program the OMAP registers */ | ||
672 | writel(lower_32_bits(pci_addr), pcie->base + omap_offset); | ||
673 | writel(upper_32_bits(pci_addr), pcie->base + omap_offset + 4); | ||
674 | |||
675 | dev_info(dev, "ob window [%d]: offset 0x%x axi %pap pci %pap\n", | ||
676 | window_idx, oarr_offset, &axi_addr, &pci_addr); | ||
677 | dev_info(dev, "oarr lo 0x%x oarr hi 0x%x\n", | ||
678 | readl(pcie->base + oarr_offset), | ||
679 | readl(pcie->base + oarr_offset + 4)); | ||
680 | dev_info(dev, "omap lo 0x%x omap hi 0x%x\n", | ||
681 | readl(pcie->base + omap_offset), | ||
682 | readl(pcie->base + omap_offset + 4)); | ||
683 | |||
684 | return 0; | ||
685 | } | ||
686 | |||
337 | /** | 687 | /** |
338 | * Some iProc SoCs require the SW to configure the outbound address mapping | 688 | * Some iProc SoCs require the SW to configure the outbound address mapping |
339 | * | 689 | * |
@@ -350,24 +700,7 @@ static int iproc_pcie_setup_ob(struct iproc_pcie *pcie, u64 axi_addr, | |||
350 | { | 700 | { |
351 | struct iproc_pcie_ob *ob = &pcie->ob; | 701 | struct iproc_pcie_ob *ob = &pcie->ob; |
352 | struct device *dev = pcie->dev; | 702 | struct device *dev = pcie->dev; |
353 | unsigned i; | 703 | int ret = -EINVAL, window_idx, size_idx; |
354 | u64 max_size = (u64)ob->window_size * MAX_NUM_OB_WINDOWS; | ||
355 | u64 remainder; | ||
356 | |||
357 | if (size > max_size) { | ||
358 | dev_err(dev, | ||
359 | "res size %pap exceeds max supported size 0x%llx\n", | ||
360 | &size, max_size); | ||
361 | return -EINVAL; | ||
362 | } | ||
363 | |||
364 | div64_u64_rem(size, ob->window_size, &remainder); | ||
365 | if (remainder) { | ||
366 | dev_err(dev, | ||
367 | "res size %pap needs to be multiple of window size %pap\n", | ||
368 | &size, &ob->window_size); | ||
369 | return -EINVAL; | ||
370 | } | ||
371 | 704 | ||
372 | if (axi_addr < ob->axi_offset) { | 705 | if (axi_addr < ob->axi_offset) { |
373 | dev_err(dev, "axi address %pap less than offset %pap\n", | 706 | dev_err(dev, "axi address %pap less than offset %pap\n", |
@@ -381,26 +714,70 @@ static int iproc_pcie_setup_ob(struct iproc_pcie *pcie, u64 axi_addr, | |||
381 | */ | 714 | */ |
382 | axi_addr -= ob->axi_offset; | 715 | axi_addr -= ob->axi_offset; |
383 | 716 | ||
384 | for (i = 0; i < MAX_NUM_OB_WINDOWS; i++) { | 717 | /* iterate through all OARR/OMAP mapping windows */ |
385 | iproc_pcie_ob_write(pcie, IPROC_PCIE_OARR_LO, i, | 718 | for (window_idx = ob->nr_windows - 1; window_idx >= 0; window_idx--) { |
386 | lower_32_bits(axi_addr) | OARR_VALID | | 719 | const struct iproc_pcie_ob_map *ob_map = |
387 | (ob->set_oarr_size ? 1 : 0)); | 720 | &pcie->ob_map[window_idx]; |
388 | iproc_pcie_ob_write(pcie, IPROC_PCIE_OARR_HI, i, | 721 | |
389 | upper_32_bits(axi_addr)); | 722 | /* |
390 | iproc_pcie_ob_write(pcie, IPROC_PCIE_OMAP_LO, i, | 723 | * If current outbound window is already in use, move on to the |
391 | lower_32_bits(pci_addr)); | 724 | * next one. |
392 | iproc_pcie_ob_write(pcie, IPROC_PCIE_OMAP_HI, i, | 725 | */ |
393 | upper_32_bits(pci_addr)); | 726 | if (iproc_pcie_ob_is_valid(pcie, window_idx)) |
394 | 727 | continue; | |
395 | size -= ob->window_size; | 728 | |
396 | if (size == 0) | 729 | /* |
730 | * Iterate through all supported window sizes within the | ||
731 | * OARR/OMAP pair to find a match. Go through the window sizes | ||
732 | * in a descending order. | ||
733 | */ | ||
734 | for (size_idx = ob_map->nr_sizes - 1; size_idx >= 0; | ||
735 | size_idx--) { | ||
736 | resource_size_t window_size = | ||
737 | ob_map->window_sizes[size_idx] * SZ_1M; | ||
738 | |||
739 | if (size < window_size) | ||
740 | continue; | ||
741 | |||
742 | if (!IS_ALIGNED(axi_addr, window_size) || | ||
743 | !IS_ALIGNED(pci_addr, window_size)) { | ||
744 | dev_err(dev, | ||
745 | "axi %pap or pci %pap not aligned\n", | ||
746 | &axi_addr, &pci_addr); | ||
747 | return -EINVAL; | ||
748 | } | ||
749 | |||
750 | /* | ||
751 | * Match found! Program both OARR and OMAP and mark | ||
752 | * them as a valid entry. | ||
753 | */ | ||
754 | ret = iproc_pcie_ob_write(pcie, window_idx, size_idx, | ||
755 | axi_addr, pci_addr); | ||
756 | if (ret) | ||
757 | goto err_ob; | ||
758 | |||
759 | size -= window_size; | ||
760 | if (size == 0) | ||
761 | return 0; | ||
762 | |||
763 | /* | ||
764 | * If we are here, we are done with the current window, | ||
765 | * but not yet finished all mappings. Need to move on | ||
766 | * to the next window. | ||
767 | */ | ||
768 | axi_addr += window_size; | ||
769 | pci_addr += window_size; | ||
397 | break; | 770 | break; |
398 | 771 | } | |
399 | axi_addr += ob->window_size; | ||
400 | pci_addr += ob->window_size; | ||
401 | } | 772 | } |
402 | 773 | ||
403 | return 0; | 774 | err_ob: |
775 | dev_err(dev, "unable to configure outbound mapping\n"); | ||
776 | dev_err(dev, | ||
777 | "axi %pap, axi offset %pap, pci %pap, res size %pap\n", | ||
778 | &axi_addr, &ob->axi_offset, &pci_addr, &size); | ||
779 | |||
780 | return ret; | ||
404 | } | 781 | } |
405 | 782 | ||
406 | static int iproc_pcie_map_ranges(struct iproc_pcie *pcie, | 783 | static int iproc_pcie_map_ranges(struct iproc_pcie *pcie, |
@@ -434,13 +811,323 @@ static int iproc_pcie_map_ranges(struct iproc_pcie *pcie, | |||
434 | return 0; | 811 | return 0; |
435 | } | 812 | } |
436 | 813 | ||
814 | static inline bool iproc_pcie_ib_is_in_use(struct iproc_pcie *pcie, | ||
815 | int region_idx) | ||
816 | { | ||
817 | const struct iproc_pcie_ib_map *ib_map = &pcie->ib_map[region_idx]; | ||
818 | u32 val; | ||
819 | |||
820 | val = iproc_pcie_read_reg(pcie, MAP_REG(IPROC_PCIE_IARR0, region_idx)); | ||
821 | |||
822 | return !!(val & (BIT(ib_map->nr_sizes) - 1)); | ||
823 | } | ||
824 | |||
825 | static inline bool iproc_pcie_ib_check_type(const struct iproc_pcie_ib_map *ib_map, | ||
826 | enum iproc_pcie_ib_map_type type) | ||
827 | { | ||
828 | return !!(ib_map->type == type); | ||
829 | } | ||
830 | |||
831 | static int iproc_pcie_ib_write(struct iproc_pcie *pcie, int region_idx, | ||
832 | int size_idx, int nr_windows, u64 axi_addr, | ||
833 | u64 pci_addr, resource_size_t size) | ||
834 | { | ||
835 | struct device *dev = pcie->dev; | ||
836 | const struct iproc_pcie_ib_map *ib_map = &pcie->ib_map[region_idx]; | ||
837 | u16 iarr_offset, imap_offset; | ||
838 | u32 val; | ||
839 | int window_idx; | ||
840 | |||
841 | iarr_offset = iproc_pcie_reg_offset(pcie, | ||
842 | MAP_REG(IPROC_PCIE_IARR0, region_idx)); | ||
843 | imap_offset = iproc_pcie_reg_offset(pcie, | ||
844 | MAP_REG(IPROC_PCIE_IMAP0, region_idx)); | ||
845 | if (iproc_pcie_reg_is_invalid(iarr_offset) || | ||
846 | iproc_pcie_reg_is_invalid(imap_offset)) | ||
847 | return -EINVAL; | ||
848 | |||
849 | dev_info(dev, "ib region [%d]: offset 0x%x axi %pap pci %pap\n", | ||
850 | region_idx, iarr_offset, &axi_addr, &pci_addr); | ||
851 | |||
852 | /* | ||
853 | * Program the IARR registers. The upper 32-bit IARR register is | ||
854 | * always right after the lower 32-bit IARR register. | ||
855 | */ | ||
856 | writel(lower_32_bits(pci_addr) | BIT(size_idx), | ||
857 | pcie->base + iarr_offset); | ||
858 | writel(upper_32_bits(pci_addr), pcie->base + iarr_offset + 4); | ||
859 | |||
860 | dev_info(dev, "iarr lo 0x%x iarr hi 0x%x\n", | ||
861 | readl(pcie->base + iarr_offset), | ||
862 | readl(pcie->base + iarr_offset + 4)); | ||
863 | |||
864 | /* | ||
865 | * Now program the IMAP registers. Each IARR region may have one or | ||
866 | * more IMAP windows. | ||
867 | */ | ||
868 | size >>= ilog2(nr_windows); | ||
869 | for (window_idx = 0; window_idx < nr_windows; window_idx++) { | ||
870 | val = readl(pcie->base + imap_offset); | ||
871 | val |= lower_32_bits(axi_addr) | IMAP_VALID; | ||
872 | writel(val, pcie->base + imap_offset); | ||
873 | writel(upper_32_bits(axi_addr), | ||
874 | pcie->base + imap_offset + ib_map->imap_addr_offset); | ||
875 | |||
876 | dev_info(dev, "imap window [%d] lo 0x%x hi 0x%x\n", | ||
877 | window_idx, readl(pcie->base + imap_offset), | ||
878 | readl(pcie->base + imap_offset + | ||
879 | ib_map->imap_addr_offset)); | ||
880 | |||
881 | imap_offset += ib_map->imap_window_offset; | ||
882 | axi_addr += size; | ||
883 | } | ||
884 | |||
885 | return 0; | ||
886 | } | ||
887 | |||
888 | static int iproc_pcie_setup_ib(struct iproc_pcie *pcie, | ||
889 | struct of_pci_range *range, | ||
890 | enum iproc_pcie_ib_map_type type) | ||
891 | { | ||
892 | struct device *dev = pcie->dev; | ||
893 | struct iproc_pcie_ib *ib = &pcie->ib; | ||
894 | int ret; | ||
895 | unsigned int region_idx, size_idx; | ||
896 | u64 axi_addr = range->cpu_addr, pci_addr = range->pci_addr; | ||
897 | resource_size_t size = range->size; | ||
898 | |||
899 | /* iterate through all IARR mapping regions */ | ||
900 | for (region_idx = 0; region_idx < ib->nr_regions; region_idx++) { | ||
901 | const struct iproc_pcie_ib_map *ib_map = | ||
902 | &pcie->ib_map[region_idx]; | ||
903 | |||
904 | /* | ||
905 | * If current inbound region is already in use or not a | ||
906 | * compatible type, move on to the next. | ||
907 | */ | ||
908 | if (iproc_pcie_ib_is_in_use(pcie, region_idx) || | ||
909 | !iproc_pcie_ib_check_type(ib_map, type)) | ||
910 | continue; | ||
911 | |||
912 | /* iterate through all supported region sizes to find a match */ | ||
913 | for (size_idx = 0; size_idx < ib_map->nr_sizes; size_idx++) { | ||
914 | resource_size_t region_size = | ||
915 | ib_map->region_sizes[size_idx] * ib_map->size_unit; | ||
916 | |||
917 | if (size != region_size) | ||
918 | continue; | ||
919 | |||
920 | if (!IS_ALIGNED(axi_addr, region_size) || | ||
921 | !IS_ALIGNED(pci_addr, region_size)) { | ||
922 | dev_err(dev, | ||
923 | "axi %pap or pci %pap not aligned\n", | ||
924 | &axi_addr, &pci_addr); | ||
925 | return -EINVAL; | ||
926 | } | ||
927 | |||
928 | /* Match found! Program IARR and all IMAP windows. */ | ||
929 | ret = iproc_pcie_ib_write(pcie, region_idx, size_idx, | ||
930 | ib_map->nr_windows, axi_addr, | ||
931 | pci_addr, size); | ||
932 | if (ret) | ||
933 | goto err_ib; | ||
934 | else | ||
935 | return 0; | ||
936 | |||
937 | } | ||
938 | } | ||
939 | ret = -EINVAL; | ||
940 | |||
941 | err_ib: | ||
942 | dev_err(dev, "unable to configure inbound mapping\n"); | ||
943 | dev_err(dev, "axi %pap, pci %pap, res size %pap\n", | ||
944 | &axi_addr, &pci_addr, &size); | ||
945 | |||
946 | return ret; | ||
947 | } | ||
948 | |||
949 | static int pci_dma_range_parser_init(struct of_pci_range_parser *parser, | ||
950 | struct device_node *node) | ||
951 | { | ||
952 | const int na = 3, ns = 2; | ||
953 | int rlen; | ||
954 | |||
955 | parser->node = node; | ||
956 | parser->pna = of_n_addr_cells(node); | ||
957 | parser->np = parser->pna + na + ns; | ||
958 | |||
959 | parser->range = of_get_property(node, "dma-ranges", &rlen); | ||
960 | if (!parser->range) | ||
961 | return -ENOENT; | ||
962 | |||
963 | parser->end = parser->range + rlen / sizeof(__be32); | ||
964 | return 0; | ||
965 | } | ||
966 | |||
967 | static int iproc_pcie_map_dma_ranges(struct iproc_pcie *pcie) | ||
968 | { | ||
969 | struct of_pci_range range; | ||
970 | struct of_pci_range_parser parser; | ||
971 | int ret; | ||
972 | |||
973 | /* Get the dma-ranges from DT */ | ||
974 | ret = pci_dma_range_parser_init(&parser, pcie->dev->of_node); | ||
975 | if (ret) | ||
976 | return ret; | ||
977 | |||
978 | for_each_of_pci_range(&parser, &range) { | ||
979 | /* Each range entry corresponds to an inbound mapping region */ | ||
980 | ret = iproc_pcie_setup_ib(pcie, &range, IPROC_PCIE_IB_MAP_MEM); | ||
981 | if (ret) | ||
982 | return ret; | ||
983 | } | ||
984 | |||
985 | return 0; | ||
986 | } | ||
987 | |||
988 | static int iproce_pcie_get_msi(struct iproc_pcie *pcie, | ||
989 | struct device_node *msi_node, | ||
990 | u64 *msi_addr) | ||
991 | { | ||
992 | struct device *dev = pcie->dev; | ||
993 | int ret; | ||
994 | struct resource res; | ||
995 | |||
996 | /* | ||
997 | * Check if 'msi-map' points to ARM GICv3 ITS, which is the only | ||
998 | * supported external MSI controller that requires steering. | ||
999 | */ | ||
1000 | if (!of_device_is_compatible(msi_node, "arm,gic-v3-its")) { | ||
1001 | dev_err(dev, "unable to find compatible MSI controller\n"); | ||
1002 | return -ENODEV; | ||
1003 | } | ||
1004 | |||
1005 | /* derive GITS_TRANSLATER address from GICv3 */ | ||
1006 | ret = of_address_to_resource(msi_node, 0, &res); | ||
1007 | if (ret < 0) { | ||
1008 | dev_err(dev, "unable to obtain MSI controller resources\n"); | ||
1009 | return ret; | ||
1010 | } | ||
1011 | |||
1012 | *msi_addr = res.start + GITS_TRANSLATER; | ||
1013 | return 0; | ||
1014 | } | ||
1015 | |||
1016 | static int iproc_pcie_paxb_v2_msi_steer(struct iproc_pcie *pcie, u64 msi_addr) | ||
1017 | { | ||
1018 | int ret; | ||
1019 | struct of_pci_range range; | ||
1020 | |||
1021 | memset(&range, 0, sizeof(range)); | ||
1022 | range.size = SZ_32K; | ||
1023 | range.pci_addr = range.cpu_addr = msi_addr & ~(range.size - 1); | ||
1024 | |||
1025 | ret = iproc_pcie_setup_ib(pcie, &range, IPROC_PCIE_IB_MAP_IO); | ||
1026 | return ret; | ||
1027 | } | ||
1028 | |||
1029 | static void iproc_pcie_paxc_v2_msi_steer(struct iproc_pcie *pcie, u64 msi_addr) | ||
1030 | { | ||
1031 | u32 val; | ||
1032 | |||
1033 | /* | ||
1034 | * Program bits [43:13] of address of GITS_TRANSLATER register into | ||
1035 | * bits [30:0] of the MSI base address register. In fact, in all iProc | ||
1036 | * based SoCs, all I/O register bases are well below the 32-bit | ||
1037 | * boundary, so we can safely assume bits [43:32] are always zeros. | ||
1038 | */ | ||
1039 | iproc_pcie_write_reg(pcie, IPROC_PCIE_MSI_BASE_ADDR, | ||
1040 | (u32)(msi_addr >> 13)); | ||
1041 | |||
1042 | /* use a default 8K window size */ | ||
1043 | iproc_pcie_write_reg(pcie, IPROC_PCIE_MSI_WINDOW_SIZE, 0); | ||
1044 | |||
1045 | /* steering MSI to GICv3 ITS */ | ||
1046 | val = iproc_pcie_read_reg(pcie, IPROC_PCIE_MSI_GIC_MODE); | ||
1047 | val |= GIC_V3_CFG; | ||
1048 | iproc_pcie_write_reg(pcie, IPROC_PCIE_MSI_GIC_MODE, val); | ||
1049 | |||
1050 | /* | ||
1051 | * Program bits [43:2] of address of GITS_TRANSLATER register into the | ||
1052 | * iProc MSI address registers. | ||
1053 | */ | ||
1054 | msi_addr >>= 2; | ||
1055 | iproc_pcie_write_reg(pcie, IPROC_PCIE_MSI_ADDR_HI, | ||
1056 | upper_32_bits(msi_addr)); | ||
1057 | iproc_pcie_write_reg(pcie, IPROC_PCIE_MSI_ADDR_LO, | ||
1058 | lower_32_bits(msi_addr)); | ||
1059 | |||
1060 | /* enable MSI */ | ||
1061 | val = iproc_pcie_read_reg(pcie, IPROC_PCIE_MSI_EN_CFG); | ||
1062 | val |= MSI_ENABLE_CFG; | ||
1063 | iproc_pcie_write_reg(pcie, IPROC_PCIE_MSI_EN_CFG, val); | ||
1064 | } | ||
1065 | |||
1066 | static int iproc_pcie_msi_steer(struct iproc_pcie *pcie, | ||
1067 | struct device_node *msi_node) | ||
1068 | { | ||
1069 | struct device *dev = pcie->dev; | ||
1070 | int ret; | ||
1071 | u64 msi_addr; | ||
1072 | |||
1073 | ret = iproce_pcie_get_msi(pcie, msi_node, &msi_addr); | ||
1074 | if (ret < 0) { | ||
1075 | dev_err(dev, "msi steering failed\n"); | ||
1076 | return ret; | ||
1077 | } | ||
1078 | |||
1079 | switch (pcie->type) { | ||
1080 | case IPROC_PCIE_PAXB_V2: | ||
1081 | ret = iproc_pcie_paxb_v2_msi_steer(pcie, msi_addr); | ||
1082 | if (ret) | ||
1083 | return ret; | ||
1084 | break; | ||
1085 | case IPROC_PCIE_PAXC_V2: | ||
1086 | iproc_pcie_paxc_v2_msi_steer(pcie, msi_addr); | ||
1087 | break; | ||
1088 | default: | ||
1089 | return -EINVAL; | ||
1090 | } | ||
1091 | |||
1092 | return 0; | ||
1093 | } | ||
1094 | |||
437 | static int iproc_pcie_msi_enable(struct iproc_pcie *pcie) | 1095 | static int iproc_pcie_msi_enable(struct iproc_pcie *pcie) |
438 | { | 1096 | { |
439 | struct device_node *msi_node; | 1097 | struct device_node *msi_node; |
1098 | int ret; | ||
1099 | |||
1100 | /* | ||
1101 | * Either the "msi-parent" or the "msi-map" phandle needs to exist | ||
1102 | * for us to obtain the MSI node. | ||
1103 | */ | ||
440 | 1104 | ||
441 | msi_node = of_parse_phandle(pcie->dev->of_node, "msi-parent", 0); | 1105 | msi_node = of_parse_phandle(pcie->dev->of_node, "msi-parent", 0); |
442 | if (!msi_node) | 1106 | if (!msi_node) { |
443 | return -ENODEV; | 1107 | const __be32 *msi_map = NULL; |
1108 | int len; | ||
1109 | u32 phandle; | ||
1110 | |||
1111 | msi_map = of_get_property(pcie->dev->of_node, "msi-map", &len); | ||
1112 | if (!msi_map) | ||
1113 | return -ENODEV; | ||
1114 | |||
1115 | phandle = be32_to_cpup(msi_map + 1); | ||
1116 | msi_node = of_find_node_by_phandle(phandle); | ||
1117 | if (!msi_node) | ||
1118 | return -ENODEV; | ||
1119 | } | ||
1120 | |||
1121 | /* | ||
1122 | * Certain revisions of the iProc PCIe controller require additional | ||
1123 | * configurations to steer the MSI writes towards an external MSI | ||
1124 | * controller. | ||
1125 | */ | ||
1126 | if (pcie->need_msi_steer) { | ||
1127 | ret = iproc_pcie_msi_steer(pcie, msi_node); | ||
1128 | if (ret) | ||
1129 | return ret; | ||
1130 | } | ||
444 | 1131 | ||
445 | /* | 1132 | /* |
446 | * If another MSI controller is being used, the call below should fail | 1133 | * If another MSI controller is being used, the call below should fail |
@@ -454,6 +1141,65 @@ static void iproc_pcie_msi_disable(struct iproc_pcie *pcie) | |||
454 | iproc_msi_exit(pcie); | 1141 | iproc_msi_exit(pcie); |
455 | } | 1142 | } |
456 | 1143 | ||
1144 | static int iproc_pcie_rev_init(struct iproc_pcie *pcie) | ||
1145 | { | ||
1146 | struct device *dev = pcie->dev; | ||
1147 | unsigned int reg_idx; | ||
1148 | const u16 *regs; | ||
1149 | |||
1150 | switch (pcie->type) { | ||
1151 | case IPROC_PCIE_PAXB_BCMA: | ||
1152 | regs = iproc_pcie_reg_paxb_bcma; | ||
1153 | break; | ||
1154 | case IPROC_PCIE_PAXB: | ||
1155 | regs = iproc_pcie_reg_paxb; | ||
1156 | pcie->has_apb_err_disable = true; | ||
1157 | if (pcie->need_ob_cfg) { | ||
1158 | pcie->ob_map = paxb_ob_map; | ||
1159 | pcie->ob.nr_windows = ARRAY_SIZE(paxb_ob_map); | ||
1160 | } | ||
1161 | break; | ||
1162 | case IPROC_PCIE_PAXB_V2: | ||
1163 | regs = iproc_pcie_reg_paxb_v2; | ||
1164 | pcie->has_apb_err_disable = true; | ||
1165 | if (pcie->need_ob_cfg) { | ||
1166 | pcie->ob_map = paxb_v2_ob_map; | ||
1167 | pcie->ob.nr_windows = ARRAY_SIZE(paxb_v2_ob_map); | ||
1168 | } | ||
1169 | pcie->ib.nr_regions = ARRAY_SIZE(paxb_v2_ib_map); | ||
1170 | pcie->ib_map = paxb_v2_ib_map; | ||
1171 | pcie->need_msi_steer = true; | ||
1172 | break; | ||
1173 | case IPROC_PCIE_PAXC: | ||
1174 | regs = iproc_pcie_reg_paxc; | ||
1175 | pcie->ep_is_internal = true; | ||
1176 | break; | ||
1177 | case IPROC_PCIE_PAXC_V2: | ||
1178 | regs = iproc_pcie_reg_paxc_v2; | ||
1179 | pcie->ep_is_internal = true; | ||
1180 | pcie->need_msi_steer = true; | ||
1181 | break; | ||
1182 | default: | ||
1183 | dev_err(dev, "incompatible iProc PCIe interface\n"); | ||
1184 | return -EINVAL; | ||
1185 | } | ||
1186 | |||
1187 | pcie->reg_offsets = devm_kcalloc(dev, IPROC_PCIE_MAX_NUM_REG, | ||
1188 | sizeof(*pcie->reg_offsets), | ||
1189 | GFP_KERNEL); | ||
1190 | if (!pcie->reg_offsets) | ||
1191 | return -ENOMEM; | ||
1192 | |||
1193 | /* go through the register table and populate all valid registers */ | ||
1194 | pcie->reg_offsets[0] = (pcie->type == IPROC_PCIE_PAXC_V2) ? | ||
1195 | IPROC_PCIE_REG_INVALID : regs[0]; | ||
1196 | for (reg_idx = 1; reg_idx < IPROC_PCIE_MAX_NUM_REG; reg_idx++) | ||
1197 | pcie->reg_offsets[reg_idx] = regs[reg_idx] ? | ||
1198 | regs[reg_idx] : IPROC_PCIE_REG_INVALID; | ||
1199 | |||
1200 | return 0; | ||
1201 | } | ||
1202 | |||
457 | int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) | 1203 | int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) |
458 | { | 1204 | { |
459 | struct device *dev; | 1205 | struct device *dev; |
@@ -462,6 +1208,13 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) | |||
462 | struct pci_bus *bus; | 1208 | struct pci_bus *bus; |
463 | 1209 | ||
464 | dev = pcie->dev; | 1210 | dev = pcie->dev; |
1211 | |||
1212 | ret = iproc_pcie_rev_init(pcie); | ||
1213 | if (ret) { | ||
1214 | dev_err(dev, "unable to initialize controller parameters\n"); | ||
1215 | return ret; | ||
1216 | } | ||
1217 | |||
465 | ret = devm_request_pci_bus_resources(dev, res); | 1218 | ret = devm_request_pci_bus_resources(dev, res); |
466 | if (ret) | 1219 | if (ret) |
467 | return ret; | 1220 | return ret; |
@@ -478,19 +1231,6 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) | |||
478 | goto err_exit_phy; | 1231 | goto err_exit_phy; |
479 | } | 1232 | } |
480 | 1233 | ||
481 | switch (pcie->type) { | ||
482 | case IPROC_PCIE_PAXB: | ||
483 | pcie->reg_offsets = iproc_pcie_reg_paxb; | ||
484 | break; | ||
485 | case IPROC_PCIE_PAXC: | ||
486 | pcie->reg_offsets = iproc_pcie_reg_paxc; | ||
487 | break; | ||
488 | default: | ||
489 | dev_err(dev, "incompatible iProc PCIe interface\n"); | ||
490 | ret = -EINVAL; | ||
491 | goto err_power_off_phy; | ||
492 | } | ||
493 | |||
494 | iproc_pcie_reset(pcie); | 1234 | iproc_pcie_reset(pcie); |
495 | 1235 | ||
496 | if (pcie->need_ob_cfg) { | 1236 | if (pcie->need_ob_cfg) { |
@@ -501,6 +1241,10 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) | |||
501 | } | 1241 | } |
502 | } | 1242 | } |
503 | 1243 | ||
1244 | ret = iproc_pcie_map_dma_ranges(pcie); | ||
1245 | if (ret && ret != -ENOENT) | ||
1246 | goto err_power_off_phy; | ||
1247 | |||
504 | #ifdef CONFIG_ARM | 1248 | #ifdef CONFIG_ARM |
505 | pcie->sysdata.private_data = pcie; | 1249 | pcie->sysdata.private_data = pcie; |
506 | sysdata = &pcie->sysdata; | 1250 | sysdata = &pcie->sysdata; |
@@ -530,7 +1274,10 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) | |||
530 | 1274 | ||
531 | pci_scan_child_bus(bus); | 1275 | pci_scan_child_bus(bus); |
532 | pci_assign_unassigned_bus_resources(bus); | 1276 | pci_assign_unassigned_bus_resources(bus); |
533 | pci_fixup_irqs(pci_common_swizzle, pcie->map_irq); | 1277 | |
1278 | if (pcie->map_irq) | ||
1279 | pci_fixup_irqs(pci_common_swizzle, pcie->map_irq); | ||
1280 | |||
534 | pci_bus_add_devices(bus); | 1281 | pci_bus_add_devices(bus); |
535 | 1282 | ||
536 | return 0; | 1283 | return 0; |
diff --git a/drivers/pci/host/pcie-iproc.h b/drivers/pci/host/pcie-iproc.h index e84d93c53c7b..04fed8e907f1 100644 --- a/drivers/pci/host/pcie-iproc.h +++ b/drivers/pci/host/pcie-iproc.h | |||
@@ -24,23 +24,34 @@ | |||
24 | * endpoint devices. | 24 | * endpoint devices. |
25 | */ | 25 | */ |
26 | enum iproc_pcie_type { | 26 | enum iproc_pcie_type { |
27 | IPROC_PCIE_PAXB = 0, | 27 | IPROC_PCIE_PAXB_BCMA = 0, |
28 | IPROC_PCIE_PAXB, | ||
29 | IPROC_PCIE_PAXB_V2, | ||
28 | IPROC_PCIE_PAXC, | 30 | IPROC_PCIE_PAXC, |
31 | IPROC_PCIE_PAXC_V2, | ||
29 | }; | 32 | }; |
30 | 33 | ||
31 | /** | 34 | /** |
32 | * iProc PCIe outbound mapping | 35 | * iProc PCIe outbound mapping |
33 | * @set_oarr_size: indicates the OARR size bit needs to be set | ||
34 | * @axi_offset: offset from the AXI address to the internal address used by | 36 | * @axi_offset: offset from the AXI address to the internal address used by |
35 | * the iProc PCIe core | 37 | * the iProc PCIe core |
36 | * @window_size: outbound window size | 38 | * @nr_windows: total number of supported outbound mapping windows |
37 | */ | 39 | */ |
38 | struct iproc_pcie_ob { | 40 | struct iproc_pcie_ob { |
39 | bool set_oarr_size; | ||
40 | resource_size_t axi_offset; | 41 | resource_size_t axi_offset; |
41 | resource_size_t window_size; | 42 | unsigned int nr_windows; |
42 | }; | 43 | }; |
43 | 44 | ||
45 | /** | ||
46 | * iProc PCIe inbound mapping | ||
47 | * @nr_regions: total number of supported inbound mapping regions | ||
48 | */ | ||
49 | struct iproc_pcie_ib { | ||
50 | unsigned int nr_regions; | ||
51 | }; | ||
52 | |||
53 | struct iproc_pcie_ob_map; | ||
54 | struct iproc_pcie_ib_map; | ||
44 | struct iproc_msi; | 55 | struct iproc_msi; |
45 | 56 | ||
46 | /** | 57 | /** |
@@ -55,14 +66,25 @@ struct iproc_msi; | |||
55 | * @root_bus: pointer to root bus | 66 | * @root_bus: pointer to root bus |
56 | * @phy: optional PHY device that controls the Serdes | 67 | * @phy: optional PHY device that controls the Serdes |
57 | * @map_irq: function callback to map interrupts | 68 | * @map_irq: function callback to map interrupts |
69 | * @ep_is_internal: indicates an internal emulated endpoint device is connected | ||
70 | * @has_apb_err_disable: indicates the controller can be configured to prevent | ||
71 | * unsupported request from being forwarded as an APB bus error | ||
72 | * | ||
58 | * @need_ob_cfg: indicates SW needs to configure the outbound mapping window | 73 | * @need_ob_cfg: indicates SW needs to configure the outbound mapping window |
59 | * @ob: outbound mapping parameters | 74 | * @ob: outbound mapping related parameters |
75 | * @ob_map: outbound mapping related parameters specific to the controller | ||
76 | * | ||
77 | * @ib: inbound mapping related parameters | ||
78 | * @ib_map: outbound mapping region related parameters | ||
79 | * | ||
80 | * @need_msi_steer: indicates additional configuration of the iProc PCIe | ||
81 | * controller is required to steer MSI writes to external interrupt controller | ||
60 | * @msi: MSI data | 82 | * @msi: MSI data |
61 | */ | 83 | */ |
62 | struct iproc_pcie { | 84 | struct iproc_pcie { |
63 | struct device *dev; | 85 | struct device *dev; |
64 | enum iproc_pcie_type type; | 86 | enum iproc_pcie_type type; |
65 | const u16 *reg_offsets; | 87 | u16 *reg_offsets; |
66 | void __iomem *base; | 88 | void __iomem *base; |
67 | phys_addr_t base_addr; | 89 | phys_addr_t base_addr; |
68 | #ifdef CONFIG_ARM | 90 | #ifdef CONFIG_ARM |
@@ -71,8 +93,17 @@ struct iproc_pcie { | |||
71 | struct pci_bus *root_bus; | 93 | struct pci_bus *root_bus; |
72 | struct phy *phy; | 94 | struct phy *phy; |
73 | int (*map_irq)(const struct pci_dev *, u8, u8); | 95 | int (*map_irq)(const struct pci_dev *, u8, u8); |
96 | bool ep_is_internal; | ||
97 | bool has_apb_err_disable; | ||
98 | |||
74 | bool need_ob_cfg; | 99 | bool need_ob_cfg; |
75 | struct iproc_pcie_ob ob; | 100 | struct iproc_pcie_ob ob; |
101 | const struct iproc_pcie_ob_map *ob_map; | ||
102 | |||
103 | struct iproc_pcie_ib ib; | ||
104 | const struct iproc_pcie_ib_map *ib_map; | ||
105 | |||
106 | bool need_msi_steer; | ||
76 | struct iproc_msi *msi; | 107 | struct iproc_msi *msi; |
77 | }; | 108 | }; |
78 | 109 | ||