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