Skip to content

Commit 19971f5

Browse files
yangbolu1991davem330
authored andcommitted
enetc: add PTP clock driver
This patch is to add PTP clock driver for ENETC. The driver reused QorIQ PTP clock driver. Signed-off-by: Yangbo Lu <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent ad6e1be commit 19971f5

File tree

4 files changed

+162
-2
lines changed

4 files changed

+162
-2
lines changed

drivers/net/ethernet/freescale/enetc/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,15 @@ config FSL_ENETC_VF
1717
virtual function (VF) devices enabled by the ENETC PF driver.
1818

1919
If compiled as module (M), the module name is fsl-enetc-vf.
20+
21+
config FSL_ENETC_PTP_CLOCK
22+
tristate "ENETC PTP clock driver"
23+
depends on PTP_1588_CLOCK_QORIQ && (FSL_ENETC || FSL_ENETC_VF)
24+
default y
25+
help
26+
This driver adds support for using the ENETC 1588 timer
27+
as a PTP clock. This clock is only useful if your PTP
28+
programs are getting hardware time stamps on the PTP Ethernet
29+
packets using the SO_TIMESTAMPING API.
30+
31+
If compiled as module (M), the module name is fsl-enetc-ptp.

drivers/net/ethernet/freescale/enetc/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@ fsl-enetc-vf-$(CONFIG_FSL_ENETC_VF) += enetc.o enetc_cbdr.o \
1313
enetc_ethtool.o
1414
fsl-enetc-vf-objs := enetc_vf.o $(fsl-enetc-vf-y)
1515
endif
16+
17+
obj-$(CONFIG_FSL_ENETC_PTP_CLOCK) += fsl-enetc-ptp.o
18+
fsl-enetc-ptp-$(CONFIG_FSL_ENETC_PTP_CLOCK) += enetc_ptp.o

drivers/net/ethernet/freescale/enetc/enetc_hw.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
#include <linux/bitops.h>
55

66
/* ENETC device IDs */
7-
#define ENETC_DEV_ID_PF 0xe100
8-
#define ENETC_DEV_ID_VF 0xef00
7+
#define ENETC_DEV_ID_PF 0xe100
8+
#define ENETC_DEV_ID_VF 0xef00
9+
#define ENETC_DEV_ID_PTP 0xee02
910

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

0 commit comments

Comments
 (0)