brcm2708: update to latest patches from RPi foundation
[openwrt/openwrt.git] / target / linux / brcm2708 / patches-4.19 / 950-0529-PCI-brcmstb-Add-MSI-capability.patch
1 From cd3af4fa73ab25353f0865ebe8e0d2af1fd2a50b Mon Sep 17 00:00:00 2001
2 From: Phil Elwell <phil@raspberrypi.org>
3 Date: Tue, 19 Feb 2019 22:06:59 +0000
4 Subject: [PATCH 529/806] PCI: brcmstb: Add MSI capability
5
6 This commit adds MSI to the Broadcom STB PCIe host controller. It does
7 not add MSIX since that functionality is not in the HW. The MSI
8 controller is physically located within the PCIe block, however, there
9 is no reason why the MSI controller could not be moved elsewhere in
10 the future.
11
12 Since the internal Brcmstb MSI controller is intertwined with the PCIe
13 controller, it is not its own platform device but rather part of the
14 PCIe platform device.
15
16 Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
17 ---
18 drivers/pci/controller/pcie-brcmstb.c | 374 ++++++++++++++++++++++++--
19 1 file changed, 353 insertions(+), 21 deletions(-)
20
21 --- a/drivers/pci/controller/pcie-brcmstb.c
22 +++ b/drivers/pci/controller/pcie-brcmstb.c
23 @@ -1,6 +1,7 @@
24 // SPDX-License-Identifier: GPL-2.0
25 /* Copyright (C) 2009 - 2017 Broadcom */
26
27 +#include <linux/bitops.h>
28 #include <linux/clk.h>
29 #include <linux/compiler.h>
30 #include <linux/delay.h>
31 @@ -9,11 +10,13 @@
32 #include <linux/interrupt.h>
33 #include <linux/io.h>
34 #include <linux/ioport.h>
35 +#include <linux/irqchip/chained_irq.h>
36 #include <linux/irqdomain.h>
37 #include <linux/kernel.h>
38 #include <linux/list.h>
39 #include <linux/log2.h>
40 #include <linux/module.h>
41 +#include <linux/msi.h>
42 #include <linux/of_address.h>
43 #include <linux/of_irq.h>
44 #include <linux/of_pci.h>
45 @@ -47,6 +50,9 @@
46 #define PCIE_MISC_RC_BAR2_CONFIG_LO 0x4034
47 #define PCIE_MISC_RC_BAR2_CONFIG_HI 0x4038
48 #define PCIE_MISC_RC_BAR3_CONFIG_LO 0x403c
49 +#define PCIE_MISC_MSI_BAR_CONFIG_LO 0x4044
50 +#define PCIE_MISC_MSI_BAR_CONFIG_HI 0x4048
51 +#define PCIE_MISC_MSI_DATA_CONFIG 0x404c
52 #define PCIE_MISC_PCIE_CTRL 0x4064
53 #define PCIE_MISC_PCIE_STATUS 0x4068
54 #define PCIE_MISC_REVISION 0x406c
55 @@ -55,6 +61,7 @@
56 #define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI 0x4084
57 #define PCIE_MISC_HARD_PCIE_HARD_DEBUG 0x4204
58 #define PCIE_INTR2_CPU_BASE 0x4300
59 +#define PCIE_MSI_INTR2_BASE 0x4500
60
61 /*
62 * Broadcom Settop Box PCIe Register Field shift and mask info. The
63 @@ -115,6 +122,8 @@
64
65 #define BRCM_NUM_PCIE_OUT_WINS 0x4
66 #define BRCM_MAX_SCB 0x4
67 +#define BRCM_INT_PCI_MSI_NR 32
68 +#define BRCM_PCIE_HW_REV_33 0x0303
69
70 #define BRCM_MSI_TARGET_ADDR_LT_4GB 0x0fffffffcULL
71 #define BRCM_MSI_TARGET_ADDR_GT_4GB 0xffffffffcULL
72 @@ -203,6 +212,33 @@ struct brcm_window {
73 dma_addr_t size;
74 };
75
76 +struct brcm_msi {
77 + struct device *dev;
78 + void __iomem *base;
79 + struct device_node *dn;
80 + struct irq_domain *msi_domain;
81 + struct irq_domain *inner_domain;
82 + struct mutex lock; /* guards the alloc/free operations */
83 + u64 target_addr;
84 + int irq;
85 +
86 + /* intr_base is the base pointer for interrupt status/set/clr regs */
87 + void __iomem *intr_base;
88 +
89 + /* intr_legacy_mask indicates how many bits are MSI interrupts */
90 + u32 intr_legacy_mask;
91 +
92 + /*
93 + * intr_legacy_offset indicates bit position of MSI_01. It is
94 + * to map the register bit position to a hwirq that starts at 0.
95 + */
96 + u32 intr_legacy_offset;
97 +
98 + /* used indicates which MSI interrupts have been alloc'd */
99 + unsigned long used;
100 + unsigned int rev;
101 +};
102 +
103 /* Internal PCIe Host Controller Information.*/
104 struct brcm_pcie {
105 struct device *dev;
106 @@ -217,7 +253,10 @@ struct brcm_pcie {
107 int num_out_wins;
108 bool ssc;
109 int gen;
110 + u64 msi_target_addr;
111 struct brcm_window out_wins[BRCM_NUM_PCIE_OUT_WINS];
112 + struct brcm_msi *msi;
113 + bool msi_internal;
114 unsigned int rev;
115 const int *reg_offsets;
116 const int *reg_field_info;
117 @@ -225,9 +264,9 @@ struct brcm_pcie {
118 };
119
120 struct pcie_cfg_data {
121 - const int *reg_field_info;
122 - const int *offsets;
123 - const enum pcie_type type;
124 + const int *reg_field_info;
125 + const int *offsets;
126 + const enum pcie_type type;
127 };
128
129 static const int pcie_reg_field_info[] = {
130 @@ -828,6 +867,267 @@ static void brcm_pcie_set_outbound_win(s
131 }
132 }
133
134 +static struct irq_chip brcm_msi_irq_chip = {
135 + .name = "Brcm_MSI",
136 + .irq_mask = pci_msi_mask_irq,
137 + .irq_unmask = pci_msi_unmask_irq,
138 +};
139 +
140 +static struct msi_domain_info brcm_msi_domain_info = {
141 + .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
142 + MSI_FLAG_PCI_MSIX),
143 + .chip = &brcm_msi_irq_chip,
144 +};
145 +
146 +static void brcm_pcie_msi_isr(struct irq_desc *desc)
147 +{
148 + struct irq_chip *chip = irq_desc_get_chip(desc);
149 + struct brcm_msi *msi;
150 + unsigned long status, virq;
151 + u32 mask, bit, hwirq;
152 + struct device *dev;
153 +
154 + chained_irq_enter(chip, desc);
155 + msi = irq_desc_get_handler_data(desc);
156 + mask = msi->intr_legacy_mask;
157 + dev = msi->dev;
158 +
159 + while ((status = bcm_readl(msi->intr_base + STATUS) & mask)) {
160 + for_each_set_bit(bit, &status, BRCM_INT_PCI_MSI_NR) {
161 + /* clear the interrupt */
162 + bcm_writel(1 << bit, msi->intr_base + CLR);
163 +
164 + /* Account for legacy interrupt offset */
165 + hwirq = bit - msi->intr_legacy_offset;
166 +
167 + virq = irq_find_mapping(msi->inner_domain, hwirq);
168 + if (virq) {
169 + if (msi->used & (1 << hwirq))
170 + generic_handle_irq(virq);
171 + else
172 + dev_info(dev, "unhandled MSI %d\n",
173 + hwirq);
174 + } else {
175 + /* Unknown MSI, just clear it */
176 + dev_dbg(dev, "unexpected MSI\n");
177 + }
178 + }
179 + }
180 + chained_irq_exit(chip, desc);
181 +}
182 +
183 +static void brcm_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
184 +{
185 + struct brcm_msi *msi = irq_data_get_irq_chip_data(data);
186 + u32 temp;
187 +
188 + msg->address_lo = lower_32_bits(msi->target_addr);
189 + msg->address_hi = upper_32_bits(msi->target_addr);
190 + temp = bcm_readl(msi->base + PCIE_MISC_MSI_DATA_CONFIG);
191 + msg->data = ((temp >> 16) & (temp & 0xffff)) | data->hwirq;
192 +}
193 +
194 +static int brcm_msi_set_affinity(struct irq_data *irq_data,
195 + const struct cpumask *mask, bool force)
196 +{
197 + return -EINVAL;
198 +}
199 +
200 +static struct irq_chip brcm_msi_bottom_irq_chip = {
201 + .name = "Brcm_MSI",
202 + .irq_compose_msi_msg = brcm_compose_msi_msg,
203 + .irq_set_affinity = brcm_msi_set_affinity,
204 +};
205 +
206 +static int brcm_msi_alloc(struct brcm_msi *msi)
207 +{
208 + int bit, hwirq;
209 +
210 + mutex_lock(&msi->lock);
211 + bit = ~msi->used ? ffz(msi->used) : -1;
212 +
213 + if (bit >= 0 && bit < BRCM_INT_PCI_MSI_NR) {
214 + msi->used |= (1 << bit);
215 + hwirq = bit - msi->intr_legacy_offset;
216 + } else {
217 + hwirq = -ENOSPC;
218 + }
219 +
220 + mutex_unlock(&msi->lock);
221 + return hwirq;
222 +}
223 +
224 +static void brcm_msi_free(struct brcm_msi *msi, unsigned long hwirq)
225 +{
226 + mutex_lock(&msi->lock);
227 + msi->used &= ~(1 << (hwirq + msi->intr_legacy_offset));
228 + mutex_unlock(&msi->lock);
229 +}
230 +
231 +static int brcm_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
232 + unsigned int nr_irqs, void *args)
233 +{
234 + struct brcm_msi *msi = domain->host_data;
235 + int hwirq;
236 +
237 + hwirq = brcm_msi_alloc(msi);
238 +
239 + if (hwirq < 0)
240 + return hwirq;
241 +
242 + irq_domain_set_info(domain, virq, (irq_hw_number_t)hwirq,
243 + &brcm_msi_bottom_irq_chip, domain->host_data,
244 + handle_simple_irq, NULL, NULL);
245 + return 0;
246 +}
247 +
248 +static void brcm_irq_domain_free(struct irq_domain *domain,
249 + unsigned int virq, unsigned int nr_irqs)
250 +{
251 + struct irq_data *d = irq_domain_get_irq_data(domain, virq);
252 + struct brcm_msi *msi = irq_data_get_irq_chip_data(d);
253 +
254 + brcm_msi_free(msi, d->hwirq);
255 +}
256 +
257 +static void brcm_msi_set_regs(struct brcm_msi *msi)
258 +{
259 + u32 data_val, msi_lo, msi_hi;
260 +
261 + if (msi->rev >= BRCM_PCIE_HW_REV_33) {
262 + /*
263 + * ffe0 -- least sig 5 bits are 0 indicating 32 msgs
264 + * 6540 -- this is our arbitrary unique data value
265 + */
266 + data_val = 0xffe06540;
267 + } else {
268 + /*
269 + * fff8 -- least sig 3 bits are 0 indicating 8 msgs
270 + * 6540 -- this is our arbitrary unique data value
271 + */
272 + data_val = 0xfff86540;
273 + }
274 +
275 + /*
276 + * Make sure we are not masking MSIs. Note that MSIs can be masked,
277 + * but that occurs on the PCIe EP device
278 + */
279 + bcm_writel(0xffffffff & msi->intr_legacy_mask,
280 + msi->intr_base + MASK_CLR);
281 +
282 + msi_lo = lower_32_bits(msi->target_addr);
283 + msi_hi = upper_32_bits(msi->target_addr);
284 + /*
285 + * The 0 bit of PCIE_MISC_MSI_BAR_CONFIG_LO is repurposed to MSI
286 + * enable, which we set to 1.
287 + */
288 + bcm_writel(msi_lo | 1, msi->base + PCIE_MISC_MSI_BAR_CONFIG_LO);
289 + bcm_writel(msi_hi, msi->base + PCIE_MISC_MSI_BAR_CONFIG_HI);
290 + bcm_writel(data_val, msi->base + PCIE_MISC_MSI_DATA_CONFIG);
291 +}
292 +
293 +static const struct irq_domain_ops msi_domain_ops = {
294 + .alloc = brcm_irq_domain_alloc,
295 + .free = brcm_irq_domain_free,
296 +};
297 +
298 +static int brcm_allocate_domains(struct brcm_msi *msi)
299 +{
300 + struct fwnode_handle *fwnode = of_node_to_fwnode(msi->dn);
301 + struct device *dev = msi->dev;
302 +
303 + msi->inner_domain = irq_domain_add_linear(NULL, BRCM_INT_PCI_MSI_NR,
304 + &msi_domain_ops, msi);
305 + if (!msi->inner_domain) {
306 + dev_err(dev, "failed to create IRQ domain\n");
307 + return -ENOMEM;
308 + }
309 +
310 + msi->msi_domain = pci_msi_create_irq_domain(fwnode,
311 + &brcm_msi_domain_info,
312 + msi->inner_domain);
313 + if (!msi->msi_domain) {
314 + dev_err(dev, "failed to create MSI domain\n");
315 + irq_domain_remove(msi->inner_domain);
316 + return -ENOMEM;
317 + }
318 +
319 + return 0;
320 +}
321 +
322 +static void brcm_free_domains(struct brcm_msi *msi)
323 +{
324 + irq_domain_remove(msi->msi_domain);
325 + irq_domain_remove(msi->inner_domain);
326 +}
327 +
328 +static void brcm_msi_remove(struct brcm_pcie *pcie)
329 +{
330 + struct brcm_msi *msi = pcie->msi;
331 +
332 + if (!msi)
333 + return;
334 + irq_set_chained_handler(msi->irq, NULL);
335 + irq_set_handler_data(msi->irq, NULL);
336 + brcm_free_domains(msi);
337 +}
338 +
339 +static int brcm_pcie_enable_msi(struct brcm_pcie *pcie)
340 +{
341 + struct brcm_msi *msi;
342 + int irq, ret;
343 + struct device *dev = pcie->dev;
344 +
345 + irq = irq_of_parse_and_map(dev->of_node, 1);
346 + if (irq <= 0) {
347 + dev_err(dev, "cannot map msi intr\n");
348 + return -ENODEV;
349 + }
350 +
351 + msi = devm_kzalloc(dev, sizeof(struct brcm_msi), GFP_KERNEL);
352 + if (!msi)
353 + return -ENOMEM;
354 +
355 + msi->dev = dev;
356 + msi->base = pcie->base;
357 + msi->rev = pcie->rev;
358 + msi->dn = pcie->dn;
359 + msi->target_addr = pcie->msi_target_addr;
360 + msi->irq = irq;
361 +
362 + ret = brcm_allocate_domains(msi);
363 + if (ret)
364 + return ret;
365 +
366 + irq_set_chained_handler_and_data(msi->irq, brcm_pcie_msi_isr, msi);
367 +
368 + if (msi->rev >= BRCM_PCIE_HW_REV_33) {
369 + msi->intr_base = msi->base + PCIE_MSI_INTR2_BASE;
370 + /*
371 + * This version of PCIe hw has only 32 intr bits
372 + * starting at bit position 0.
373 + */
374 + msi->intr_legacy_mask = 0xffffffff;
375 + msi->intr_legacy_offset = 0x0;
376 + msi->used = 0x0;
377 +
378 + } else {
379 + msi->intr_base = msi->base + PCIE_INTR2_CPU_BASE;
380 + /*
381 + * This version of PCIe hw has only 8 intr bits starting
382 + * at bit position 24.
383 + */
384 + msi->intr_legacy_mask = 0xff000000;
385 + msi->intr_legacy_offset = 24;
386 + msi->used = 0x00ffffff;
387 + }
388 +
389 + brcm_msi_set_regs(msi);
390 + pcie->msi = msi;
391 +
392 + return 0;
393 +}
394 +
395 /* Configuration space read/write support */
396 static int cfg_index(int busnr, int devfn, int reg)
397 {
398 @@ -1072,6 +1372,7 @@ static int brcm_pcie_setup(struct brcm_p
399 u16 nlw, cls, lnksta;
400 bool ssc_good = false;
401 struct device *dev = pcie->dev;
402 + u64 msi_target_addr;
403
404 /* Reset the bridge */
405 brcm_pcie_bridge_sw_init_set(pcie, 1);
406 @@ -1116,27 +1417,24 @@ static int brcm_pcie_setup(struct brcm_p
407 * The PCIe host controller by design must set the inbound
408 * viewport to be a contiguous arrangement of all of the
409 * system's memory. In addition, its size mut be a power of
410 - * two. To further complicate matters, the viewport must
411 - * start on a pcie-address that is aligned on a multiple of its
412 - * size. If a portion of the viewport does not represent
413 - * system memory -- e.g. 3GB of memory requires a 4GB viewport
414 - * -- we can map the outbound memory in or after 3GB and even
415 - * though the viewport will overlap the outbound memory the
416 - * controller will know to send outbound memory downstream and
417 - * everything else upstream.
418 + * two. Further, the MSI target address must NOT be placed
419 + * inside this region, as the decoding logic will consider its
420 + * address to be inbound memory traffic. To further
421 + * complicate matters, the viewport must start on a
422 + * pcie-address that is aligned on a multiple of its size.
423 + * If a portion of the viewport does not represent system
424 + * memory -- e.g. 3GB of memory requires a 4GB viewport --
425 + * we can map the outbound memory in or after 3GB and even
426 + * though the viewport will overlap the outbound memory
427 + * the controller will know to send outbound memory downstream
428 + * and everything else upstream.
429 */
430 rc_bar2_size = roundup_pow_of_two_64(total_mem_size);
431
432 - /*
433 - * Set simple configuration based on memory sizes
434 - * only. We always start the viewport at address 0.
435 - */
436 - rc_bar2_offset = 0;
437 -
438 if (dma_ranges) {
439 /*
440 * The best-case scenario is to place the inbound
441 - * region in the first 4GB of pci-space, as some
442 + * region in the first 4GB of pcie-space, as some
443 * legacy devices can only address 32bits.
444 * We would also like to put the MSI under 4GB
445 * as well, since some devices require a 32bit
446 @@ -1145,6 +1443,14 @@ static int brcm_pcie_setup(struct brcm_p
447 if (total_mem_size <= 0xc0000000ULL &&
448 rc_bar2_size <= 0x100000000ULL) {
449 rc_bar2_offset = 0;
450 + /* If the viewport is less then 4GB we can fit
451 + * the MSI target address under 4GB. Otherwise
452 + * put it right below 64GB.
453 + */
454 + msi_target_addr =
455 + (rc_bar2_size == 0x100000000ULL)
456 + ? BRCM_MSI_TARGET_ADDR_GT_4GB
457 + : BRCM_MSI_TARGET_ADDR_LT_4GB;
458 } else {
459 /*
460 * The system memory is 4GB or larger so we
461 @@ -1154,8 +1460,12 @@ static int brcm_pcie_setup(struct brcm_p
462 * start it at the 1x multiple of its size
463 */
464 rc_bar2_offset = rc_bar2_size;
465 - }
466
467 + /* Since we are starting the viewport at 4GB or
468 + * higher, put the MSI target address below 4GB
469 + */
470 + msi_target_addr = BRCM_MSI_TARGET_ADDR_LT_4GB;
471 + }
472 } else {
473 /*
474 * Set simple configuration based on memory sizes
475 @@ -1163,7 +1473,12 @@ static int brcm_pcie_setup(struct brcm_p
476 * and set the MSI target address accordingly.
477 */
478 rc_bar2_offset = 0;
479 +
480 + msi_target_addr = (rc_bar2_size >= 0x100000000ULL)
481 + ? BRCM_MSI_TARGET_ADDR_GT_4GB
482 + : BRCM_MSI_TARGET_ADDR_LT_4GB;
483 }
484 + pcie->msi_target_addr = msi_target_addr;
485
486 tmp = lower_32_bits(rc_bar2_offset);
487 tmp = INSERT_FIELD(tmp, PCIE_MISC_RC_BAR2_CONFIG_LO, SIZE,
488 @@ -1333,6 +1648,9 @@ static int brcm_pcie_resume(struct devic
489 if (ret)
490 return ret;
491
492 + if (pcie->msi && pcie->msi_internal)
493 + brcm_msi_set_regs(pcie->msi);
494 +
495 pcie->suspended = false;
496
497 return 0;
498 @@ -1340,6 +1658,7 @@ static int brcm_pcie_resume(struct devic
499
500 static void _brcm_pcie_remove(struct brcm_pcie *pcie)
501 {
502 + brcm_msi_remove(pcie);
503 turn_off(pcie);
504 clk_disable_unprepare(pcie->clk);
505 clk_put(pcie->clk);
506 @@ -1368,7 +1687,7 @@ MODULE_DEVICE_TABLE(of, brcm_pcie_match)
507
508 static int brcm_pcie_probe(struct platform_device *pdev)
509 {
510 - struct device_node *dn = pdev->dev.of_node;
511 + struct device_node *dn = pdev->dev.of_node, *msi_dn;
512 const struct of_device_id *of_id;
513 const struct pcie_cfg_data *data;
514 int ret;
515 @@ -1448,6 +1767,20 @@ static int brcm_pcie_probe(struct platfo
516 if (ret)
517 goto fail;
518
519 + msi_dn = of_parse_phandle(pcie->dn, "msi-parent", 0);
520 + /* Use the internal MSI if no msi-parent property */
521 + if (!msi_dn)
522 + msi_dn = pcie->dn;
523 +
524 + if (pci_msi_enabled() && msi_dn == pcie->dn) {
525 + ret = brcm_pcie_enable_msi(pcie);
526 + if (ret)
527 + dev_err(pcie->dev,
528 + "probe of internal MSI failed: %d)", ret);
529 + else
530 + pcie->msi_internal = true;
531 + }
532 +
533 list_splice_init(&pcie->resources, &bridge->windows);
534 bridge->dev.parent = &pdev->dev;
535 bridge->busnr = 0;
536 @@ -1470,7 +1803,6 @@ static int brcm_pcie_probe(struct platfo
537 pcie->root_bus = bridge->bus;
538
539 return 0;
540 -
541 fail:
542 _brcm_pcie_remove(pcie);
543 return ret;