1// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
2/* Copyright 2019 NXP */
3
4#include <linux/module.h>
5#include <linux/of.h>
6#include <linux/fsl/ptp_qoriq.h>
7
8#include "enetc.h"
9
10int enetc_phc_index = -1;
11EXPORT_SYMBOL_GPL(enetc_phc_index);
12
13static struct ptp_clock_info enetc_ptp_caps = {
14	.owner		= THIS_MODULE,
15	.name		= "ENETC PTP clock",
16	.max_adj	= 512000,
17	.n_alarm	= 0,
18	.n_ext_ts	= 2,
19	.n_per_out	= 0,
20	.n_pins		= 0,
21	.pps		= 1,
22	.adjfine	= ptp_qoriq_adjfine,
23	.adjtime	= ptp_qoriq_adjtime,
24	.gettime64	= ptp_qoriq_gettime,
25	.settime64	= ptp_qoriq_settime,
26	.enable		= ptp_qoriq_enable,
27};
28
29static int enetc_ptp_probe(struct pci_dev *pdev,
30			   const struct pci_device_id *ent)
31{
32	struct ptp_qoriq *ptp_qoriq;
33	void __iomem *base;
34	int err, len, n;
35
36	if (pdev->dev.of_node && !of_device_is_available(pdev->dev.of_node)) {
37		dev_info(&pdev->dev, "device is disabled, skipping\n");
38		return -ENODEV;
39	}
40
41	err = pci_enable_device_mem(pdev);
42	if (err) {
43		dev_err(&pdev->dev, "device enable failed\n");
44		return err;
45	}
46
47	/* set up for high or low dma */
48	err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
49	if (err) {
50		err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
51		if (err) {
52			dev_err(&pdev->dev,
53				"DMA configuration failed: 0x%x\n", err);
54			goto err_dma;
55		}
56	}
57
58	err = pci_request_mem_regions(pdev, KBUILD_MODNAME);
59	if (err) {
60		dev_err(&pdev->dev, "pci_request_regions failed err=%d\n", err);
61		goto err_pci_mem_reg;
62	}
63
64	pci_set_master(pdev);
65
66	ptp_qoriq = kzalloc(sizeof(*ptp_qoriq), GFP_KERNEL);
67	if (!ptp_qoriq) {
68		err = -ENOMEM;
69		goto err_alloc_ptp;
70	}
71
72	len = pci_resource_len(pdev, ENETC_BAR_REGS);
73
74	base = ioremap(pci_resource_start(pdev, ENETC_BAR_REGS), len);
75	if (!base) {
76		err = -ENXIO;
77		dev_err(&pdev->dev, "ioremap() failed\n");
78		goto err_ioremap;
79	}
80
81	/* Allocate 1 interrupt */
82	n = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX);
83	if (n != 1) {
84		err = -EPERM;
85		goto err_irq_vectors;
86	}
87
88	ptp_qoriq->irq = pci_irq_vector(pdev, 0);
89
90	err = request_irq(ptp_qoriq->irq, ptp_qoriq_isr, 0, DRIVER, ptp_qoriq);
91	if (err) {
92		dev_err(&pdev->dev, "request_irq() failed!\n");
93		goto err_irq;
94	}
95
96	ptp_qoriq->dev = &pdev->dev;
97
98	err = ptp_qoriq_init(ptp_qoriq, base, &enetc_ptp_caps);
99	if (err)
100		goto err_no_clock;
101
102	enetc_phc_index = ptp_qoriq->phc_index;
103	pci_set_drvdata(pdev, ptp_qoriq);
104
105	return 0;
106
107err_no_clock:
108	free_irq(ptp_qoriq->irq, ptp_qoriq);
109err_irq:
110	pci_free_irq_vectors(pdev);
111err_irq_vectors:
112	iounmap(base);
113err_ioremap:
114	kfree(ptp_qoriq);
115err_alloc_ptp:
116	pci_release_mem_regions(pdev);
117err_pci_mem_reg:
118err_dma:
119	pci_disable_device(pdev);
120
121	return err;
122}
123
124static void enetc_ptp_remove(struct pci_dev *pdev)
125{
126	struct ptp_qoriq *ptp_qoriq = pci_get_drvdata(pdev);
127
128	enetc_phc_index = -1;
129	ptp_qoriq_free(ptp_qoriq);
130	pci_free_irq_vectors(pdev);
131	kfree(ptp_qoriq);
132
133	pci_release_mem_regions(pdev);
134	pci_disable_device(pdev);
135}
136
137static const struct pci_device_id enetc_ptp_id_table[] = {
138	{ PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_PTP) },
139	{ 0, } /* End of table. */
140};
141MODULE_DEVICE_TABLE(pci, enetc_ptp_id_table);
142
143static struct pci_driver enetc_ptp_driver = {
144	.name = KBUILD_MODNAME,
145	.id_table = enetc_ptp_id_table,
146	.probe = enetc_ptp_probe,
147	.remove = enetc_ptp_remove,
148};
149module_pci_driver(enetc_ptp_driver);
150
151MODULE_DESCRIPTION("ENETC PTP clock driver");
152MODULE_LICENSE("Dual BSD/GPL");
153