1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Support for Digigram AlpX PCI-e boards
*
* Copyright (c) 2024 Digigram Digital (info@digigram.com)
*/
#include <linux/version.h>
#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 <linux/platform_data/amd_xdma.h>
#include <linux/dma/amd_xdma.h>
#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);
}
|