1 // SPDX-License-Identifier: GPL-2.0
2 /* Marvell PTP driver
3 *
4 * Copyright (C) 2020 Marvell International Ltd.
5 */
6
7 #include <linux/bitfield.h>
8 #include <linux/device.h>
9 #include <linux/module.h>
10 #include <linux/pci.h>
11
12 #include "ptp.h"
13 #include "mbox.h"
14 #include "rvu.h"
15
16 #define DRV_NAME "Marvell PTP Driver"
17
18 #define PCI_DEVID_OCTEONTX2_PTP 0xA00C
19 #define PCI_SUBSYS_DEVID_OCTX2_98xx_PTP 0xB100
20 #define PCI_SUBSYS_DEVID_OCTX2_96XX_PTP 0xB200
21 #define PCI_SUBSYS_DEVID_OCTX2_95XX_PTP 0xB300
22 #define PCI_SUBSYS_DEVID_OCTX2_LOKI_PTP 0xB400
23 #define PCI_SUBSYS_DEVID_OCTX2_95MM_PTP 0xB500
24 #define PCI_SUBSYS_DEVID_CN10K_A_PTP 0xB900
25 #define PCI_SUBSYS_DEVID_CNF10K_A_PTP 0xBA00
26 #define PCI_SUBSYS_DEVID_CNF10K_B_PTP 0xBC00
27 #define PCI_DEVID_OCTEONTX2_RST 0xA085
28
29 #define PCI_PTP_BAR_NO 0
30 #define PCI_RST_BAR_NO 0
31
32 #define PTP_CLOCK_CFG 0xF00ULL
33 #define PTP_CLOCK_CFG_PTP_EN BIT_ULL(0)
34 #define PTP_CLOCK_LO 0xF08ULL
35 #define PTP_CLOCK_HI 0xF10ULL
36 #define PTP_CLOCK_COMP 0xF18ULL
37
38 #define RST_BOOT 0x1600ULL
39 #define RST_MUL_BITS GENMASK_ULL(38, 33)
40 #define CLOCK_BASE_RATE 50000000ULL
41
get_clock_rate(void)42 static u64 get_clock_rate(void)
43 {
44 u64 cfg, ret = CLOCK_BASE_RATE * 16;
45 struct pci_dev *pdev;
46 void __iomem *base;
47
48 /* To get the input clock frequency with which PTP co-processor
49 * block is running the base frequency(50 MHz) needs to be multiplied
50 * with multiplier bits present in RST_BOOT register of RESET block.
51 * Hence below code gets the multiplier bits from the RESET PCI
52 * device present in the system.
53 */
54 pdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
55 PCI_DEVID_OCTEONTX2_RST, NULL);
56 if (!pdev)
57 goto error;
58
59 base = pci_ioremap_bar(pdev, PCI_RST_BAR_NO);
60 if (!base)
61 goto error_put_pdev;
62
63 cfg = readq(base + RST_BOOT);
64 ret = CLOCK_BASE_RATE * FIELD_GET(RST_MUL_BITS, cfg);
65
66 iounmap(base);
67
68 error_put_pdev:
69 pci_dev_put(pdev);
70
71 error:
72 return ret;
73 }
74
ptp_get(void)75 struct ptp *ptp_get(void)
76 {
77 struct pci_dev *pdev;
78 struct ptp *ptp;
79
80 /* If the PTP pci device is found on the system and ptp
81 * driver is bound to it then the PTP pci device is returned
82 * to the caller(rvu driver).
83 */
84 pdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
85 PCI_DEVID_OCTEONTX2_PTP, NULL);
86 if (!pdev)
87 return ERR_PTR(-ENODEV);
88
89 ptp = pci_get_drvdata(pdev);
90 if (!ptp)
91 ptp = ERR_PTR(-EPROBE_DEFER);
92 if (IS_ERR(ptp))
93 pci_dev_put(pdev);
94
95 return ptp;
96 }
97
ptp_put(struct ptp * ptp)98 void ptp_put(struct ptp *ptp)
99 {
100 if (!ptp)
101 return;
102
103 pci_dev_put(ptp->pdev);
104 }
105
ptp_adjfine(struct ptp * ptp,long scaled_ppm)106 static int ptp_adjfine(struct ptp *ptp, long scaled_ppm)
107 {
108 bool neg_adj = false;
109 u64 comp;
110 u64 adj;
111 s64 ppb;
112
113 if (scaled_ppm < 0) {
114 neg_adj = true;
115 scaled_ppm = -scaled_ppm;
116 }
117
118 /* The hardware adds the clock compensation value to the PTP clock
119 * on every coprocessor clock cycle. Typical convention is that it
120 * represent number of nanosecond betwen each cycle. In this
121 * convention compensation value is in 64 bit fixed-point
122 * representation where upper 32 bits are number of nanoseconds
123 * and lower is fractions of nanosecond.
124 * The scaled_ppm represent the ratio in "parts per million" by which
125 * the compensation value should be corrected.
126 * To calculate new compenstation value we use 64bit fixed point
127 * arithmetic on following formula
128 * comp = tbase + tbase * scaled_ppm / (1M * 2^16)
129 * where tbase is the basic compensation value calculated
130 * initialy in the probe function.
131 */
132 comp = ((u64)1000000000ull << 32) / ptp->clock_rate;
133 /* convert scaled_ppm to ppb */
134 ppb = 1 + scaled_ppm;
135 ppb *= 125;
136 ppb >>= 13;
137 adj = comp * ppb;
138 adj = div_u64(adj, 1000000000ull);
139 comp = neg_adj ? comp - adj : comp + adj;
140
141 writeq(comp, ptp->reg_base + PTP_CLOCK_COMP);
142
143 return 0;
144 }
145
ptp_get_clock(struct ptp * ptp,u64 * clk)146 static int ptp_get_clock(struct ptp *ptp, u64 *clk)
147 {
148 /* Return the current PTP clock */
149 *clk = readq(ptp->reg_base + PTP_CLOCK_HI);
150
151 return 0;
152 }
153
ptp_probe(struct pci_dev * pdev,const struct pci_device_id * ent)154 static int ptp_probe(struct pci_dev *pdev,
155 const struct pci_device_id *ent)
156 {
157 struct device *dev = &pdev->dev;
158 struct ptp *ptp;
159 u64 clock_comp;
160 u64 clock_cfg;
161 int err;
162
163 ptp = devm_kzalloc(dev, sizeof(*ptp), GFP_KERNEL);
164 if (!ptp) {
165 err = -ENOMEM;
166 goto error;
167 }
168
169 ptp->pdev = pdev;
170
171 err = pcim_enable_device(pdev);
172 if (err)
173 goto error_free;
174
175 err = pcim_iomap_regions(pdev, 1 << PCI_PTP_BAR_NO, pci_name(pdev));
176 if (err)
177 goto error_free;
178
179 ptp->reg_base = pcim_iomap_table(pdev)[PCI_PTP_BAR_NO];
180
181 ptp->clock_rate = get_clock_rate();
182
183 /* Enable PTP clock */
184 clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG);
185 clock_cfg |= PTP_CLOCK_CFG_PTP_EN;
186 writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG);
187
188 clock_comp = ((u64)1000000000ull << 32) / ptp->clock_rate;
189 /* Initial compensation value to start the nanosecs counter */
190 writeq(clock_comp, ptp->reg_base + PTP_CLOCK_COMP);
191
192 pci_set_drvdata(pdev, ptp);
193
194 return 0;
195
196 error_free:
197 devm_kfree(dev, ptp);
198
199 error:
200 /* For `ptp_get()` we need to differentiate between the case
201 * when the core has not tried to probe this device and the case when
202 * the probe failed. In the later case we pretend that the
203 * initialization was successful and keep the error in
204 * `dev->driver_data`.
205 */
206 pci_set_drvdata(pdev, ERR_PTR(err));
207 return 0;
208 }
209
ptp_remove(struct pci_dev * pdev)210 static void ptp_remove(struct pci_dev *pdev)
211 {
212 struct ptp *ptp = pci_get_drvdata(pdev);
213 u64 clock_cfg;
214
215 if (IS_ERR_OR_NULL(ptp))
216 return;
217
218 /* Disable PTP clock */
219 clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG);
220 clock_cfg &= ~PTP_CLOCK_CFG_PTP_EN;
221 writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG);
222 }
223
224 static const struct pci_device_id ptp_id_table[] = {
225 { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_PTP,
226 PCI_VENDOR_ID_CAVIUM,
227 PCI_SUBSYS_DEVID_OCTX2_98xx_PTP) },
228 { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_PTP,
229 PCI_VENDOR_ID_CAVIUM,
230 PCI_SUBSYS_DEVID_OCTX2_96XX_PTP) },
231 { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_PTP,
232 PCI_VENDOR_ID_CAVIUM,
233 PCI_SUBSYS_DEVID_OCTX2_95XX_PTP) },
234 { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_PTP,
235 PCI_VENDOR_ID_CAVIUM,
236 PCI_SUBSYS_DEVID_OCTX2_LOKI_PTP) },
237 { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_PTP,
238 PCI_VENDOR_ID_CAVIUM,
239 PCI_SUBSYS_DEVID_OCTX2_95MM_PTP) },
240 { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_PTP,
241 PCI_VENDOR_ID_CAVIUM,
242 PCI_SUBSYS_DEVID_CN10K_A_PTP) },
243 { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_PTP,
244 PCI_VENDOR_ID_CAVIUM,
245 PCI_SUBSYS_DEVID_CNF10K_A_PTP) },
246 { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_OCTEONTX2_PTP,
247 PCI_VENDOR_ID_CAVIUM,
248 PCI_SUBSYS_DEVID_CNF10K_B_PTP) },
249 { 0, }
250 };
251
252 struct pci_driver ptp_driver = {
253 .name = DRV_NAME,
254 .id_table = ptp_id_table,
255 .probe = ptp_probe,
256 .remove = ptp_remove,
257 };
258
rvu_mbox_handler_ptp_op(struct rvu * rvu,struct ptp_req * req,struct ptp_rsp * rsp)259 int rvu_mbox_handler_ptp_op(struct rvu *rvu, struct ptp_req *req,
260 struct ptp_rsp *rsp)
261 {
262 int err = 0;
263
264 /* This function is the PTP mailbox handler invoked when
265 * called by AF consumers/netdev drivers via mailbox mechanism.
266 * It is used by netdev driver to get the PTP clock and to set
267 * frequency adjustments. Since mailbox can be called without
268 * notion of whether the driver is bound to ptp device below
269 * validation is needed as first step.
270 */
271 if (!rvu->ptp)
272 return -ENODEV;
273
274 switch (req->op) {
275 case PTP_OP_ADJFINE:
276 err = ptp_adjfine(rvu->ptp, req->scaled_ppm);
277 break;
278 case PTP_OP_GET_CLOCK:
279 err = ptp_get_clock(rvu->ptp, &rsp->clk);
280 break;
281 default:
282 err = -EINVAL;
283 break;
284 }
285
286 return err;
287 }
288