1a3fc56b1SAlejandro Lucero // SPDX-License-Identifier: GPL-2.0-only
2a3fc56b1SAlejandro Lucero /****************************************************************************
3a3fc56b1SAlejandro Lucero *
4a3fc56b1SAlejandro Lucero * Driver for AMD network controllers and boards
5a3fc56b1SAlejandro Lucero * Copyright (C) 2025, Advanced Micro Devices, Inc.
6a3fc56b1SAlejandro Lucero */
7a3fc56b1SAlejandro Lucero
8a3fc56b1SAlejandro Lucero #include <linux/pci.h>
9a3fc56b1SAlejandro Lucero
1008699796SAlejandro Lucero #include <cxl/cxl.h>
1108699796SAlejandro Lucero #include <cxl/pci.h>
12a3fc56b1SAlejandro Lucero #include "net_driver.h"
13a3fc56b1SAlejandro Lucero #include "efx_cxl.h"
14a3fc56b1SAlejandro Lucero
15a3fc56b1SAlejandro Lucero #define EFX_CTPIO_BUFFER_SIZE SZ_256M
16a3fc56b1SAlejandro Lucero
efx_cxl_init(struct efx_probe_data * probe_data)17a3fc56b1SAlejandro Lucero int efx_cxl_init(struct efx_probe_data *probe_data)
18a3fc56b1SAlejandro Lucero {
19a3fc56b1SAlejandro Lucero struct efx_nic *efx = &probe_data->efx;
20a3fc56b1SAlejandro Lucero struct pci_dev *pci_dev = efx->pci_dev;
210418860eSAlejandro Lucero struct range cxl_pio_range;
22a3fc56b1SAlejandro Lucero struct efx_cxl *cxl;
23a3fc56b1SAlejandro Lucero u16 dvsec;
2408699796SAlejandro Lucero int rc;
25a3fc56b1SAlejandro Lucero
26a3fc56b1SAlejandro Lucero /* Is the device configured with and using CXL? */
27a3fc56b1SAlejandro Lucero if (!pcie_is_cxl(pci_dev))
28a3fc56b1SAlejandro Lucero return 0;
29a3fc56b1SAlejandro Lucero
30a3fc56b1SAlejandro Lucero dvsec = pci_find_dvsec_capability(pci_dev, PCI_VENDOR_ID_CXL,
31a3fc56b1SAlejandro Lucero PCI_DVSEC_CXL_DEVICE);
32a3fc56b1SAlejandro Lucero if (!dvsec) {
33a3fc56b1SAlejandro Lucero pci_info(pci_dev, "CXL_DVSEC_PCIE_DEVICE capability not found\n");
34a3fc56b1SAlejandro Lucero return 0;
35a3fc56b1SAlejandro Lucero }
36a3fc56b1SAlejandro Lucero
37a3fc56b1SAlejandro Lucero pci_dbg(pci_dev, "CXL_DVSEC_PCIE_DEVICE capability found\n");
38a3fc56b1SAlejandro Lucero
39a3fc56b1SAlejandro Lucero /* Create a cxl_dev_state embedded in the cxl struct using cxl core api
40a3fc56b1SAlejandro Lucero * specifying no mbox available.
41a3fc56b1SAlejandro Lucero */
42a3fc56b1SAlejandro Lucero cxl = devm_cxl_dev_state_create(&pci_dev->dev, CXL_DEVTYPE_DEVMEM,
43a3fc56b1SAlejandro Lucero pci_get_dsn(pci_dev), dvsec,
44a3fc56b1SAlejandro Lucero struct efx_cxl, cxlds, false);
45a3fc56b1SAlejandro Lucero
46a3fc56b1SAlejandro Lucero if (!cxl)
47a3fc56b1SAlejandro Lucero return -ENOMEM;
48a3fc56b1SAlejandro Lucero
4908699796SAlejandro Lucero rc = cxl_pci_setup_regs(pci_dev, CXL_REGLOC_RBI_COMPONENT,
5008699796SAlejandro Lucero &cxl->cxlds.reg_map);
5108699796SAlejandro Lucero if (rc) {
5208699796SAlejandro Lucero pci_err(pci_dev, "No component registers\n");
5308699796SAlejandro Lucero return rc;
5408699796SAlejandro Lucero }
5508699796SAlejandro Lucero
5608699796SAlejandro Lucero if (!cxl->cxlds.reg_map.component_map.hdm_decoder.valid) {
5708699796SAlejandro Lucero pci_err(pci_dev, "Expected HDM component register not found\n");
5808699796SAlejandro Lucero return -ENODEV;
5908699796SAlejandro Lucero }
6008699796SAlejandro Lucero
6108699796SAlejandro Lucero if (!cxl->cxlds.reg_map.component_map.ras.valid) {
6208699796SAlejandro Lucero pci_err(pci_dev, "Expected RAS component register not found\n");
6308699796SAlejandro Lucero return -ENODEV;
6408699796SAlejandro Lucero }
6508699796SAlejandro Lucero
6608699796SAlejandro Lucero /* Set media ready explicitly as there are neither mailbox for checking
6708699796SAlejandro Lucero * this state nor the CXL register involved, both not mandatory for
6808699796SAlejandro Lucero * type2.
6908699796SAlejandro Lucero */
7008699796SAlejandro Lucero cxl->cxlds.media_ready = true;
7108699796SAlejandro Lucero
72230284c1SAlejandro Lucero if (cxl_set_capacity(&cxl->cxlds, EFX_CTPIO_BUFFER_SIZE)) {
73230284c1SAlejandro Lucero pci_err(pci_dev, "dpa capacity setup failed\n");
74230284c1SAlejandro Lucero return -ENODEV;
75230284c1SAlejandro Lucero }
76230284c1SAlejandro Lucero
770418860eSAlejandro Lucero cxl->cxlmd = devm_cxl_probe_mem(&cxl->cxlds, &cxl_pio_range);
780418860eSAlejandro Lucero if (IS_ERR(cxl->cxlmd)) {
790418860eSAlejandro Lucero pci_err(pci_dev, "CXL accel memdev creation failed\n");
800418860eSAlejandro Lucero return PTR_ERR(cxl->cxlmd);
810418860eSAlejandro Lucero }
820418860eSAlejandro Lucero
830418860eSAlejandro Lucero cxl->ctpio_cxl = ioremap_wc(cxl_pio_range.start,
840418860eSAlejandro Lucero range_len(&cxl_pio_range));
850418860eSAlejandro Lucero if (!cxl->ctpio_cxl) {
860418860eSAlejandro Lucero pci_err(pci_dev, "CXL ioremap region (%pra) failed\n",
870418860eSAlejandro Lucero &cxl_pio_range);
880418860eSAlejandro Lucero return -ENOMEM;
890418860eSAlejandro Lucero }
900418860eSAlejandro Lucero
91*bd6550bcSAlejandro Lucero probe_data->cxl_pio_initialised = true;
92a3fc56b1SAlejandro Lucero probe_data->cxl = cxl;
93a3fc56b1SAlejandro Lucero
94a3fc56b1SAlejandro Lucero return 0;
95a3fc56b1SAlejandro Lucero }
96a3fc56b1SAlejandro Lucero
efx_cxl_exit(struct efx_probe_data * probe_data)970418860eSAlejandro Lucero void efx_cxl_exit(struct efx_probe_data *probe_data)
980418860eSAlejandro Lucero {
990418860eSAlejandro Lucero if (!probe_data->cxl)
1000418860eSAlejandro Lucero return;
1010418860eSAlejandro Lucero
1020418860eSAlejandro Lucero iounmap(probe_data->cxl->ctpio_cxl);
1030418860eSAlejandro Lucero }
1040418860eSAlejandro Lucero
105a3fc56b1SAlejandro Lucero MODULE_IMPORT_NS("CXL");
106