xref: /linux/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c (revision 32daa5d7899e03433429bedf9e20d7963179703a)
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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