1792a5b67SPavel Pisa // SPDX-License-Identifier: GPL-2.0-or-later
2792a5b67SPavel Pisa /*******************************************************************************
3792a5b67SPavel Pisa  *
4792a5b67SPavel Pisa  * CTU CAN FD IP Core
5792a5b67SPavel Pisa  *
6792a5b67SPavel Pisa  * Copyright (C) 2015-2018 Ondrej Ille <ondrej.ille@gmail.com> FEE CTU
7792a5b67SPavel Pisa  * Copyright (C) 2018-2021 Ondrej Ille <ondrej.ille@gmail.com> self-funded
8792a5b67SPavel Pisa  * Copyright (C) 2018-2019 Martin Jerabek <martin.jerabek01@gmail.com> FEE CTU
9792a5b67SPavel Pisa  * Copyright (C) 2018-2022 Pavel Pisa <pisa@cmp.felk.cvut.cz> FEE CTU/self-funded
10792a5b67SPavel Pisa  *
11792a5b67SPavel Pisa  * Project advisors:
12792a5b67SPavel Pisa  *     Jiri Novak <jnovak@fel.cvut.cz>
13792a5b67SPavel Pisa  *     Pavel Pisa <pisa@cmp.felk.cvut.cz>
14792a5b67SPavel Pisa  *
15792a5b67SPavel Pisa  * Department of Measurement         (http://meas.fel.cvut.cz/)
16792a5b67SPavel Pisa  * Faculty of Electrical Engineering (http://www.fel.cvut.cz)
17792a5b67SPavel Pisa  * Czech Technical University        (http://www.cvut.cz/)
18792a5b67SPavel Pisa  ******************************************************************************/
19792a5b67SPavel Pisa 
20792a5b67SPavel Pisa #include <linux/module.h>
21792a5b67SPavel Pisa #include <linux/pci.h>
22792a5b67SPavel Pisa 
23792a5b67SPavel Pisa #include "ctucanfd.h"
24792a5b67SPavel Pisa 
25792a5b67SPavel Pisa #ifndef PCI_DEVICE_DATA
26792a5b67SPavel Pisa #define PCI_DEVICE_DATA(vend, dev, data) \
27792a5b67SPavel Pisa .vendor = PCI_VENDOR_ID_##vend, \
28792a5b67SPavel Pisa .device = PCI_DEVICE_ID_##vend##_##dev, \
29792a5b67SPavel Pisa .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, 0, 0, \
30792a5b67SPavel Pisa .driver_data = (kernel_ulong_t)(data)
31792a5b67SPavel Pisa #endif
32792a5b67SPavel Pisa 
33792a5b67SPavel Pisa #ifndef PCI_VENDOR_ID_TEDIA
34792a5b67SPavel Pisa #define PCI_VENDOR_ID_TEDIA 0x1760
35792a5b67SPavel Pisa #endif
36792a5b67SPavel Pisa 
37792a5b67SPavel Pisa #ifndef PCI_DEVICE_ID_TEDIA_CTUCAN_VER21
38792a5b67SPavel Pisa #define PCI_DEVICE_ID_TEDIA_CTUCAN_VER21 0xff00
39792a5b67SPavel Pisa #endif
40792a5b67SPavel Pisa 
41792a5b67SPavel Pisa #define CTUCAN_BAR0_CTUCAN_ID 0x0000
42792a5b67SPavel Pisa #define CTUCAN_BAR0_CRA_BASE  0x4000
43792a5b67SPavel Pisa #define CYCLONE_IV_CRA_A2P_IE (0x0050)
44792a5b67SPavel Pisa 
45792a5b67SPavel Pisa #define CTUCAN_WITHOUT_CTUCAN_ID  0
46792a5b67SPavel Pisa #define CTUCAN_WITH_CTUCAN_ID     1
47792a5b67SPavel Pisa 
48792a5b67SPavel Pisa struct ctucan_pci_board_data {
49792a5b67SPavel Pisa 	void __iomem *bar0_base;
50792a5b67SPavel Pisa 	void __iomem *cra_base;
51792a5b67SPavel Pisa 	void __iomem *bar1_base;
52792a5b67SPavel Pisa 	struct list_head ndev_list_head;
53792a5b67SPavel Pisa 	int use_msi;
54792a5b67SPavel Pisa };
55792a5b67SPavel Pisa 
ctucan_pci_get_bdata(struct pci_dev * pdev)56792a5b67SPavel Pisa static struct ctucan_pci_board_data *ctucan_pci_get_bdata(struct pci_dev *pdev)
57792a5b67SPavel Pisa {
58792a5b67SPavel Pisa 	return (struct ctucan_pci_board_data *)pci_get_drvdata(pdev);
59792a5b67SPavel Pisa }
60792a5b67SPavel Pisa 
ctucan_pci_set_drvdata(struct device * dev,struct net_device * ndev)61792a5b67SPavel Pisa static void ctucan_pci_set_drvdata(struct device *dev,
62792a5b67SPavel Pisa 				   struct net_device *ndev)
63792a5b67SPavel Pisa {
64792a5b67SPavel Pisa 	struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
65792a5b67SPavel Pisa 	struct ctucan_priv *priv = netdev_priv(ndev);
66792a5b67SPavel Pisa 	struct ctucan_pci_board_data *bdata = ctucan_pci_get_bdata(pdev);
67792a5b67SPavel Pisa 
68792a5b67SPavel Pisa 	list_add(&priv->peers_on_pdev, &bdata->ndev_list_head);
69792a5b67SPavel Pisa 	priv->irq_flags = IRQF_SHARED;
70792a5b67SPavel Pisa }
71792a5b67SPavel Pisa 
72792a5b67SPavel Pisa /**
73792a5b67SPavel Pisa  * ctucan_pci_probe - PCI registration call
74792a5b67SPavel Pisa  * @pdev:	Handle to the pci device structure
75792a5b67SPavel Pisa  * @ent:	Pointer to the entry from ctucan_pci_tbl
76792a5b67SPavel Pisa  *
77792a5b67SPavel Pisa  * This function does all the memory allocation and registration for the CAN
78792a5b67SPavel Pisa  * device.
79792a5b67SPavel Pisa  *
80792a5b67SPavel Pisa  * Return: 0 on success and failure value on error
81792a5b67SPavel Pisa  */
ctucan_pci_probe(struct pci_dev * pdev,const struct pci_device_id * ent)82792a5b67SPavel Pisa static int ctucan_pci_probe(struct pci_dev *pdev,
83792a5b67SPavel Pisa 			    const struct pci_device_id *ent)
84792a5b67SPavel Pisa {
85792a5b67SPavel Pisa 	struct device	*dev = &pdev->dev;
86792a5b67SPavel Pisa 	unsigned long driver_data = ent->driver_data;
87792a5b67SPavel Pisa 	struct ctucan_pci_board_data *bdata;
88792a5b67SPavel Pisa 	void __iomem *addr;
89792a5b67SPavel Pisa 	void __iomem *cra_addr;
90792a5b67SPavel Pisa 	void __iomem *bar0_base;
91792a5b67SPavel Pisa 	u32 cra_a2p_ie;
92792a5b67SPavel Pisa 	u32 ctucan_id = 0;
93792a5b67SPavel Pisa 	int ret;
94792a5b67SPavel Pisa 	unsigned int ntxbufs;
95792a5b67SPavel Pisa 	unsigned int num_cores = 1;
96792a5b67SPavel Pisa 	unsigned int core_i = 0;
97792a5b67SPavel Pisa 	int irq;
98792a5b67SPavel Pisa 	int msi_ok = 0;
99792a5b67SPavel Pisa 
100792a5b67SPavel Pisa 	ret = pci_enable_device(pdev);
101792a5b67SPavel Pisa 	if (ret) {
102792a5b67SPavel Pisa 		dev_err(dev, "pci_enable_device FAILED\n");
103792a5b67SPavel Pisa 		goto err;
104792a5b67SPavel Pisa 	}
105792a5b67SPavel Pisa 
106792a5b67SPavel Pisa 	ret = pci_request_regions(pdev, KBUILD_MODNAME);
107792a5b67SPavel Pisa 	if (ret) {
108792a5b67SPavel Pisa 		dev_err(dev, "pci_request_regions FAILED\n");
109792a5b67SPavel Pisa 		goto err_disable_device;
110792a5b67SPavel Pisa 	}
111792a5b67SPavel Pisa 
112792a5b67SPavel Pisa 	ret = pci_enable_msi(pdev);
113792a5b67SPavel Pisa 	if (!ret) {
114792a5b67SPavel Pisa 		dev_info(dev, "MSI enabled\n");
115792a5b67SPavel Pisa 		pci_set_master(pdev);
116792a5b67SPavel Pisa 		msi_ok = 1;
117792a5b67SPavel Pisa 	}
118792a5b67SPavel Pisa 
119792a5b67SPavel Pisa 	dev_info(dev, "ctucan BAR0 0x%08llx 0x%08llx\n",
120792a5b67SPavel Pisa 		 (long long)pci_resource_start(pdev, 0),
121792a5b67SPavel Pisa 		 (long long)pci_resource_len(pdev, 0));
122792a5b67SPavel Pisa 
123792a5b67SPavel Pisa 	dev_info(dev, "ctucan BAR1 0x%08llx 0x%08llx\n",
124792a5b67SPavel Pisa 		 (long long)pci_resource_start(pdev, 1),
125792a5b67SPavel Pisa 		 (long long)pci_resource_len(pdev, 1));
126792a5b67SPavel Pisa 
127792a5b67SPavel Pisa 	addr = pci_iomap(pdev, 1, pci_resource_len(pdev, 1));
128792a5b67SPavel Pisa 	if (!addr) {
129792a5b67SPavel Pisa 		dev_err(dev, "PCI BAR 1 cannot be mapped\n");
130792a5b67SPavel Pisa 		ret = -ENOMEM;
131792a5b67SPavel Pisa 		goto err_release_regions;
132792a5b67SPavel Pisa 	}
133792a5b67SPavel Pisa 
134792a5b67SPavel Pisa 	/* Cyclone IV PCI Express Control Registers Area */
135792a5b67SPavel Pisa 	bar0_base = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
136792a5b67SPavel Pisa 	if (!bar0_base) {
137792a5b67SPavel Pisa 		dev_err(dev, "PCI BAR 0 cannot be mapped\n");
138792a5b67SPavel Pisa 		ret = -EIO;
139792a5b67SPavel Pisa 		goto err_pci_iounmap_bar1;
140792a5b67SPavel Pisa 	}
141792a5b67SPavel Pisa 
142792a5b67SPavel Pisa 	if (driver_data == CTUCAN_WITHOUT_CTUCAN_ID) {
143792a5b67SPavel Pisa 		cra_addr = bar0_base;
144792a5b67SPavel Pisa 		num_cores = 2;
145792a5b67SPavel Pisa 	} else {
146792a5b67SPavel Pisa 		cra_addr = bar0_base + CTUCAN_BAR0_CRA_BASE;
147792a5b67SPavel Pisa 		ctucan_id = ioread32(bar0_base + CTUCAN_BAR0_CTUCAN_ID);
148792a5b67SPavel Pisa 		dev_info(dev, "ctucan_id 0x%08lx\n", (unsigned long)ctucan_id);
149792a5b67SPavel Pisa 		num_cores = ctucan_id & 0xf;
150792a5b67SPavel Pisa 	}
151792a5b67SPavel Pisa 
152792a5b67SPavel Pisa 	irq = pdev->irq;
153792a5b67SPavel Pisa 
154792a5b67SPavel Pisa 	ntxbufs = 4;
155792a5b67SPavel Pisa 
156792a5b67SPavel Pisa 	bdata = kzalloc(sizeof(*bdata), GFP_KERNEL);
157792a5b67SPavel Pisa 	if (!bdata) {
158792a5b67SPavel Pisa 		ret = -ENOMEM;
159792a5b67SPavel Pisa 		goto err_pci_iounmap_bar0;
160792a5b67SPavel Pisa 	}
161792a5b67SPavel Pisa 
162792a5b67SPavel Pisa 	INIT_LIST_HEAD(&bdata->ndev_list_head);
163792a5b67SPavel Pisa 	bdata->bar0_base = bar0_base;
164792a5b67SPavel Pisa 	bdata->cra_base = cra_addr;
165792a5b67SPavel Pisa 	bdata->bar1_base = addr;
166792a5b67SPavel Pisa 	bdata->use_msi = msi_ok;
167792a5b67SPavel Pisa 
168792a5b67SPavel Pisa 	pci_set_drvdata(pdev, bdata);
169792a5b67SPavel Pisa 
170792a5b67SPavel Pisa 	ret = ctucan_probe_common(dev, addr, irq, ntxbufs, 100000000,
171792a5b67SPavel Pisa 				  0, ctucan_pci_set_drvdata);
172792a5b67SPavel Pisa 	if (ret < 0)
173792a5b67SPavel Pisa 		goto err_free_board;
174792a5b67SPavel Pisa 
175792a5b67SPavel Pisa 	core_i++;
176792a5b67SPavel Pisa 
17728b250e0SPavel Pisa 	while (core_i < num_cores) {
178792a5b67SPavel Pisa 		addr += 0x4000;
179792a5b67SPavel Pisa 		ret = ctucan_probe_common(dev, addr, irq, ntxbufs, 100000000,
180792a5b67SPavel Pisa 					  0, ctucan_pci_set_drvdata);
181792a5b67SPavel Pisa 		if (ret < 0) {
182792a5b67SPavel Pisa 			dev_info(dev, "CTU CAN FD core %d initialization failed\n",
183792a5b67SPavel Pisa 				 core_i);
184792a5b67SPavel Pisa 			break;
185792a5b67SPavel Pisa 		}
186792a5b67SPavel Pisa 		core_i++;
187792a5b67SPavel Pisa 	}
188792a5b67SPavel Pisa 
189792a5b67SPavel Pisa 	/* enable interrupt in
190792a5b67SPavel Pisa 	 * Avalon-MM to PCI Express Interrupt Enable Register
191792a5b67SPavel Pisa 	 */
192792a5b67SPavel Pisa 	cra_a2p_ie = ioread32(cra_addr + CYCLONE_IV_CRA_A2P_IE);
193792a5b67SPavel Pisa 	dev_info(dev, "cra_a2p_ie 0x%08x\n", cra_a2p_ie);
194792a5b67SPavel Pisa 	cra_a2p_ie |= 1;
195792a5b67SPavel Pisa 	iowrite32(cra_a2p_ie, cra_addr + CYCLONE_IV_CRA_A2P_IE);
196792a5b67SPavel Pisa 	cra_a2p_ie = ioread32(cra_addr + CYCLONE_IV_CRA_A2P_IE);
197792a5b67SPavel Pisa 	dev_info(dev, "cra_a2p_ie 0x%08x\n", cra_a2p_ie);
198792a5b67SPavel Pisa 
199792a5b67SPavel Pisa 	return 0;
200792a5b67SPavel Pisa 
201792a5b67SPavel Pisa err_free_board:
202792a5b67SPavel Pisa 	pci_set_drvdata(pdev, NULL);
203792a5b67SPavel Pisa 	kfree(bdata);
204792a5b67SPavel Pisa err_pci_iounmap_bar0:
205792a5b67SPavel Pisa 	pci_iounmap(pdev, cra_addr);
206792a5b67SPavel Pisa err_pci_iounmap_bar1:
207792a5b67SPavel Pisa 	pci_iounmap(pdev, addr);
208792a5b67SPavel Pisa err_release_regions:
209*c9d23f96SCai Huoqing 	if (msi_ok)
210792a5b67SPavel Pisa 		pci_disable_msi(pdev);
211792a5b67SPavel Pisa 	pci_release_regions(pdev);
212792a5b67SPavel Pisa err_disable_device:
213792a5b67SPavel Pisa 	pci_disable_device(pdev);
214792a5b67SPavel Pisa err:
215792a5b67SPavel Pisa 	return ret;
216792a5b67SPavel Pisa }
217792a5b67SPavel Pisa 
218792a5b67SPavel Pisa /**
219792a5b67SPavel Pisa  * ctucan_pci_remove - Unregister the device after releasing the resources
220792a5b67SPavel Pisa  * @pdev:	Handle to the pci device structure
221792a5b67SPavel Pisa  *
222792a5b67SPavel Pisa  * This function frees all the resources allocated to the device.
223792a5b67SPavel Pisa  * Return: 0 always
224792a5b67SPavel Pisa  */
ctucan_pci_remove(struct pci_dev * pdev)225792a5b67SPavel Pisa static void ctucan_pci_remove(struct pci_dev *pdev)
226792a5b67SPavel Pisa {
227792a5b67SPavel Pisa 	struct net_device *ndev;
228792a5b67SPavel Pisa 	struct ctucan_priv *priv = NULL;
229792a5b67SPavel Pisa 	struct ctucan_pci_board_data *bdata = ctucan_pci_get_bdata(pdev);
230792a5b67SPavel Pisa 
231792a5b67SPavel Pisa 	dev_dbg(&pdev->dev, "ctucan_remove");
232792a5b67SPavel Pisa 
233792a5b67SPavel Pisa 	if (!bdata) {
234792a5b67SPavel Pisa 		dev_err(&pdev->dev, "%s: no list of devices\n", __func__);
235792a5b67SPavel Pisa 		return;
236792a5b67SPavel Pisa 	}
237792a5b67SPavel Pisa 
238792a5b67SPavel Pisa 	/* disable interrupt in
239792a5b67SPavel Pisa 	 * Avalon-MM to PCI Express Interrupt Enable Register
240792a5b67SPavel Pisa 	 */
241792a5b67SPavel Pisa 	if (bdata->cra_base)
242792a5b67SPavel Pisa 		iowrite32(0, bdata->cra_base + CYCLONE_IV_CRA_A2P_IE);
243792a5b67SPavel Pisa 
244792a5b67SPavel Pisa 	while ((priv = list_first_entry_or_null(&bdata->ndev_list_head, struct ctucan_priv,
245792a5b67SPavel Pisa 						peers_on_pdev)) != NULL) {
246792a5b67SPavel Pisa 		ndev = priv->can.dev;
247792a5b67SPavel Pisa 
248792a5b67SPavel Pisa 		unregister_candev(ndev);
249792a5b67SPavel Pisa 
250792a5b67SPavel Pisa 		netif_napi_del(&priv->napi);
251792a5b67SPavel Pisa 
252792a5b67SPavel Pisa 		list_del_init(&priv->peers_on_pdev);
253792a5b67SPavel Pisa 		free_candev(ndev);
254792a5b67SPavel Pisa 	}
255792a5b67SPavel Pisa 
256792a5b67SPavel Pisa 	pci_iounmap(pdev, bdata->bar1_base);
257792a5b67SPavel Pisa 
258*c9d23f96SCai Huoqing 	if (bdata->use_msi)
259792a5b67SPavel Pisa 		pci_disable_msi(pdev);
260792a5b67SPavel Pisa 
261792a5b67SPavel Pisa 	pci_release_regions(pdev);
262792a5b67SPavel Pisa 	pci_disable_device(pdev);
263792a5b67SPavel Pisa 
264792a5b67SPavel Pisa 	pci_iounmap(pdev, bdata->bar0_base);
265792a5b67SPavel Pisa 
266792a5b67SPavel Pisa 	pci_set_drvdata(pdev, NULL);
267792a5b67SPavel Pisa 	kfree(bdata);
268792a5b67SPavel Pisa }
269792a5b67SPavel Pisa 
270792a5b67SPavel Pisa static SIMPLE_DEV_PM_OPS(ctucan_pci_pm_ops, ctucan_suspend, ctucan_resume);
271792a5b67SPavel Pisa 
272792a5b67SPavel Pisa static const struct pci_device_id ctucan_pci_tbl[] = {
273792a5b67SPavel Pisa 	{PCI_DEVICE_DATA(TEDIA, CTUCAN_VER21,
274792a5b67SPavel Pisa 		CTUCAN_WITH_CTUCAN_ID)},
275792a5b67SPavel Pisa 	{},
276792a5b67SPavel Pisa };
277792a5b67SPavel Pisa 
278792a5b67SPavel Pisa static struct pci_driver ctucan_pci_driver = {
279792a5b67SPavel Pisa 	.name = KBUILD_MODNAME,
280792a5b67SPavel Pisa 	.id_table = ctucan_pci_tbl,
281792a5b67SPavel Pisa 	.probe = ctucan_pci_probe,
282792a5b67SPavel Pisa 	.remove = ctucan_pci_remove,
283792a5b67SPavel Pisa 	.driver.pm = &ctucan_pci_pm_ops,
284792a5b67SPavel Pisa };
285792a5b67SPavel Pisa 
286792a5b67SPavel Pisa module_pci_driver(ctucan_pci_driver);
287792a5b67SPavel Pisa 
288792a5b67SPavel Pisa MODULE_LICENSE("GPL");
289792a5b67SPavel Pisa MODULE_AUTHOR("Pavel Pisa <pisa@cmp.felk.cvut.cz>");
290792a5b67SPavel Pisa MODULE_DESCRIPTION("CTU CAN FD for PCI bus");
291