aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cxl/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cxl/core.c')
-rw-r--r--drivers/cxl/core.c74
1 files changed, 62 insertions, 12 deletions
diff --git a/drivers/cxl/core.c b/drivers/cxl/core.c
index 38979c97158d..f836aaab03e0 100644
--- a/drivers/cxl/core.c
+++ b/drivers/cxl/core.c
@@ -3,6 +3,7 @@
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/device.h>
#include <linux/module.h>
+#include <linux/pci.h>
#include "cxl.h"
/**
@@ -13,18 +14,20 @@
*/
/**
- * cxl_setup_device_regs() - Detect CXL Device register blocks
+ * cxl_probe_device_regs() - Detect CXL Device register blocks
* @dev: Host device of the @base mapping
* @base: Mapping of CXL 2.0 8.2.8 CXL Device Register Interface
- * @regs: Base pointers for device register blocks (see CXL_DEVICE_REGS())
+ * @map: Map object describing the register block information found
+ *
+ * Probe for device register information and return it in map object.
*/
-void cxl_setup_device_regs(struct device *dev, void __iomem *base,
- struct cxl_device_regs *regs)
+void cxl_probe_device_regs(struct device *dev, void __iomem *base,
+ struct cxl_device_reg_map *map)
{
int cap, cap_count;
u64 cap_array;
- *regs = (struct cxl_device_regs) { 0 };
+ *map = (struct cxl_device_reg_map){ 0 };
cap_array = readq(base + CXLDEV_CAP_ARRAY_OFFSET);
if (FIELD_GET(CXLDEV_CAP_ARRAY_ID_MASK, cap_array) !=
@@ -34,30 +37,36 @@ void cxl_setup_device_regs(struct device *dev, void __iomem *base,
cap_count = FIELD_GET(CXLDEV_CAP_ARRAY_COUNT_MASK, cap_array);
for (cap = 1; cap <= cap_count; cap++) {
- void __iomem *register_block;
- u32 offset;
+ u32 offset, length;
u16 cap_id;
cap_id = FIELD_GET(CXLDEV_CAP_HDR_CAP_ID_MASK,
readl(base + cap * 0x10));
offset = readl(base + cap * 0x10 + 0x4);
- register_block = base + offset;
+ length = readl(base + cap * 0x10 + 0x8);
switch (cap_id) {
case CXLDEV_CAP_CAP_ID_DEVICE_STATUS:
dev_dbg(dev, "found Status capability (0x%x)\n", offset);
- regs->status = register_block;
+
+ map->status.valid = true;
+ map->status.offset = offset;
+ map->status.size = length;
break;
case CXLDEV_CAP_CAP_ID_PRIMARY_MAILBOX:
dev_dbg(dev, "found Mailbox capability (0x%x)\n", offset);
- regs->mbox = register_block;
+ map->mbox.valid = true;
+ map->mbox.offset = offset;
+ map->mbox.size = length;
break;
case CXLDEV_CAP_CAP_ID_SECONDARY_MAILBOX:
dev_dbg(dev, "found Secondary Mailbox capability (0x%x)\n", offset);
break;
case CXLDEV_CAP_CAP_ID_MEMDEV:
dev_dbg(dev, "found Memory Device capability (0x%x)\n", offset);
- regs->memdev = register_block;
+ map->memdev.valid = true;
+ map->memdev.offset = offset;
+ map->memdev.size = length;
break;
default:
if (cap_id >= 0x8000)
@@ -68,7 +77,48 @@ void cxl_setup_device_regs(struct device *dev, void __iomem *base,
}
}
}
-EXPORT_SYMBOL_GPL(cxl_setup_device_regs);
+EXPORT_SYMBOL_GPL(cxl_probe_device_regs);
+
+int cxl_map_device_regs(struct pci_dev *pdev,
+ struct cxl_device_regs *regs,
+ struct cxl_register_map *map)
+{
+ struct device *dev = &pdev->dev;
+ resource_size_t phys_addr;
+
+ phys_addr = pci_resource_start(pdev, map->barno);
+ phys_addr += map->block_offset;
+
+ if (map->device_map.status.valid) {
+ resource_size_t addr;
+ resource_size_t length;
+
+ addr = phys_addr + map->device_map.status.offset;
+ length = map->device_map.status.size;
+ regs->status = devm_ioremap(dev, addr, length);
+ }
+
+ if (map->device_map.mbox.valid) {
+ resource_size_t addr;
+ resource_size_t length;
+
+ addr = phys_addr + map->device_map.mbox.offset;
+ length = map->device_map.mbox.size;
+ regs->mbox = devm_ioremap(dev, addr, length);
+ }
+
+ if (map->device_map.memdev.valid) {
+ resource_size_t addr;
+ resource_size_t length;
+
+ addr = phys_addr + map->device_map.memdev.offset;
+ length = map->device_map.memdev.size;
+ regs->memdev = devm_ioremap(dev, addr, length);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cxl_map_device_regs);
struct bus_type cxl_bus_type = {
.name = "cxl",