xref: /linux/drivers/dma/dw-edma/dw-edma-pcie.c (revision e6f2a617ac53bc0753b885ffb94379ff48b2e2df)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
4  * Synopsys DesignWare eDMA PCIe driver
5  *
6  * Author: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
7  */
8 
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/pci.h>
12 #include <linux/device.h>
13 #include <linux/dma/edma.h>
14 #include <linux/pci-epf.h>
15 #include <linux/msi.h>
16 
17 #include "dw-edma-core.h"
18 
19 struct dw_edma_pcie_data {
20 	/* eDMA registers location */
21 	enum pci_barno			rg_bar;
22 	off_t				rg_off;
23 	size_t				rg_sz;
24 	/* eDMA memory linked list location */
25 	enum pci_barno			ll_bar;
26 	off_t				ll_off;
27 	size_t				ll_sz;
28 	/* eDMA memory data location */
29 	enum pci_barno			dt_bar;
30 	off_t				dt_off;
31 	size_t				dt_sz;
32 	/* Other */
33 	u32				version;
34 	enum dw_edma_mode		mode;
35 	u8				irqs;
36 };
37 
38 static const struct dw_edma_pcie_data snps_edda_data = {
39 	/* eDMA registers location */
40 	.rg_bar				= BAR_0,
41 	.rg_off				= 0x00001000,	/*  4 Kbytes */
42 	.rg_sz				= 0x00002000,	/*  8 Kbytes */
43 	/* eDMA memory linked list location */
44 	.ll_bar				= BAR_2,
45 	.ll_off				= 0x00000000,	/*  0 Kbytes */
46 	.ll_sz				= 0x00800000,	/*  8 Mbytes */
47 	/* eDMA memory data location */
48 	.dt_bar				= BAR_2,
49 	.dt_off				= 0x00800000,	/*  8 Mbytes */
50 	.dt_sz				= 0x03800000,	/* 56 Mbytes */
51 	/* Other */
52 	.version			= 0,
53 	.mode				= EDMA_MODE_UNROLL,
54 	.irqs				= 1,
55 };
56 
57 static int dw_edma_pcie_probe(struct pci_dev *pdev,
58 			      const struct pci_device_id *pid)
59 {
60 	const struct dw_edma_pcie_data *pdata = (void *)pid->driver_data;
61 	struct device *dev = &pdev->dev;
62 	struct dw_edma_chip *chip;
63 	int err, nr_irqs;
64 	struct dw_edma *dw;
65 
66 	/* Enable PCI device */
67 	err = pcim_enable_device(pdev);
68 	if (err) {
69 		pci_err(pdev, "enabling device failed\n");
70 		return err;
71 	}
72 
73 	/* Mapping PCI BAR regions */
74 	err = pcim_iomap_regions(pdev, BIT(pdata->rg_bar) |
75 				       BIT(pdata->ll_bar) |
76 				       BIT(pdata->dt_bar),
77 				 pci_name(pdev));
78 	if (err) {
79 		pci_err(pdev, "eDMA BAR I/O remapping failed\n");
80 		return err;
81 	}
82 
83 	pci_set_master(pdev);
84 
85 	/* DMA configuration */
86 	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
87 	if (!err) {
88 		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
89 		if (err) {
90 			pci_err(pdev, "consistent DMA mask 64 set failed\n");
91 			return err;
92 		}
93 	} else {
94 		pci_err(pdev, "DMA mask 64 set failed\n");
95 
96 		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
97 		if (err) {
98 			pci_err(pdev, "DMA mask 32 set failed\n");
99 			return err;
100 		}
101 
102 		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
103 		if (err) {
104 			pci_err(pdev, "consistent DMA mask 32 set failed\n");
105 			return err;
106 		}
107 	}
108 
109 	/* Data structure allocation */
110 	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
111 	if (!chip)
112 		return -ENOMEM;
113 
114 	dw = devm_kzalloc(dev, sizeof(*dw), GFP_KERNEL);
115 	if (!dw)
116 		return -ENOMEM;
117 
118 	/* IRQs allocation */
119 	nr_irqs = pci_alloc_irq_vectors(pdev, 1, pdata->irqs,
120 					PCI_IRQ_MSI | PCI_IRQ_MSIX);
121 	if (nr_irqs < 1) {
122 		pci_err(pdev, "fail to alloc IRQ vector (number of IRQs=%u)\n",
123 			nr_irqs);
124 		return -EPERM;
125 	}
126 
127 	/* Data structure initialization */
128 	chip->dw = dw;
129 	chip->dev = dev;
130 	chip->id = pdev->devfn;
131 	chip->irq = pdev->irq;
132 
133 	dw->rg_region.vaddr = pcim_iomap_table(pdev)[pdata->rg_bar];
134 	dw->rg_region.vaddr += pdata->rg_off;
135 	dw->rg_region.paddr = pdev->resource[pdata->rg_bar].start;
136 	dw->rg_region.paddr += pdata->rg_off;
137 	dw->rg_region.sz = pdata->rg_sz;
138 
139 	dw->ll_region.vaddr = pcim_iomap_table(pdev)[pdata->ll_bar];
140 	dw->ll_region.vaddr += pdata->ll_off;
141 	dw->ll_region.paddr = pdev->resource[pdata->ll_bar].start;
142 	dw->ll_region.paddr += pdata->ll_off;
143 	dw->ll_region.sz = pdata->ll_sz;
144 
145 	dw->dt_region.vaddr = pcim_iomap_table(pdev)[pdata->dt_bar];
146 	dw->dt_region.vaddr += pdata->dt_off;
147 	dw->dt_region.paddr = pdev->resource[pdata->dt_bar].start;
148 	dw->dt_region.paddr += pdata->dt_off;
149 	dw->dt_region.sz = pdata->dt_sz;
150 
151 	dw->version = pdata->version;
152 	dw->mode = pdata->mode;
153 	dw->nr_irqs = nr_irqs;
154 
155 	/* Debug info */
156 	pci_dbg(pdev, "Version:\t%u\n", dw->version);
157 
158 	pci_dbg(pdev, "Mode:\t%s\n",
159 		dw->mode == EDMA_MODE_LEGACY ? "Legacy" : "Unroll");
160 
161 	pci_dbg(pdev, "Registers:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
162 		pdata->rg_bar, pdata->rg_off, pdata->rg_sz,
163 		dw->rg_region.vaddr, &dw->rg_region.paddr);
164 
165 	pci_dbg(pdev, "L. List:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
166 		pdata->ll_bar, pdata->ll_off, pdata->ll_sz,
167 		dw->ll_region.vaddr, &dw->ll_region.paddr);
168 
169 	pci_dbg(pdev, "Data:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
170 		pdata->dt_bar, pdata->dt_off, pdata->dt_sz,
171 		dw->dt_region.vaddr, &dw->dt_region.paddr);
172 
173 	pci_dbg(pdev, "Nr. IRQs:\t%u\n", dw->nr_irqs);
174 
175 	/* Validating if PCI interrupts were enabled */
176 	if (!pci_dev_msi_enabled(pdev)) {
177 		pci_err(pdev, "enable interrupt failed\n");
178 		return -EPERM;
179 	}
180 
181 	dw->irq = devm_kcalloc(dev, nr_irqs, sizeof(*dw->irq), GFP_KERNEL);
182 	if (!dw->irq)
183 		return -ENOMEM;
184 
185 	/* Starting eDMA driver */
186 	err = dw_edma_probe(chip);
187 	if (err) {
188 		pci_err(pdev, "eDMA probe failed\n");
189 		return err;
190 	}
191 
192 	/* Saving data structure reference */
193 	pci_set_drvdata(pdev, chip);
194 
195 	return 0;
196 }
197 
198 static void dw_edma_pcie_remove(struct pci_dev *pdev)
199 {
200 	struct dw_edma_chip *chip = pci_get_drvdata(pdev);
201 	int err;
202 
203 	/* Stopping eDMA driver */
204 	err = dw_edma_remove(chip);
205 	if (err)
206 		pci_warn(pdev, "can't remove device properly: %d\n", err);
207 
208 	/* Freeing IRQs */
209 	pci_free_irq_vectors(pdev);
210 }
211 
212 static const struct pci_device_id dw_edma_pcie_id_table[] = {
213 	{ PCI_DEVICE_DATA(SYNOPSYS, EDDA, &snps_edda_data) },
214 	{ }
215 };
216 MODULE_DEVICE_TABLE(pci, dw_edma_pcie_id_table);
217 
218 static struct pci_driver dw_edma_pcie_driver = {
219 	.name		= "dw-edma-pcie",
220 	.id_table	= dw_edma_pcie_id_table,
221 	.probe		= dw_edma_pcie_probe,
222 	.remove		= dw_edma_pcie_remove,
223 };
224 
225 module_pci_driver(dw_edma_pcie_driver);
226 
227 MODULE_LICENSE("GPL v2");
228 MODULE_DESCRIPTION("Synopsys DesignWare eDMA PCIe driver");
229 MODULE_AUTHOR("Gustavo Pimentel <gustavo.pimentel@synopsys.com>");
230