1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2020 Facebook */
5 #include <linux/kernel.h>
6 #include <linux/module.h>
7 #include <linux/init.h>
9 #include <linux/ptp_clock_kernel.h>
11 static const struct pci_device_id ptp_ocp_pcidev_id
[] = {
12 { PCI_DEVICE(0x1d9b, 0x0400) },
15 MODULE_DEVICE_TABLE(pci
, ptp_ocp_pcidev_id
);
17 #define OCP_REGISTER_OFFSET 0x01000000
34 #define OCP_CTRL_ENABLE BIT(0)
35 #define OCP_CTRL_ADJUST_TIME BIT(1)
36 #define OCP_CTRL_ADJUST_OFFSET BIT(2)
37 #define OCP_CTRL_READ_TIME_REQ BIT(30)
38 #define OCP_CTRL_READ_TIME_DONE BIT(31)
40 #define OCP_STATUS_IN_SYNC BIT(0)
42 #define OCP_SELECT_CLK_NONE 0
43 #define OCP_SELECT_CLK_REG 6
58 #define TOD_REGISTER_OFFSET 0x01050000
60 #define TOD_CTRL_PROTOCOL BIT(28)
61 #define TOD_CTRL_DISABLE_FMT_A BIT(17)
62 #define TOD_CTRL_DISABLE_FMT_B BIT(16)
63 #define TOD_CTRL_ENABLE BIT(0)
64 #define TOD_CTRL_GNSS_MASK ((1U << 4) - 1)
65 #define TOD_CTRL_GNSS_SHIFT 24
67 #define TOD_STATUS_UTC_MASK 0xff
68 #define TOD_STATUS_UTC_VALID BIT(8)
69 #define TOD_STATUS_LEAP_VALID BIT(16)
75 struct ocp_reg __iomem
*reg
;
76 struct tod_reg __iomem
*tod
;
77 struct ptp_clock
*ptp
;
78 struct ptp_clock_info ptp_info
;
82 __ptp_ocp_gettime_locked(struct ptp_ocp
*bp
, struct timespec64
*ts
,
83 struct ptp_system_timestamp
*sts
)
85 u32 ctrl
, time_sec
, time_ns
;
88 ctrl
= ioread32(&bp
->reg
->ctrl
);
89 ctrl
|= OCP_CTRL_READ_TIME_REQ
;
91 ptp_read_system_prets(sts
);
92 iowrite32(ctrl
, &bp
->reg
->ctrl
);
94 for (i
= 0; i
< 100; i
++) {
95 ctrl
= ioread32(&bp
->reg
->ctrl
);
96 if (ctrl
& OCP_CTRL_READ_TIME_DONE
)
99 ptp_read_system_postts(sts
);
101 time_ns
= ioread32(&bp
->reg
->time_ns
);
102 time_sec
= ioread32(&bp
->reg
->time_sec
);
104 ts
->tv_sec
= time_sec
;
105 ts
->tv_nsec
= time_ns
;
107 return ctrl
& OCP_CTRL_READ_TIME_DONE
? 0 : -ETIMEDOUT
;
111 ptp_ocp_gettimex(struct ptp_clock_info
*ptp_info
, struct timespec64
*ts
,
112 struct ptp_system_timestamp
*sts
)
114 struct ptp_ocp
*bp
= container_of(ptp_info
, struct ptp_ocp
, ptp_info
);
118 spin_lock_irqsave(&bp
->lock
, flags
);
119 err
= __ptp_ocp_gettime_locked(bp
, ts
, sts
);
120 spin_unlock_irqrestore(&bp
->lock
, flags
);
126 __ptp_ocp_settime_locked(struct ptp_ocp
*bp
, const struct timespec64
*ts
)
128 u32 ctrl
, time_sec
, time_ns
;
131 time_ns
= ts
->tv_nsec
;
132 time_sec
= ts
->tv_sec
;
134 select
= ioread32(&bp
->reg
->select
);
135 iowrite32(OCP_SELECT_CLK_REG
, &bp
->reg
->select
);
137 iowrite32(time_ns
, &bp
->reg
->adjust_ns
);
138 iowrite32(time_sec
, &bp
->reg
->adjust_sec
);
140 ctrl
= ioread32(&bp
->reg
->ctrl
);
141 ctrl
|= OCP_CTRL_ADJUST_TIME
;
142 iowrite32(ctrl
, &bp
->reg
->ctrl
);
144 /* restore clock selection */
145 iowrite32(select
>> 16, &bp
->reg
->select
);
149 ptp_ocp_settime(struct ptp_clock_info
*ptp_info
, const struct timespec64
*ts
)
151 struct ptp_ocp
*bp
= container_of(ptp_info
, struct ptp_ocp
, ptp_info
);
154 if (ioread32(&bp
->reg
->status
) & OCP_STATUS_IN_SYNC
)
157 spin_lock_irqsave(&bp
->lock
, flags
);
158 __ptp_ocp_settime_locked(bp
, ts
);
159 spin_unlock_irqrestore(&bp
->lock
, flags
);
165 ptp_ocp_adjtime(struct ptp_clock_info
*ptp_info
, s64 delta_ns
)
167 struct ptp_ocp
*bp
= container_of(ptp_info
, struct ptp_ocp
, ptp_info
);
168 struct timespec64 ts
;
172 if (ioread32(&bp
->reg
->status
) & OCP_STATUS_IN_SYNC
)
175 spin_lock_irqsave(&bp
->lock
, flags
);
176 err
= __ptp_ocp_gettime_locked(bp
, &ts
, NULL
);
178 timespec64_add_ns(&ts
, delta_ns
);
179 __ptp_ocp_settime_locked(bp
, &ts
);
181 spin_unlock_irqrestore(&bp
->lock
, flags
);
187 ptp_ocp_null_adjfine(struct ptp_clock_info
*ptp_info
, long scaled_ppm
)
195 static const struct ptp_clock_info ptp_ocp_clock_info
= {
196 .owner
= THIS_MODULE
,
197 .name
= KBUILD_MODNAME
,
198 .max_adj
= 100000000,
199 .gettimex64
= ptp_ocp_gettimex
,
200 .settime64
= ptp_ocp_settime
,
201 .adjtime
= ptp_ocp_adjtime
,
202 .adjfine
= ptp_ocp_null_adjfine
,
206 ptp_ocp_check_clock(struct ptp_ocp
*bp
)
208 struct timespec64 ts
;
212 /* make sure clock is enabled */
213 ctrl
= ioread32(&bp
->reg
->ctrl
);
214 ctrl
|= OCP_CTRL_ENABLE
;
215 iowrite32(ctrl
, &bp
->reg
->ctrl
);
217 if ((ioread32(&bp
->reg
->ctrl
) & OCP_CTRL_ENABLE
) == 0) {
218 dev_err(&bp
->pdev
->dev
, "clock not enabled\n");
222 sync
= ioread32(&bp
->reg
->status
) & OCP_STATUS_IN_SYNC
;
224 ktime_get_real_ts64(&ts
);
225 ptp_ocp_settime(&bp
->ptp_info
, &ts
);
227 if (!ptp_ocp_gettimex(&bp
->ptp_info
, &ts
, NULL
))
228 dev_info(&bp
->pdev
->dev
, "Time: %lld.%ld, %s\n",
229 ts
.tv_sec
, ts
.tv_nsec
,
230 sync
? "in-sync" : "UNSYNCED");
236 ptp_ocp_tod_info(struct ptp_ocp
*bp
)
238 static const char * const proto_name
[] = {
239 "NMEA", "NMEA_ZDA", "NMEA_RMC", "NMEA_none",
240 "UBX", "UBX_UTC", "UBX_LS", "UBX_none"
242 static const char * const gnss_name
[] = {
243 "ALL", "COMBINED", "GPS", "GLONASS", "GALILEO", "BEIDOU",
245 u32 version
, ctrl
, reg
;
248 version
= ioread32(&bp
->tod
->version
);
249 dev_info(&bp
->pdev
->dev
, "TOD Version %d.%d.%d\n",
250 version
>> 24, (version
>> 16) & 0xff, version
& 0xffff);
252 ctrl
= ioread32(&bp
->tod
->ctrl
);
253 ctrl
|= TOD_CTRL_PROTOCOL
| TOD_CTRL_ENABLE
;
254 ctrl
&= ~(TOD_CTRL_DISABLE_FMT_A
| TOD_CTRL_DISABLE_FMT_B
);
255 iowrite32(ctrl
, &bp
->tod
->ctrl
);
257 ctrl
= ioread32(&bp
->tod
->ctrl
);
258 idx
= ctrl
& TOD_CTRL_PROTOCOL
? 4 : 0;
259 idx
+= (ctrl
>> 16) & 3;
260 dev_info(&bp
->pdev
->dev
, "control: %x\n", ctrl
);
261 dev_info(&bp
->pdev
->dev
, "TOD Protocol %s %s\n", proto_name
[idx
],
262 ctrl
& TOD_CTRL_ENABLE
? "enabled" : "");
264 idx
= (ctrl
>> TOD_CTRL_GNSS_SHIFT
) & TOD_CTRL_GNSS_MASK
;
265 if (idx
< ARRAY_SIZE(gnss_name
))
266 dev_info(&bp
->pdev
->dev
, "GNSS %s\n", gnss_name
[idx
]);
268 reg
= ioread32(&bp
->tod
->status
);
269 dev_info(&bp
->pdev
->dev
, "status: %x\n", reg
);
271 reg
= ioread32(&bp
->tod
->correction_sec
);
272 dev_info(&bp
->pdev
->dev
, "correction: %d\n", reg
);
274 reg
= ioread32(&bp
->tod
->utc_status
);
275 dev_info(&bp
->pdev
->dev
, "utc_status: %x\n", reg
);
276 dev_info(&bp
->pdev
->dev
, "utc_offset: %d valid:%d leap_valid:%d\n",
277 reg
& TOD_STATUS_UTC_MASK
, reg
& TOD_STATUS_UTC_VALID
? 1 : 0,
278 reg
& TOD_STATUS_LEAP_VALID
? 1 : 0);
282 ptp_ocp_info(struct ptp_ocp
*bp
)
284 static const char * const clock_name
[] = {
285 "NO", "TOD", "IRIG", "PPS", "PTP", "RTC", "REGS", "EXT"
289 version
= ioread32(&bp
->reg
->version
);
290 select
= ioread32(&bp
->reg
->select
);
291 dev_info(&bp
->pdev
->dev
, "Version %d.%d.%d, clock %s, device ptp%d\n",
292 version
>> 24, (version
>> 16) & 0xff, version
& 0xffff,
293 clock_name
[select
& 7],
294 ptp_clock_index(bp
->ptp
));
296 ptp_ocp_tod_info(bp
);
300 ptp_ocp_probe(struct pci_dev
*pdev
, const struct pci_device_id
*id
)
305 bp
= kzalloc(sizeof(*bp
), GFP_KERNEL
);
309 pci_set_drvdata(pdev
, bp
);
311 err
= pci_enable_device(pdev
);
313 dev_err(&pdev
->dev
, "pci_enable_device\n");
317 err
= pci_request_regions(pdev
, KBUILD_MODNAME
);
319 dev_err(&pdev
->dev
, "pci_request_region\n");
323 bp
->base
= pci_ioremap_bar(pdev
, 0);
325 dev_err(&pdev
->dev
, "io_remap bar0\n");
329 bp
->reg
= bp
->base
+ OCP_REGISTER_OFFSET
;
330 bp
->tod
= bp
->base
+ TOD_REGISTER_OFFSET
;
331 bp
->ptp_info
= ptp_ocp_clock_info
;
332 spin_lock_init(&bp
->lock
);
334 err
= ptp_ocp_check_clock(bp
);
338 bp
->ptp
= ptp_clock_register(&bp
->ptp_info
, &pdev
->dev
);
339 if (IS_ERR(bp
->ptp
)) {
340 dev_err(&pdev
->dev
, "ptp_clock_register\n");
341 err
= PTR_ERR(bp
->ptp
);
350 pci_release_regions(pdev
);
352 pci_disable_device(pdev
);
360 ptp_ocp_remove(struct pci_dev
*pdev
)
362 struct ptp_ocp
*bp
= pci_get_drvdata(pdev
);
364 ptp_clock_unregister(bp
->ptp
);
365 pci_iounmap(pdev
, bp
->base
);
366 pci_release_regions(pdev
);
367 pci_disable_device(pdev
);
368 pci_set_drvdata(pdev
, NULL
);
372 static struct pci_driver ptp_ocp_driver
= {
373 .name
= KBUILD_MODNAME
,
374 .id_table
= ptp_ocp_pcidev_id
,
375 .probe
= ptp_ocp_probe
,
376 .remove
= ptp_ocp_remove
,
384 err
= pci_register_driver(&ptp_ocp_driver
);
391 pci_unregister_driver(&ptp_ocp_driver
);
394 module_init(ptp_ocp_init
);
395 module_exit(ptp_ocp_fini
);
397 MODULE_DESCRIPTION("OpenCompute TimeCard driver");
398 MODULE_LICENSE("GPL v2");