// SPDX-License-Identifier: GPL-2.0-or-later /* * Support for Digigram AlpX PCI-e boards * * Copyright (c) 2024 Digigram Digital (info@digigram.com) */ #include #include "alpx_xdma.h" #if KERNEL_VERSION(6, 7, 0) > LINUX_VERSION_CODE #include "core/generic/6.3/amd_xdma.h" #include "include/6.3/amd_xdma.h" #else #include #include #endif static struct xdma_chan_info alpx_xdma_chan_info[2] = { [0].dir = DMA_MEM_TO_DEV, [1].dir = DMA_DEV_TO_MEM, }; struct alpx_xdma_platform_data { struct resource resources[2]; struct dma_slave_map map[2]; struct xdma_platdata platdata; }; struct platform_device *alpx_xdma_register(struct pci_dev *pci_dev) { struct alpx_xdma_platform_data *data; struct platform_device *xdma_pdev; int nvectors, vector, ret; data = devm_kzalloc(&pci_dev->dev, sizeof(*data), GFP_KERNEL); if (!data) return NULL; xdma_pdev = platform_device_alloc("xdma", PLATFORM_DEVID_AUTO); if (!xdma_pdev) return NULL; data->resources[0].start = pci_resource_start(pci_dev, 2); data->resources[0].end = pci_resource_end(pci_dev, 2); data->resources[0].flags = IORESOURCE_MEM; nvectors = pci_alloc_irq_vectors(pci_dev, 2, 2, PCI_IRQ_MSIX | PCI_IRQ_MSI | PCI_IRQ_LEGACY); if (nvectors < 0) goto put_pdev; vector = pci_irq_vector(pci_dev, 0); data->resources[1].start = vector; data->resources[1].end = vector + nvectors - 1; data->resources[1].flags = IORESOURCE_IRQ; ret = platform_device_add_resources(xdma_pdev, data->resources, ARRAY_SIZE(data->resources)); if (ret) goto free_irq_vectors; data->map[0].devname = pci_name(pci_dev); data->map[0].slave = "h2c-0"; data->map[0].param = &alpx_xdma_chan_info[0]; data->map[1].devname = pci_name(pci_dev); data->map[1].slave = "c2h-0"; data->map[1].param = &alpx_xdma_chan_info[1]; data->platdata.max_dma_channels = 4; data->platdata.device_map = data->map; data->platdata.device_map_cnt = ARRAY_SIZE(data->map); ret = platform_device_add_data(xdma_pdev, &data->platdata, sizeof(data->platdata)); if (ret) goto free_irq_vectors; xdma_pdev->dev.parent = &pci_dev->dev; ret = platform_device_add(xdma_pdev); if (ret) goto free_irq_vectors; return xdma_pdev; free_irq_vectors: pci_free_irq_vectors(pci_dev); put_pdev: platform_device_put(xdma_pdev); return NULL; } void alpx_xdma_unregister(struct pci_dev *pci_dev, struct platform_device *xdma_pdev) { platform_device_unregister(xdma_pdev); pci_free_irq_vectors(pci_dev); }