aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/host/pci-thunder-pem.c56
1 files changed, 54 insertions, 2 deletions
diff --git a/drivers/pci/host/pci-thunder-pem.c b/drivers/pci/host/pci-thunder-pem.c
index 5b88faeebaaa..b89c373555c5 100644
--- a/drivers/pci/host/pci-thunder-pem.c
+++ b/drivers/pci/host/pci-thunder-pem.c
@@ -14,6 +14,7 @@
14 * Copyright (C) 2015 - 2016 Cavium, Inc. 14 * Copyright (C) 2015 - 2016 Cavium, Inc.
15 */ 15 */
16 16
17#include <linux/bitfield.h>
17#include <linux/kernel.h> 18#include <linux/kernel.h>
18#include <linux/init.h> 19#include <linux/init.h>
19#include <linux/of_address.h> 20#include <linux/of_address.h>
@@ -334,6 +335,50 @@ static int thunder_pem_init(struct device *dev, struct pci_config_window *cfg,
334 335
335#if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS) 336#if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)
336 337
338#define PEM_RES_BASE 0x87e0c0000000UL
339#define PEM_NODE_MASK GENMASK(45, 44)
340#define PEM_INDX_MASK GENMASK(26, 24)
341#define PEM_MIN_DOM_IN_NODE 4
342#define PEM_MAX_DOM_IN_NODE 10
343
344static void thunder_pem_reserve_range(struct device *dev, int seg,
345 struct resource *r)
346{
347 resource_size_t start = r->start, end = r->end;
348 struct resource *res;
349 const char *regionid;
350
351 regionid = kasprintf(GFP_KERNEL, "PEM RC:%d", seg);
352 if (!regionid)
353 return;
354
355 res = request_mem_region(start, end - start + 1, regionid);
356 if (res)
357 res->flags &= ~IORESOURCE_BUSY;
358 else
359 kfree(regionid);
360
361 dev_info(dev, "%pR %s reserved\n", r,
362 res ? "has been" : "could not be");
363}
364
365static void thunder_pem_legacy_fw(struct acpi_pci_root *root,
366 struct resource *res_pem)
367{
368 int node = acpi_get_node(root->device->handle);
369 int index;
370
371 if (node == NUMA_NO_NODE)
372 node = 0;
373
374 index = root->segment - PEM_MIN_DOM_IN_NODE;
375 index -= node * PEM_MAX_DOM_IN_NODE;
376 res_pem->start = PEM_RES_BASE | FIELD_PREP(PEM_NODE_MASK, node) |
377 FIELD_PREP(PEM_INDX_MASK, index);
378 res_pem->end = res_pem->start + SZ_16M - 1;
379 res_pem->flags = IORESOURCE_MEM;
380}
381
337static int thunder_pem_acpi_init(struct pci_config_window *cfg) 382static int thunder_pem_acpi_init(struct pci_config_window *cfg)
338{ 383{
339 struct device *dev = cfg->parent; 384 struct device *dev = cfg->parent;
@@ -347,9 +392,16 @@ static int thunder_pem_acpi_init(struct pci_config_window *cfg)
347 return -ENOMEM; 392 return -ENOMEM;
348 393
349 ret = acpi_get_rc_resources(dev, "CAVA02B", root->segment, res_pem); 394 ret = acpi_get_rc_resources(dev, "CAVA02B", root->segment, res_pem);
395
396 /*
397 * If we fail to gather resources it means that we run with old
398 * FW where we need to calculate PEM-specific resources manually.
399 */
350 if (ret) { 400 if (ret) {
351 dev_err(dev, "can't get rc base address\n"); 401 thunder_pem_legacy_fw(root, res_pem);
352 return ret; 402 /* Reserve PEM-specific resources and PCI configuration space */
403 thunder_pem_reserve_range(dev, root->segment, res_pem);
404 thunder_pem_reserve_range(dev, root->segment, &cfg->res);
353 } 405 }
354 406
355 return thunder_pem_init(dev, cfg, res_pem); 407 return thunder_pem_init(dev, cfg, res_pem);