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