1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * s390 PTP clock driver
7 #include "ptp_private.h"
8 #include <linux/time.h>
11 static struct ptp_clock
*ptp_stcke_clock
, *ptp_qpt_clock
;
13 static int ptp_s390_adjfine(struct ptp_clock_info
*ptp
, long scaled_ppm
)
18 static int ptp_s390_adjtime(struct ptp_clock_info
*ptp
, s64 delta
)
23 static struct timespec64
eitod_to_timespec64(union tod_clock
*clk
)
25 return ns_to_timespec64(eitod_to_ns(clk
->eitod
- TOD_UNIX_EPOCH
));
28 static struct timespec64
tod_to_timespec64(unsigned long tod
)
30 return ns_to_timespec64(tod_to_ns(tod
- TOD_UNIX_EPOCH
));
33 static int ptp_s390_stcke_gettime(struct ptp_clock_info
*ptp
,
34 struct timespec64
*ts
)
41 store_tod_clock_ext(&tod
);
42 *ts
= eitod_to_timespec64(&tod
);
46 static int ptp_s390_qpt_gettime(struct ptp_clock_info
*ptp
,
47 struct timespec64
*ts
)
51 ptff(&tod
, sizeof(tod
), PTFF_QPT
);
52 *ts
= tod_to_timespec64(tod
);
56 static int ptp_s390_settime(struct ptp_clock_info
*ptp
,
57 const struct timespec64
*ts
)
62 static int s390_arch_ptp_get_crosststamp(ktime_t
*device_time
,
63 struct system_counterval_t
*system_counter
,
68 store_tod_clock_ext(&clk
);
69 *device_time
= ns_to_ktime(tod_to_ns(clk
.tod
- TOD_UNIX_EPOCH
));
70 system_counter
->cycles
= clk
.tod
;
71 system_counter
->cs_id
= CSID_S390_TOD
;
75 static int ptp_s390_getcrosststamp(struct ptp_clock_info
*ptp
,
76 struct system_device_crosststamp
*xtstamp
)
80 return get_device_system_crosststamp(s390_arch_ptp_get_crosststamp
, NULL
, NULL
, xtstamp
);
83 static struct ptp_clock_info ptp_s390_stcke_info
= {
85 .name
= "s390 STCKE Clock",
87 .adjfine
= ptp_s390_adjfine
,
88 .adjtime
= ptp_s390_adjtime
,
89 .gettime64
= ptp_s390_stcke_gettime
,
90 .settime64
= ptp_s390_settime
,
91 .getcrosststamp
= ptp_s390_getcrosststamp
,
94 static struct ptp_clock_info ptp_s390_qpt_info
= {
96 .name
= "s390 Physical Clock",
98 .adjfine
= ptp_s390_adjfine
,
99 .adjtime
= ptp_s390_adjtime
,
100 .gettime64
= ptp_s390_qpt_gettime
,
101 .settime64
= ptp_s390_settime
,
104 static __init
int ptp_s390_init(void)
106 ptp_stcke_clock
= ptp_clock_register(&ptp_s390_stcke_info
, NULL
);
107 if (IS_ERR(ptp_stcke_clock
))
108 return PTR_ERR(ptp_stcke_clock
);
110 ptp_qpt_clock
= ptp_clock_register(&ptp_s390_qpt_info
, NULL
);
111 if (IS_ERR(ptp_qpt_clock
)) {
112 ptp_clock_unregister(ptp_stcke_clock
);
113 return PTR_ERR(ptp_qpt_clock
);
118 static __exit
void ptp_s390_exit(void)
120 ptp_clock_unregister(ptp_qpt_clock
);
121 ptp_clock_unregister(ptp_stcke_clock
);
124 module_init(ptp_s390_init
);
125 module_exit(ptp_s390_exit
);
127 MODULE_AUTHOR("Sven Schnelle <svens@linux.ibm.com>");
128 MODULE_DESCRIPTION("s390 Physical/STCKE Clock PtP Driver");
129 MODULE_LICENSE("GPL");