xref: /linux/drivers/dma/dw-edma/dw-edma-pcie.c (revision e5a52fd2b8cdb700b3c07b030e050a49ef3156b9)
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_irq_vector(struct device *dev, unsigned int nr)
58 {
59 	return pci_irq_vector(to_pci_dev(dev), nr);
60 }
61 
62 static const struct dw_edma_core_ops dw_edma_pcie_core_ops = {
63 	.irq_vector = dw_edma_pcie_irq_vector,
64 };
65 
66 static int dw_edma_pcie_probe(struct pci_dev *pdev,
67 			      const struct pci_device_id *pid)
68 {
69 	const struct dw_edma_pcie_data *pdata = (void *)pid->driver_data;
70 	struct device *dev = &pdev->dev;
71 	struct dw_edma_chip *chip;
72 	int err, nr_irqs;
73 	struct dw_edma *dw;
74 
75 	/* Enable PCI device */
76 	err = pcim_enable_device(pdev);
77 	if (err) {
78 		pci_err(pdev, "enabling device failed\n");
79 		return err;
80 	}
81 
82 	/* Mapping PCI BAR regions */
83 	err = pcim_iomap_regions(pdev, BIT(pdata->rg_bar) |
84 				       BIT(pdata->ll_bar) |
85 				       BIT(pdata->dt_bar),
86 				 pci_name(pdev));
87 	if (err) {
88 		pci_err(pdev, "eDMA BAR I/O remapping failed\n");
89 		return err;
90 	}
91 
92 	pci_set_master(pdev);
93 
94 	/* DMA configuration */
95 	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
96 	if (!err) {
97 		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
98 		if (err) {
99 			pci_err(pdev, "consistent DMA mask 64 set failed\n");
100 			return err;
101 		}
102 	} else {
103 		pci_err(pdev, "DMA mask 64 set failed\n");
104 
105 		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
106 		if (err) {
107 			pci_err(pdev, "DMA mask 32 set failed\n");
108 			return err;
109 		}
110 
111 		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
112 		if (err) {
113 			pci_err(pdev, "consistent DMA mask 32 set failed\n");
114 			return err;
115 		}
116 	}
117 
118 	/* Data structure allocation */
119 	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
120 	if (!chip)
121 		return -ENOMEM;
122 
123 	dw = devm_kzalloc(dev, sizeof(*dw), GFP_KERNEL);
124 	if (!dw)
125 		return -ENOMEM;
126 
127 	/* IRQs allocation */
128 	nr_irqs = pci_alloc_irq_vectors(pdev, 1, pdata->irqs,
129 					PCI_IRQ_MSI | PCI_IRQ_MSIX);
130 	if (nr_irqs < 1) {
131 		pci_err(pdev, "fail to alloc IRQ vector (number of IRQs=%u)\n",
132 			nr_irqs);
133 		return -EPERM;
134 	}
135 
136 	/* Data structure initialization */
137 	chip->dw = dw;
138 	chip->dev = dev;
139 	chip->id = pdev->devfn;
140 	chip->irq = pdev->irq;
141 
142 	dw->rg_region.vaddr = pcim_iomap_table(pdev)[pdata->rg_bar];
143 	dw->rg_region.vaddr += pdata->rg_off;
144 	dw->rg_region.paddr = pdev->resource[pdata->rg_bar].start;
145 	dw->rg_region.paddr += pdata->rg_off;
146 	dw->rg_region.sz = pdata->rg_sz;
147 
148 	dw->ll_region.vaddr = pcim_iomap_table(pdev)[pdata->ll_bar];
149 	dw->ll_region.vaddr += pdata->ll_off;
150 	dw->ll_region.paddr = pdev->resource[pdata->ll_bar].start;
151 	dw->ll_region.paddr += pdata->ll_off;
152 	dw->ll_region.sz = pdata->ll_sz;
153 
154 	dw->dt_region.vaddr = pcim_iomap_table(pdev)[pdata->dt_bar];
155 	dw->dt_region.vaddr += pdata->dt_off;
156 	dw->dt_region.paddr = pdev->resource[pdata->dt_bar].start;
157 	dw->dt_region.paddr += pdata->dt_off;
158 	dw->dt_region.sz = pdata->dt_sz;
159 
160 	dw->version = pdata->version;
161 	dw->mode = pdata->mode;
162 	dw->nr_irqs = nr_irqs;
163 	dw->ops = &dw_edma_pcie_core_ops;
164 
165 	/* Debug info */
166 	pci_dbg(pdev, "Version:\t%u\n", dw->version);
167 
168 	pci_dbg(pdev, "Mode:\t%s\n",
169 		dw->mode == EDMA_MODE_LEGACY ? "Legacy" : "Unroll");
170 
171 	pci_dbg(pdev, "Registers:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
172 		pdata->rg_bar, pdata->rg_off, pdata->rg_sz,
173 		dw->rg_region.vaddr, &dw->rg_region.paddr);
174 
175 	pci_dbg(pdev, "L. List:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
176 		pdata->ll_bar, pdata->ll_off, pdata->ll_sz,
177 		dw->ll_region.vaddr, &dw->ll_region.paddr);
178 
179 	pci_dbg(pdev, "Data:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
180 		pdata->dt_bar, pdata->dt_off, pdata->dt_sz,
181 		dw->dt_region.vaddr, &dw->dt_region.paddr);
182 
183 	pci_dbg(pdev, "Nr. IRQs:\t%u\n", dw->nr_irqs);
184 
185 	/* Validating if PCI interrupts were enabled */
186 	if (!pci_dev_msi_enabled(pdev)) {
187 		pci_err(pdev, "enable interrupt failed\n");
188 		return -EPERM;
189 	}
190 
191 	dw->irq = devm_kcalloc(dev, nr_irqs, sizeof(*dw->irq), GFP_KERNEL);
192 	if (!dw->irq)
193 		return -ENOMEM;
194 
195 	/* Starting eDMA driver */
196 	err = dw_edma_probe(chip);
197 	if (err) {
198 		pci_err(pdev, "eDMA probe failed\n");
199 		return err;
200 	}
201 
202 	/* Saving data structure reference */
203 	pci_set_drvdata(pdev, chip);
204 
205 	return 0;
206 }
207 
208 static void dw_edma_pcie_remove(struct pci_dev *pdev)
209 {
210 	struct dw_edma_chip *chip = pci_get_drvdata(pdev);
211 	int err;
212 
213 	/* Stopping eDMA driver */
214 	err = dw_edma_remove(chip);
215 	if (err)
216 		pci_warn(pdev, "can't remove device properly: %d\n", err);
217 
218 	/* Freeing IRQs */
219 	pci_free_irq_vectors(pdev);
220 }
221 
222 static const struct pci_device_id dw_edma_pcie_id_table[] = {
223 	{ PCI_DEVICE_DATA(SYNOPSYS, EDDA, &snps_edda_data) },
224 	{ }
225 };
226 MODULE_DEVICE_TABLE(pci, dw_edma_pcie_id_table);
227 
228 static struct pci_driver dw_edma_pcie_driver = {
229 	.name		= "dw-edma-pcie",
230 	.id_table	= dw_edma_pcie_id_table,
231 	.probe		= dw_edma_pcie_probe,
232 	.remove		= dw_edma_pcie_remove,
233 };
234 
235 module_pci_driver(dw_edma_pcie_driver);
236 
237 MODULE_LICENSE("GPL v2");
238 MODULE_DESCRIPTION("Synopsys DesignWare eDMA PCIe driver");
239 MODULE_AUTHOR("Gustavo Pimentel <gustavo.pimentel@synopsys.com>");
240