Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ptp: add debugfs interfaces to loop back the periodic output signal

For some PTP devices, they have the capability to loop back the periodic
output signal for debugging, such as the ptp_qoriq device. So add the
generic interfaces to set the periodic output signal loopback, rather
than each vendor having a different implementation.

Show how many channels support the periodic output signal loopback:
$ cat /sys/kernel/debug/ptp<N>/n_perout_loopback

Enable the loopback of the periodic output signal of channel X:
$ echo <X> 1 > /sys/kernel/debug/ptp<N>/perout_loopback

Disable the loopback of the periodic output signal of channel X:
$ echo <X> 0 > /sys/kernel/debug/ptp<N>/perout_loopback

Suggested-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Wei Fang <wei.fang@nxp.com>
Link: https://patch.msgid.link/20250905030711.1509648-2-wei.fang@nxp.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Wei Fang and committed by
Jakub Kicinski
e096a7cc cf71bdf6

+79
+69
drivers/ptp/ptp_clock.c
··· 248 248 kthread_queue_delayed_work(ptp->kworker, &ptp->aux_work, delay); 249 249 } 250 250 251 + static ssize_t ptp_n_perout_loopback_read(struct file *filep, 252 + char __user *buffer, 253 + size_t count, loff_t *pos) 254 + { 255 + struct ptp_clock *ptp = filep->private_data; 256 + char buf[12] = {}; 257 + 258 + snprintf(buf, sizeof(buf), "%d\n", ptp->info->n_per_lp); 259 + 260 + return simple_read_from_buffer(buffer, count, pos, buf, strlen(buf)); 261 + } 262 + 263 + static const struct file_operations ptp_n_perout_loopback_fops = { 264 + .owner = THIS_MODULE, 265 + .open = simple_open, 266 + .read = ptp_n_perout_loopback_read, 267 + }; 268 + 269 + static ssize_t ptp_perout_loopback_write(struct file *filep, 270 + const char __user *buffer, 271 + size_t count, loff_t *ppos) 272 + { 273 + struct ptp_clock *ptp = filep->private_data; 274 + struct ptp_clock_info *ops = ptp->info; 275 + unsigned int index, enable; 276 + int len, cnt, err; 277 + char buf[32] = {}; 278 + 279 + if (*ppos || !count) 280 + return -EINVAL; 281 + 282 + if (count >= sizeof(buf)) 283 + return -ENOSPC; 284 + 285 + len = simple_write_to_buffer(buf, sizeof(buf) - 1, 286 + ppos, buffer, count); 287 + if (len < 0) 288 + return len; 289 + 290 + buf[len] = '\0'; 291 + cnt = sscanf(buf, "%u %u", &index, &enable); 292 + if (cnt != 2) 293 + return -EINVAL; 294 + 295 + if (index >= ops->n_per_lp) 296 + return -EINVAL; 297 + 298 + if (enable != 0 && enable != 1) 299 + return -EINVAL; 300 + 301 + err = ops->perout_loopback(ops, index, enable); 302 + if (err) 303 + return err; 304 + 305 + return count; 306 + } 307 + 308 + static const struct file_operations ptp_perout_loopback_ops = { 309 + .owner = THIS_MODULE, 310 + .open = simple_open, 311 + .write = ptp_perout_loopback_write, 312 + }; 313 + 251 314 /* public interface */ 252 315 253 316 struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info, ··· 452 389 /* Debugfs initialization */ 453 390 snprintf(debugfsname, sizeof(debugfsname), "ptp%d", ptp->index); 454 391 ptp->debugfs_root = debugfs_create_dir(debugfsname, NULL); 392 + if (info->n_per_lp > 0 && info->perout_loopback) { 393 + debugfs_create_file("n_perout_loopback", 0400, ptp->debugfs_root, 394 + ptp, &ptp_n_perout_loopback_fops); 395 + debugfs_create_file("perout_loopback", 0200, ptp->debugfs_root, 396 + ptp, &ptp_perout_loopback_ops); 397 + } 455 398 456 399 return ptp; 457 400
+10
include/linux/ptp_clock_kernel.h
··· 67 67 * @n_ext_ts: The number of external time stamp channels. 68 68 * @n_per_out: The number of programmable periodic signals. 69 69 * @n_pins: The number of programmable pins. 70 + * @n_per_lp: The number of channels that support loopback the periodic 71 + * output signal. 70 72 * @pps: Indicates whether the clock supports a PPS callback. 71 73 * 72 74 * @supported_perout_flags: The set of flags the driver supports for the ··· 177 175 * scheduling time (>=0) or negative value in case further 178 176 * scheduling is not required. 179 177 * 178 + * @perout_loopback: Request driver to enable or disable the periodic output 179 + * signal loopback. 180 + * parameter index: index of the periodic output signal channel. 181 + * parameter on: caller passes one to enable or zero to disable. 182 + * 180 183 * Drivers should embed their ptp_clock_info within a private 181 184 * structure, obtaining a reference to it using container_of(). 182 185 * ··· 196 189 int n_ext_ts; 197 190 int n_per_out; 198 191 int n_pins; 192 + int n_per_lp; 199 193 int pps; 200 194 unsigned int supported_perout_flags; 201 195 unsigned int supported_extts_flags; ··· 221 213 int (*verify)(struct ptp_clock_info *ptp, unsigned int pin, 222 214 enum ptp_pin_function func, unsigned int chan); 223 215 long (*do_aux_work)(struct ptp_clock_info *ptp); 216 + int (*perout_loopback)(struct ptp_clock_info *ptp, unsigned int index, 217 + int on); 224 218 }; 225 219 226 220 struct ptp_clock;