1 // SPDX-License-Identifier: GPL-2.0
2 /* Marvell OcteonTx2 PTP support for ethernet driver
3 *
4 * Copyright (C) 2020 Marvell International Ltd.
5 */
6
7 #include "otx2_common.h"
8 #include "otx2_ptp.h"
9
otx2_ptp_adjfine(struct ptp_clock_info * ptp_info,long scaled_ppm)10 static int otx2_ptp_adjfine(struct ptp_clock_info *ptp_info, long scaled_ppm)
11 {
12 struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
13 ptp_info);
14 struct ptp_req *req;
15
16 if (!ptp->nic)
17 return -ENODEV;
18
19 req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
20 if (!req)
21 return -ENOMEM;
22
23 req->op = PTP_OP_ADJFINE;
24 req->scaled_ppm = scaled_ppm;
25
26 return otx2_sync_mbox_msg(&ptp->nic->mbox);
27 }
28
ptp_cc_read(const struct cyclecounter * cc)29 static u64 ptp_cc_read(const struct cyclecounter *cc)
30 {
31 struct otx2_ptp *ptp = container_of(cc, struct otx2_ptp, cycle_counter);
32 struct ptp_req *req;
33 struct ptp_rsp *rsp;
34 int err;
35
36 if (!ptp->nic)
37 return 0;
38
39 req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox);
40 if (!req)
41 return 0;
42
43 req->op = PTP_OP_GET_CLOCK;
44
45 err = otx2_sync_mbox_msg(&ptp->nic->mbox);
46 if (err)
47 return 0;
48
49 rsp = (struct ptp_rsp *)otx2_mbox_get_rsp(&ptp->nic->mbox.mbox, 0,
50 &req->hdr);
51 if (IS_ERR(rsp))
52 return 0;
53
54 return rsp->clk;
55 }
56
otx2_ptp_adjtime(struct ptp_clock_info * ptp_info,s64 delta)57 static int otx2_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta)
58 {
59 struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
60 ptp_info);
61 struct otx2_nic *pfvf = ptp->nic;
62
63 mutex_lock(&pfvf->mbox.lock);
64 timecounter_adjtime(&ptp->time_counter, delta);
65 mutex_unlock(&pfvf->mbox.lock);
66
67 return 0;
68 }
69
otx2_ptp_gettime(struct ptp_clock_info * ptp_info,struct timespec64 * ts)70 static int otx2_ptp_gettime(struct ptp_clock_info *ptp_info,
71 struct timespec64 *ts)
72 {
73 struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
74 ptp_info);
75 struct otx2_nic *pfvf = ptp->nic;
76 u64 nsec;
77
78 mutex_lock(&pfvf->mbox.lock);
79 nsec = timecounter_read(&ptp->time_counter);
80 mutex_unlock(&pfvf->mbox.lock);
81
82 *ts = ns_to_timespec64(nsec);
83
84 return 0;
85 }
86
otx2_ptp_settime(struct ptp_clock_info * ptp_info,const struct timespec64 * ts)87 static int otx2_ptp_settime(struct ptp_clock_info *ptp_info,
88 const struct timespec64 *ts)
89 {
90 struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp,
91 ptp_info);
92 struct otx2_nic *pfvf = ptp->nic;
93 u64 nsec;
94
95 nsec = timespec64_to_ns(ts);
96
97 mutex_lock(&pfvf->mbox.lock);
98 timecounter_init(&ptp->time_counter, &ptp->cycle_counter, nsec);
99 mutex_unlock(&pfvf->mbox.lock);
100
101 return 0;
102 }
103
otx2_ptp_enable(struct ptp_clock_info * ptp_info,struct ptp_clock_request * rq,int on)104 static int otx2_ptp_enable(struct ptp_clock_info *ptp_info,
105 struct ptp_clock_request *rq, int on)
106 {
107 return -EOPNOTSUPP;
108 }
109
otx2_ptp_init(struct otx2_nic * pfvf)110 int otx2_ptp_init(struct otx2_nic *pfvf)
111 {
112 struct otx2_ptp *ptp_ptr;
113 struct cyclecounter *cc;
114 struct ptp_req *req;
115 int err;
116
117 mutex_lock(&pfvf->mbox.lock);
118 /* check if PTP block is available */
119 req = otx2_mbox_alloc_msg_ptp_op(&pfvf->mbox);
120 if (!req) {
121 mutex_unlock(&pfvf->mbox.lock);
122 return -ENOMEM;
123 }
124
125 req->op = PTP_OP_GET_CLOCK;
126
127 err = otx2_sync_mbox_msg(&pfvf->mbox);
128 if (err) {
129 mutex_unlock(&pfvf->mbox.lock);
130 return err;
131 }
132 mutex_unlock(&pfvf->mbox.lock);
133
134 ptp_ptr = kzalloc(sizeof(*ptp_ptr), GFP_KERNEL);
135 if (!ptp_ptr) {
136 err = -ENOMEM;
137 goto error;
138 }
139
140 ptp_ptr->nic = pfvf;
141
142 cc = &ptp_ptr->cycle_counter;
143 cc->read = ptp_cc_read;
144 cc->mask = CYCLECOUNTER_MASK(64);
145 cc->mult = 1;
146 cc->shift = 0;
147
148 timecounter_init(&ptp_ptr->time_counter, &ptp_ptr->cycle_counter,
149 ktime_to_ns(ktime_get_real()));
150
151 ptp_ptr->ptp_info = (struct ptp_clock_info) {
152 .owner = THIS_MODULE,
153 .name = "OcteonTX2 PTP",
154 .max_adj = 1000000000ull,
155 .n_ext_ts = 0,
156 .n_pins = 0,
157 .pps = 0,
158 .adjfine = otx2_ptp_adjfine,
159 .adjtime = otx2_ptp_adjtime,
160 .gettime64 = otx2_ptp_gettime,
161 .settime64 = otx2_ptp_settime,
162 .enable = otx2_ptp_enable,
163 };
164
165 ptp_ptr->ptp_clock = ptp_clock_register(&ptp_ptr->ptp_info, pfvf->dev);
166 if (IS_ERR_OR_NULL(ptp_ptr->ptp_clock)) {
167 err = ptp_ptr->ptp_clock ?
168 PTR_ERR(ptp_ptr->ptp_clock) : -ENODEV;
169 kfree(ptp_ptr);
170 goto error;
171 }
172
173 pfvf->ptp = ptp_ptr;
174
175 error:
176 return err;
177 }
178
otx2_ptp_destroy(struct otx2_nic * pfvf)179 void otx2_ptp_destroy(struct otx2_nic *pfvf)
180 {
181 struct otx2_ptp *ptp = pfvf->ptp;
182
183 if (!ptp)
184 return;
185
186 ptp_clock_unregister(ptp->ptp_clock);
187 kfree(ptp);
188 pfvf->ptp = NULL;
189 }
190
otx2_ptp_clock_index(struct otx2_nic * pfvf)191 int otx2_ptp_clock_index(struct otx2_nic *pfvf)
192 {
193 if (!pfvf->ptp)
194 return -ENODEV;
195
196 return ptp_clock_index(pfvf->ptp->ptp_clock);
197 }
198
otx2_ptp_tstamp2time(struct otx2_nic * pfvf,u64 tstamp,u64 * tsns)199 int otx2_ptp_tstamp2time(struct otx2_nic *pfvf, u64 tstamp, u64 *tsns)
200 {
201 if (!pfvf->ptp)
202 return -ENODEV;
203
204 *tsns = timecounter_cyc2time(&pfvf->ptp->time_counter, tstamp);
205
206 return 0;
207 }
208