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(device: 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(dev: pdev);
42 if (err)
43 return dev_err_probe(dev: &pdev->dev, err, fmt: "device enable failed\n");
44
45 err = dma_set_mask_and_coherent(dev: &pdev->dev, DMA_BIT_MASK(64));
46 if (err) {
47 dev_err(&pdev->dev, "DMA configuration failed: 0x%x\n", err);
48 goto err_dma;
49 }
50
51 err = pci_request_mem_regions(pdev, KBUILD_MODNAME);
52 if (err) {
53 dev_err(&pdev->dev, "pci_request_regions failed err=%d\n", err);
54 goto err_pci_mem_reg;
55 }
56
57 pci_set_master(dev: pdev);
58
59 ptp_qoriq = kzalloc(size: sizeof(*ptp_qoriq), GFP_KERNEL);
60 if (!ptp_qoriq) {
61 err = -ENOMEM;
62 goto err_alloc_ptp;
63 }
64
65 len = pci_resource_len(pdev, ENETC_BAR_REGS);
66
67 base = ioremap(pci_resource_start(pdev, ENETC_BAR_REGS), size: len);
68 if (!base) {
69 err = -ENXIO;
70 dev_err(&pdev->dev, "ioremap() failed\n");
71 goto err_ioremap;
72 }
73
74 /* Allocate 1 interrupt */
75 n = pci_alloc_irq_vectors(dev: pdev, min_vecs: 1, max_vecs: 1, PCI_IRQ_MSIX);
76 if (n != 1) {
77 err = -EPERM;
78 goto err_irq_vectors;
79 }
80
81 ptp_qoriq->irq = pci_irq_vector(dev: pdev, nr: 0);
82
83 err = request_irq(irq: ptp_qoriq->irq, handler: ptp_qoriq_isr, flags: 0, DRIVER, dev: ptp_qoriq);
84 if (err) {
85 dev_err(&pdev->dev, "request_irq() failed!\n");
86 goto err_irq;
87 }
88
89 ptp_qoriq->dev = &pdev->dev;
90
91 err = ptp_qoriq_init(ptp_qoriq, base, caps: &enetc_ptp_caps);
92 if (err)
93 goto err_no_clock;
94
95 enetc_phc_index = ptp_qoriq->phc_index;
96 pci_set_drvdata(pdev, data: ptp_qoriq);
97
98 return 0;
99
100err_no_clock:
101 free_irq(ptp_qoriq->irq, ptp_qoriq);
102err_irq:
103 pci_free_irq_vectors(dev: pdev);
104err_irq_vectors:
105 iounmap(addr: base);
106err_ioremap:
107 kfree(objp: ptp_qoriq);
108err_alloc_ptp:
109 pci_release_mem_regions(pdev);
110err_pci_mem_reg:
111err_dma:
112 pci_disable_device(dev: pdev);
113
114 return err;
115}
116
117static void enetc_ptp_remove(struct pci_dev *pdev)
118{
119 struct ptp_qoriq *ptp_qoriq = pci_get_drvdata(pdev);
120
121 enetc_phc_index = -1;
122 ptp_qoriq_free(ptp_qoriq);
123 pci_free_irq_vectors(dev: pdev);
124 kfree(objp: ptp_qoriq);
125
126 pci_release_mem_regions(pdev);
127 pci_disable_device(dev: pdev);
128}
129
130static const struct pci_device_id enetc_ptp_id_table[] = {
131 { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_PTP) },
132 { 0, } /* End of table. */
133};
134MODULE_DEVICE_TABLE(pci, enetc_ptp_id_table);
135
136static struct pci_driver enetc_ptp_driver = {
137 .name = KBUILD_MODNAME,
138 .id_table = enetc_ptp_id_table,
139 .probe = enetc_ptp_probe,
140 .remove = enetc_ptp_remove,
141};
142module_pci_driver(enetc_ptp_driver);
143
144MODULE_DESCRIPTION("ENETC PTP clock driver");
145MODULE_LICENSE("Dual BSD/GPL");
146

source code of linux/drivers/net/ethernet/freescale/enetc/enetc_ptp.c