forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/drivers/ptp/ptp_chardev.c
....@@ -1,21 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * PTP 1588 clock support - character device implementation.
34 *
45 * Copyright (C) 2010 OMICRON electronics GmbH
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License as published by
8
- * the Free Software Foundation; either version 2 of the License, or
9
- * (at your option) any later version.
10
- *
11
- * This program is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- * GNU General Public License for more details.
15
- *
16
- * You should have received a copy of the GNU General Public License
17
- * along with this program; if not, write to the Free Software
18
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
196 */
207 #include <linux/module.h>
218 #include <linux/posix-clock.h>
....@@ -121,23 +108,27 @@
121108
122109 long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
123110 {
124
- struct ptp_clock_caps caps;
125
- struct ptp_clock_request req;
126
- struct ptp_sys_offset *sysoff = NULL;
127
- struct ptp_sys_offset_precise precise_offset;
128
- struct ptp_pin_desc pd;
129111 struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
130
- struct ptp_clock_info *ops = ptp->info;
131
- struct ptp_clock_time *pct;
132
- struct timespec64 ts;
112
+ struct ptp_sys_offset_extended *extoff = NULL;
113
+ struct ptp_sys_offset_precise precise_offset;
133114 struct system_device_crosststamp xtstamp;
134
- int enable, err = 0;
115
+ struct ptp_clock_info *ops = ptp->info;
116
+ struct ptp_sys_offset *sysoff = NULL;
117
+ struct ptp_system_timestamp sts;
118
+ struct ptp_clock_request req;
119
+ struct ptp_clock_caps caps;
120
+ struct ptp_clock_time *pct;
135121 unsigned int i, pin_index;
122
+ struct ptp_pin_desc pd;
123
+ struct timespec64 ts;
124
+ int enable, err = 0;
136125
137126 switch (cmd) {
138127
139128 case PTP_CLOCK_GETCAPS:
129
+ case PTP_CLOCK_GETCAPS2:
140130 memset(&caps, 0, sizeof(caps));
131
+
141132 caps.max_adj = ptp->info->max_adj;
142133 caps.n_alarm = ptp->info->n_alarm;
143134 caps.n_ext_ts = ptp->info->n_ext_ts;
....@@ -145,15 +136,39 @@
145136 caps.pps = ptp->info->pps;
146137 caps.n_pins = ptp->info->n_pins;
147138 caps.cross_timestamping = ptp->info->getcrosststamp != NULL;
139
+ caps.adjust_phase = ptp->info->adjphase != NULL;
148140 if (copy_to_user((void __user *)arg, &caps, sizeof(caps)))
149141 err = -EFAULT;
150142 break;
151143
152144 case PTP_EXTTS_REQUEST:
145
+ case PTP_EXTTS_REQUEST2:
146
+ memset(&req, 0, sizeof(req));
147
+
153148 if (copy_from_user(&req.extts, (void __user *)arg,
154149 sizeof(req.extts))) {
155150 err = -EFAULT;
156151 break;
152
+ }
153
+ if (cmd == PTP_EXTTS_REQUEST2) {
154
+ /* Tell the drivers to check the flags carefully. */
155
+ req.extts.flags |= PTP_STRICT_FLAGS;
156
+ /* Make sure no reserved bit is set. */
157
+ if ((req.extts.flags & ~PTP_EXTTS_VALID_FLAGS) ||
158
+ req.extts.rsv[0] || req.extts.rsv[1]) {
159
+ err = -EINVAL;
160
+ break;
161
+ }
162
+ /* Ensure one of the rising/falling edge bits is set. */
163
+ if ((req.extts.flags & PTP_ENABLE_FEATURE) &&
164
+ (req.extts.flags & PTP_EXTTS_EDGES) == 0) {
165
+ err = -EINVAL;
166
+ break;
167
+ }
168
+ } else if (cmd == PTP_EXTTS_REQUEST) {
169
+ req.extts.flags &= PTP_EXTTS_V1_VALID_FLAGS;
170
+ req.extts.rsv[0] = 0;
171
+ req.extts.rsv[1] = 0;
157172 }
158173 if (req.extts.index >= ops->n_ext_ts) {
159174 err = -EINVAL;
....@@ -161,14 +176,67 @@
161176 }
162177 req.type = PTP_CLK_REQ_EXTTS;
163178 enable = req.extts.flags & PTP_ENABLE_FEATURE ? 1 : 0;
179
+ if (mutex_lock_interruptible(&ptp->pincfg_mux))
180
+ return -ERESTARTSYS;
164181 err = ops->enable(ops, &req, enable);
182
+ mutex_unlock(&ptp->pincfg_mux);
165183 break;
166184
167185 case PTP_PEROUT_REQUEST:
186
+ case PTP_PEROUT_REQUEST2:
187
+ memset(&req, 0, sizeof(req));
188
+
168189 if (copy_from_user(&req.perout, (void __user *)arg,
169190 sizeof(req.perout))) {
170191 err = -EFAULT;
171192 break;
193
+ }
194
+ if (cmd == PTP_PEROUT_REQUEST2) {
195
+ struct ptp_perout_request *perout = &req.perout;
196
+
197
+ if (perout->flags & ~PTP_PEROUT_VALID_FLAGS) {
198
+ err = -EINVAL;
199
+ break;
200
+ }
201
+ /*
202
+ * The "on" field has undefined meaning if
203
+ * PTP_PEROUT_DUTY_CYCLE isn't set, we must still treat
204
+ * it as reserved, which must be set to zero.
205
+ */
206
+ if (!(perout->flags & PTP_PEROUT_DUTY_CYCLE) &&
207
+ (perout->rsv[0] || perout->rsv[1] ||
208
+ perout->rsv[2] || perout->rsv[3])) {
209
+ err = -EINVAL;
210
+ break;
211
+ }
212
+ if (perout->flags & PTP_PEROUT_DUTY_CYCLE) {
213
+ /* The duty cycle must be subunitary. */
214
+ if (perout->on.sec > perout->period.sec ||
215
+ (perout->on.sec == perout->period.sec &&
216
+ perout->on.nsec > perout->period.nsec)) {
217
+ err = -ERANGE;
218
+ break;
219
+ }
220
+ }
221
+ if (perout->flags & PTP_PEROUT_PHASE) {
222
+ /*
223
+ * The phase should be specified modulo the
224
+ * period, therefore anything equal or larger
225
+ * than 1 period is invalid.
226
+ */
227
+ if (perout->phase.sec > perout->period.sec ||
228
+ (perout->phase.sec == perout->period.sec &&
229
+ perout->phase.nsec >= perout->period.nsec)) {
230
+ err = -ERANGE;
231
+ break;
232
+ }
233
+ }
234
+ } else if (cmd == PTP_PEROUT_REQUEST) {
235
+ req.perout.flags &= PTP_PEROUT_V1_VALID_FLAGS;
236
+ req.perout.rsv[0] = 0;
237
+ req.perout.rsv[1] = 0;
238
+ req.perout.rsv[2] = 0;
239
+ req.perout.rsv[3] = 0;
172240 }
173241 if (req.perout.index >= ops->n_per_out) {
174242 err = -EINVAL;
....@@ -176,18 +244,28 @@
176244 }
177245 req.type = PTP_CLK_REQ_PEROUT;
178246 enable = req.perout.period.sec || req.perout.period.nsec;
247
+ if (mutex_lock_interruptible(&ptp->pincfg_mux))
248
+ return -ERESTARTSYS;
179249 err = ops->enable(ops, &req, enable);
250
+ mutex_unlock(&ptp->pincfg_mux);
180251 break;
181252
182253 case PTP_ENABLE_PPS:
254
+ case PTP_ENABLE_PPS2:
255
+ memset(&req, 0, sizeof(req));
256
+
183257 if (!capable(CAP_SYS_TIME))
184258 return -EPERM;
185259 req.type = PTP_CLK_REQ_PPS;
186260 enable = arg ? 1 : 0;
261
+ if (mutex_lock_interruptible(&ptp->pincfg_mux))
262
+ return -ERESTARTSYS;
187263 err = ops->enable(ops, &req, enable);
264
+ mutex_unlock(&ptp->pincfg_mux);
188265 break;
189266
190267 case PTP_SYS_OFFSET_PRECISE:
268
+ case PTP_SYS_OFFSET_PRECISE2:
191269 if (!ptp->info->getcrosststamp) {
192270 err = -EOPNOTSUPP;
193271 break;
....@@ -211,7 +289,40 @@
211289 err = -EFAULT;
212290 break;
213291
292
+ case PTP_SYS_OFFSET_EXTENDED:
293
+ case PTP_SYS_OFFSET_EXTENDED2:
294
+ if (!ptp->info->gettimex64) {
295
+ err = -EOPNOTSUPP;
296
+ break;
297
+ }
298
+ extoff = memdup_user((void __user *)arg, sizeof(*extoff));
299
+ if (IS_ERR(extoff)) {
300
+ err = PTR_ERR(extoff);
301
+ extoff = NULL;
302
+ break;
303
+ }
304
+ if (extoff->n_samples > PTP_MAX_SAMPLES
305
+ || extoff->rsv[0] || extoff->rsv[1] || extoff->rsv[2]) {
306
+ err = -EINVAL;
307
+ break;
308
+ }
309
+ for (i = 0; i < extoff->n_samples; i++) {
310
+ err = ptp->info->gettimex64(ptp->info, &ts, &sts);
311
+ if (err)
312
+ goto out;
313
+ extoff->ts[i][0].sec = sts.pre_ts.tv_sec;
314
+ extoff->ts[i][0].nsec = sts.pre_ts.tv_nsec;
315
+ extoff->ts[i][1].sec = ts.tv_sec;
316
+ extoff->ts[i][1].nsec = ts.tv_nsec;
317
+ extoff->ts[i][2].sec = sts.post_ts.tv_sec;
318
+ extoff->ts[i][2].nsec = sts.post_ts.tv_nsec;
319
+ }
320
+ if (copy_to_user((void __user *)arg, extoff, sizeof(*extoff)))
321
+ err = -EFAULT;
322
+ break;
323
+
214324 case PTP_SYS_OFFSET:
325
+ case PTP_SYS_OFFSET2:
215326 sysoff = memdup_user((void __user *)arg, sizeof(*sysoff));
216327 if (IS_ERR(sysoff)) {
217328 err = PTR_ERR(sysoff);
....@@ -228,7 +339,10 @@
228339 pct->sec = ts.tv_sec;
229340 pct->nsec = ts.tv_nsec;
230341 pct++;
231
- err = ptp->info->gettime64(ptp->info, &ts);
342
+ if (ops->gettimex64)
343
+ err = ops->gettimex64(ops, &ts, NULL);
344
+ else
345
+ err = ops->gettime64(ops, &ts);
232346 if (err)
233347 goto out;
234348 pct->sec = ts.tv_sec;
....@@ -243,9 +357,22 @@
243357 break;
244358
245359 case PTP_PIN_GETFUNC:
360
+ case PTP_PIN_GETFUNC2:
246361 if (copy_from_user(&pd, (void __user *)arg, sizeof(pd))) {
247362 err = -EFAULT;
248363 break;
364
+ }
365
+ if ((pd.rsv[0] || pd.rsv[1] || pd.rsv[2]
366
+ || pd.rsv[3] || pd.rsv[4])
367
+ && cmd == PTP_PIN_GETFUNC2) {
368
+ err = -EINVAL;
369
+ break;
370
+ } else if (cmd == PTP_PIN_GETFUNC) {
371
+ pd.rsv[0] = 0;
372
+ pd.rsv[1] = 0;
373
+ pd.rsv[2] = 0;
374
+ pd.rsv[3] = 0;
375
+ pd.rsv[4] = 0;
249376 }
250377 pin_index = pd.index;
251378 if (pin_index >= ops->n_pins) {
....@@ -262,9 +389,22 @@
262389 break;
263390
264391 case PTP_PIN_SETFUNC:
392
+ case PTP_PIN_SETFUNC2:
265393 if (copy_from_user(&pd, (void __user *)arg, sizeof(pd))) {
266394 err = -EFAULT;
267395 break;
396
+ }
397
+ if ((pd.rsv[0] || pd.rsv[1] || pd.rsv[2]
398
+ || pd.rsv[3] || pd.rsv[4])
399
+ && cmd == PTP_PIN_SETFUNC2) {
400
+ err = -EINVAL;
401
+ break;
402
+ } else if (cmd == PTP_PIN_SETFUNC) {
403
+ pd.rsv[0] = 0;
404
+ pd.rsv[1] = 0;
405
+ pd.rsv[2] = 0;
406
+ pd.rsv[3] = 0;
407
+ pd.rsv[4] = 0;
268408 }
269409 pin_index = pd.index;
270410 if (pin_index >= ops->n_pins) {
....@@ -284,6 +424,7 @@
284424 }
285425
286426 out:
427
+ kfree(extoff);
287428 kfree(sysoff);
288429 return err;
289430 }