1 // SPDX-License-Identifier: GPL-2.0
2 /* cavium_ptp.c - PTP 1588 clock on Cavium hardware
3 * Copyright (c) 2003-2015, 2017 Cavium, Inc.
6 #include <linux/device.h>
7 #include <linux/module.h>
8 #include <linux/timecounter.h>
11 #include "cavium_ptp.h"
13 #define DRV_NAME "Cavium PTP Driver"
15 #define PCI_DEVICE_ID_CAVIUM_PTP 0xA00C
16 #define PCI_DEVICE_ID_CAVIUM_RST 0xA00E
18 #define PCI_PTP_BAR_NO 0
19 #define PCI_RST_BAR_NO 0
21 #define PTP_CLOCK_CFG 0xF00ULL
22 #define PTP_CLOCK_CFG_PTP_EN BIT(0)
23 #define PTP_CLOCK_LO 0xF08ULL
24 #define PTP_CLOCK_HI 0xF10ULL
25 #define PTP_CLOCK_COMP 0xF18ULL
27 #define RST_BOOT 0x1600ULL
28 #define CLOCK_BASE_RATE 50000000ULL
30 static u64
ptp_cavium_clock_get(void)
34 u64 ret
= CLOCK_BASE_RATE
* 16;
36 pdev
= pci_get_device(PCI_VENDOR_ID_CAVIUM
,
37 PCI_DEVICE_ID_CAVIUM_RST
, NULL
);
41 base
= pci_ioremap_bar(pdev
, PCI_RST_BAR_NO
);
45 ret
= CLOCK_BASE_RATE
* ((readq(base
+ RST_BOOT
) >> 33) & 0x3f);
56 struct cavium_ptp
*cavium_ptp_get(void)
58 struct cavium_ptp
*ptp
;
61 pdev
= pci_get_device(PCI_VENDOR_ID_CAVIUM
,
62 PCI_DEVICE_ID_CAVIUM_PTP
, NULL
);
64 return ERR_PTR(-ENODEV
);
66 ptp
= pci_get_drvdata(pdev
);
68 ptp
= ERR_PTR(-EPROBE_DEFER
);
74 EXPORT_SYMBOL(cavium_ptp_get
);
76 void cavium_ptp_put(struct cavium_ptp
*ptp
)
80 pci_dev_put(ptp
->pdev
);
82 EXPORT_SYMBOL(cavium_ptp_put
);
85 * cavium_ptp_adjfine() - Adjust ptp frequency
86 * @ptp: PTP clock info
87 * @scaled_ppm: how much to adjust by, in parts per million, but with a
88 * 16 bit binary fractional field
90 static int cavium_ptp_adjfine(struct ptp_clock_info
*ptp_info
, long scaled_ppm
)
92 struct cavium_ptp
*clock
=
93 container_of(ptp_info
, struct cavium_ptp
, ptp_info
);
101 scaled_ppm
= -scaled_ppm
;
104 /* The hardware adds the clock compensation value to the PTP clock
105 * on every coprocessor clock cycle. Typical convention is that it
106 * represent number of nanosecond betwen each cycle. In this
107 * convention compensation value is in 64 bit fixed-point
108 * representation where upper 32 bits are number of nanoseconds
109 * and lower is fractions of nanosecond.
110 * The scaled_ppm represent the ratio in "parts per bilion" by which the
111 * compensation value should be corrected.
112 * To calculate new compenstation value we use 64bit fixed point
113 * arithmetic on following formula
114 * comp = tbase + tbase * scaled_ppm / (1M * 2^16)
115 * where tbase is the basic compensation value calculated initialy
116 * in cavium_ptp_init() -> tbase = 1/Hz. Then we use endian
117 * independent structure definition to write data to PTP register.
119 comp
= ((u64
)1000000000ull << 32) / clock
->clock_rate
;
120 adj
= comp
* scaled_ppm
;
122 adj
= div_u64(adj
, 1000000ull);
123 comp
= neg_adj
? comp
- adj
: comp
+ adj
;
125 spin_lock_irqsave(&clock
->spin_lock
, flags
);
126 writeq(comp
, clock
->reg_base
+ PTP_CLOCK_COMP
);
127 spin_unlock_irqrestore(&clock
->spin_lock
, flags
);
133 * cavium_ptp_adjtime() - Adjust ptp time
134 * @ptp: PTP clock info
135 * @delta: how much to adjust by, in nanosecs
137 static int cavium_ptp_adjtime(struct ptp_clock_info
*ptp_info
, s64 delta
)
139 struct cavium_ptp
*clock
=
140 container_of(ptp_info
, struct cavium_ptp
, ptp_info
);
143 spin_lock_irqsave(&clock
->spin_lock
, flags
);
144 timecounter_adjtime(&clock
->time_counter
, delta
);
145 spin_unlock_irqrestore(&clock
->spin_lock
, flags
);
147 /* Sync, for network driver to get latest value */
154 * cavium_ptp_gettime() - Get hardware clock time with adjustment
155 * @ptp: PTP clock info
158 static int cavium_ptp_gettime(struct ptp_clock_info
*ptp_info
,
159 struct timespec64
*ts
)
161 struct cavium_ptp
*clock
=
162 container_of(ptp_info
, struct cavium_ptp
, ptp_info
);
166 spin_lock_irqsave(&clock
->spin_lock
, flags
);
167 nsec
= timecounter_read(&clock
->time_counter
);
168 spin_unlock_irqrestore(&clock
->spin_lock
, flags
);
170 *ts
= ns_to_timespec64(nsec
);
176 * cavium_ptp_settime() - Set hardware clock time. Reset adjustment
177 * @ptp: PTP clock info
180 static int cavium_ptp_settime(struct ptp_clock_info
*ptp_info
,
181 const struct timespec64
*ts
)
183 struct cavium_ptp
*clock
=
184 container_of(ptp_info
, struct cavium_ptp
, ptp_info
);
188 nsec
= timespec64_to_ns(ts
);
190 spin_lock_irqsave(&clock
->spin_lock
, flags
);
191 timecounter_init(&clock
->time_counter
, &clock
->cycle_counter
, nsec
);
192 spin_unlock_irqrestore(&clock
->spin_lock
, flags
);
198 * cavium_ptp_enable() - Request to enable or disable an ancillary feature.
199 * @ptp: PTP clock info
203 static int cavium_ptp_enable(struct ptp_clock_info
*ptp_info
,
204 struct ptp_clock_request
*rq
, int on
)
209 static u64
cavium_ptp_cc_read(const struct cyclecounter
*cc
)
211 struct cavium_ptp
*clock
=
212 container_of(cc
, struct cavium_ptp
, cycle_counter
);
214 return readq(clock
->reg_base
+ PTP_CLOCK_HI
);
217 static int cavium_ptp_probe(struct pci_dev
*pdev
,
218 const struct pci_device_id
*ent
)
220 struct device
*dev
= &pdev
->dev
;
221 struct cavium_ptp
*clock
;
222 struct cyclecounter
*cc
;
227 clock
= devm_kzalloc(dev
, sizeof(*clock
), GFP_KERNEL
);
235 err
= pcim_enable_device(pdev
);
239 err
= pcim_iomap_regions(pdev
, 1 << PCI_PTP_BAR_NO
, pci_name(pdev
));
243 clock
->reg_base
= pcim_iomap_table(pdev
)[PCI_PTP_BAR_NO
];
245 spin_lock_init(&clock
->spin_lock
);
247 cc
= &clock
->cycle_counter
;
248 cc
->read
= cavium_ptp_cc_read
;
249 cc
->mask
= CYCLECOUNTER_MASK(64);
253 timecounter_init(&clock
->time_counter
, &clock
->cycle_counter
,
254 ktime_to_ns(ktime_get_real()));
256 clock
->clock_rate
= ptp_cavium_clock_get();
258 clock
->ptp_info
= (struct ptp_clock_info
) {
259 .owner
= THIS_MODULE
,
260 .name
= "ThunderX PTP",
261 .max_adj
= 1000000000ull,
265 .adjfine
= cavium_ptp_adjfine
,
266 .adjtime
= cavium_ptp_adjtime
,
267 .gettime64
= cavium_ptp_gettime
,
268 .settime64
= cavium_ptp_settime
,
269 .enable
= cavium_ptp_enable
,
272 clock_cfg
= readq(clock
->reg_base
+ PTP_CLOCK_CFG
);
273 clock_cfg
|= PTP_CLOCK_CFG_PTP_EN
;
274 writeq(clock_cfg
, clock
->reg_base
+ PTP_CLOCK_CFG
);
276 clock_comp
= ((u64
)1000000000ull << 32) / clock
->clock_rate
;
277 writeq(clock_comp
, clock
->reg_base
+ PTP_CLOCK_COMP
);
279 clock
->ptp_clock
= ptp_clock_register(&clock
->ptp_info
, dev
);
280 if (!clock
->ptp_clock
) {
284 if (IS_ERR(clock
->ptp_clock
)) {
285 err
= PTR_ERR(clock
->ptp_clock
);
289 pci_set_drvdata(pdev
, clock
);
293 clock_cfg
= readq(clock
->reg_base
+ PTP_CLOCK_CFG
);
294 clock_cfg
&= ~PTP_CLOCK_CFG_PTP_EN
;
295 writeq(clock_cfg
, clock
->reg_base
+ PTP_CLOCK_CFG
);
296 pcim_iounmap_regions(pdev
, 1 << PCI_PTP_BAR_NO
);
299 devm_kfree(dev
, clock
);
302 /* For `cavium_ptp_get()` we need to differentiate between the case
303 * when the core has not tried to probe this device and the case when
304 * the probe failed. In the later case we pretend that the
305 * initialization was successful and keep the error in
306 * `dev->driver_data`.
308 pci_set_drvdata(pdev
, ERR_PTR(err
));
312 static void cavium_ptp_remove(struct pci_dev
*pdev
)
314 struct cavium_ptp
*clock
= pci_get_drvdata(pdev
);
317 if (IS_ERR_OR_NULL(clock
))
320 ptp_clock_unregister(clock
->ptp_clock
);
322 clock_cfg
= readq(clock
->reg_base
+ PTP_CLOCK_CFG
);
323 clock_cfg
&= ~PTP_CLOCK_CFG_PTP_EN
;
324 writeq(clock_cfg
, clock
->reg_base
+ PTP_CLOCK_CFG
);
327 static const struct pci_device_id cavium_ptp_id_table
[] = {
328 { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM
, PCI_DEVICE_ID_CAVIUM_PTP
) },
332 static struct pci_driver cavium_ptp_driver
= {
334 .id_table
= cavium_ptp_id_table
,
335 .probe
= cavium_ptp_probe
,
336 .remove
= cavium_ptp_remove
,
339 static int __init
cavium_ptp_init_module(void)
341 return pci_register_driver(&cavium_ptp_driver
);
344 static void __exit
cavium_ptp_cleanup_module(void)
346 pci_unregister_driver(&cavium_ptp_driver
);
349 module_init(cavium_ptp_init_module
);
350 module_exit(cavium_ptp_cleanup_module
);
352 MODULE_DESCRIPTION(DRV_NAME
);
353 MODULE_AUTHOR("Cavium Networks <support@cavium.com>");
354 MODULE_LICENSE("GPL v2");
355 MODULE_DEVICE_TABLE(pci
, cavium_ptp_id_table
);