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.

net: dsa: mv88e6xxx: Enable PTP receive for mv88e6390

The switch receives management traffic such as STP and LLDP. However, PTP
messages are not received, only transmitted.

Ideally, the switch would trap all PTP messages to the management CPU. This
particular switch has a PTP block which identifies PTP messages and traps them
to a dedicated port. There is a register to program this destination. This is
not used at the moment.

Therefore, program it to the same port as the MGMT traffic is trapped to. This
allows to receive PTP messages as soon as timestamping is enabled.

In addition, the datasheet mentions that this register is not valid e.g., for
6190 variants. So, add a new PTP operation which is added for the 6390 and 6290
devices.

Tested simply like this on Marvell 88E6390, revision 1:

|/ # ptp4l -2 -i lan4 --tx_timestamp_timeout=40 -m
|[...]
|ptp4l[147.450]: master offset 56 s2 freq +1262 path delay 413
|ptp4l[148.450]: master offset 22 s2 freq +1244 path delay 434
|ptp4l[149.450]: master offset 5 s2 freq +1234 path delay 446
|ptp4l[150.451]: master offset 3 s2 freq +1233 path delay 451
|ptp4l[151.451]: master offset 1 s2 freq +1232 path delay 451
|ptp4l[152.451]: master offset -3 s2 freq +1229 path delay 451
|ptp4l[153.451]: master offset 9 s2 freq +1240 path delay 451

Link: https://lore.kernel.org/r/CAFSKS=PJBpvtRJxrR4sG1hyxpnUnQpiHg4SrUNzAhkWnyt9ivg@mail.gmail.com
Signed-off-by: Kurt Kanzenbach <kurt@linutronix.de>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Vladimir Oltean <olteanv@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Kurt Kanzenbach and committed by
David S. Miller
9627c981 71dc9ec9

+66 -3
+3 -3
drivers/net/dsa/mv88e6xxx/chip.c
··· 5082 5082 .serdes_get_regs = mv88e6390_serdes_get_regs, 5083 5083 .gpio_ops = &mv88e6352_gpio_ops, 5084 5084 .avb_ops = &mv88e6390_avb_ops, 5085 - .ptp_ops = &mv88e6352_ptp_ops, 5085 + .ptp_ops = &mv88e6390_ptp_ops, 5086 5086 .phylink_get_caps = mv88e6390_phylink_get_caps, 5087 5087 }; 5088 5088 ··· 5470 5470 .serdes_irq_status = mv88e6390_serdes_irq_status, 5471 5471 .gpio_ops = &mv88e6352_gpio_ops, 5472 5472 .avb_ops = &mv88e6390_avb_ops, 5473 - .ptp_ops = &mv88e6352_ptp_ops, 5473 + .ptp_ops = &mv88e6390_ptp_ops, 5474 5474 .serdes_get_sset_count = mv88e6390_serdes_get_sset_count, 5475 5475 .serdes_get_strings = mv88e6390_serdes_get_strings, 5476 5476 .serdes_get_stats = mv88e6390_serdes_get_stats, ··· 5543 5543 .serdes_get_regs = mv88e6390_serdes_get_regs, 5544 5544 .gpio_ops = &mv88e6352_gpio_ops, 5545 5545 .avb_ops = &mv88e6390_avb_ops, 5546 - .ptp_ops = &mv88e6352_ptp_ops, 5546 + .ptp_ops = &mv88e6390_ptp_ops, 5547 5547 .phylink_get_caps = mv88e6390x_phylink_get_caps, 5548 5548 }; 5549 5549
+1
drivers/net/dsa/mv88e6xxx/chip.h
··· 715 715 int (*port_disable)(struct mv88e6xxx_chip *chip, int port); 716 716 int (*global_enable)(struct mv88e6xxx_chip *chip); 717 717 int (*global_disable)(struct mv88e6xxx_chip *chip); 718 + int (*set_ptp_cpu_port)(struct mv88e6xxx_chip *chip, int port); 718 719 int n_ext_ts; 719 720 int arr0_sts_reg; 720 721 int arr1_sts_reg;
+12
drivers/net/dsa/mv88e6xxx/global1.c
··· 403 403 return mv88e6390_g1_monitor_write(chip, ptr, port); 404 404 } 405 405 406 + int mv88e6390_g1_set_ptp_cpu_port(struct mv88e6xxx_chip *chip, int port) 407 + { 408 + u16 ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_PTP_CPU_DEST; 409 + 410 + /* Use the default high priority for PTP frames sent to 411 + * the CPU. 412 + */ 413 + port |= MV88E6390_G1_MONITOR_MGMT_CTL_PTR_CPU_DEST_MGMTPRI; 414 + 415 + return mv88e6390_g1_monitor_write(chip, ptr, port); 416 + } 417 + 406 418 int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip) 407 419 { 408 420 u16 ptr;
+2
drivers/net/dsa/mv88e6xxx/global1.h
··· 214 214 #define MV88E6390_G1_MONITOR_MGMT_CTL_PTR_INGRESS_DEST 0x2000 215 215 #define MV88E6390_G1_MONITOR_MGMT_CTL_PTR_EGRESS_DEST 0x2100 216 216 #define MV88E6390_G1_MONITOR_MGMT_CTL_PTR_CPU_DEST 0x3000 217 + #define MV88E6390_G1_MONITOR_MGMT_CTL_PTR_PTP_CPU_DEST 0x3200 217 218 #define MV88E6390_G1_MONITOR_MGMT_CTL_PTR_CPU_DEST_MGMTPRI 0x00e0 218 219 #define MV88E6390_G1_MONITOR_MGMT_CTL_DATA_MASK 0x00ff 219 220 ··· 304 303 int port); 305 304 int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port); 306 305 int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port); 306 + int mv88e6390_g1_set_ptp_cpu_port(struct mv88e6xxx_chip *chip, int port); 307 307 int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip); 308 308 309 309 int mv88e6085_g1_ip_pri_map(struct mv88e6xxx_chip *chip);
+46
drivers/net/dsa/mv88e6xxx/ptp.c
··· 11 11 */ 12 12 13 13 #include "chip.h" 14 + #include "global1.h" 14 15 #include "global2.h" 15 16 #include "hwtstamp.h" 16 17 #include "ptp.h" ··· 420 419 .cc_mult_dem = MV88E6XXX_CC_MULT_DEM, 421 420 }; 422 421 422 + const struct mv88e6xxx_ptp_ops mv88e6390_ptp_ops = { 423 + .clock_read = mv88e6352_ptp_clock_read, 424 + .ptp_enable = mv88e6352_ptp_enable, 425 + .ptp_verify = mv88e6352_ptp_verify, 426 + .event_work = mv88e6352_tai_event_work, 427 + .port_enable = mv88e6352_hwtstamp_port_enable, 428 + .port_disable = mv88e6352_hwtstamp_port_disable, 429 + .set_ptp_cpu_port = mv88e6390_g1_set_ptp_cpu_port, 430 + .n_ext_ts = 1, 431 + .arr0_sts_reg = MV88E6XXX_PORT_PTP_ARR0_STS, 432 + .arr1_sts_reg = MV88E6XXX_PORT_PTP_ARR1_STS, 433 + .dep_sts_reg = MV88E6XXX_PORT_PTP_DEP_STS, 434 + .rx_filters = (1 << HWTSTAMP_FILTER_NONE) | 435 + (1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) | 436 + (1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) | 437 + (1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) | 438 + (1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) | 439 + (1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) | 440 + (1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) | 441 + (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) | 442 + (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) | 443 + (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ), 444 + .cc_shift = MV88E6XXX_CC_SHIFT, 445 + .cc_mult = MV88E6XXX_CC_MULT, 446 + .cc_mult_num = MV88E6XXX_CC_MULT_NUM, 447 + .cc_mult_dem = MV88E6XXX_CC_MULT_DEM, 448 + }; 449 + 423 450 static u64 mv88e6xxx_ptp_clock_read(const struct cyclecounter *cc) 424 451 { 425 452 struct mv88e6xxx_chip *chip = cc_to_chip(cc); ··· 519 490 chip->ptp_clock_info.enable = ptp_ops->ptp_enable; 520 491 chip->ptp_clock_info.verify = ptp_ops->ptp_verify; 521 492 chip->ptp_clock_info.do_aux_work = mv88e6xxx_hwtstamp_work; 493 + 494 + if (ptp_ops->set_ptp_cpu_port) { 495 + struct dsa_port *dp; 496 + int upstream = 0; 497 + int err; 498 + 499 + dsa_switch_for_each_user_port(dp, chip->ds) { 500 + upstream = dsa_upstream_port(chip->ds, dp->index); 501 + break; 502 + } 503 + 504 + err = ptp_ops->set_ptp_cpu_port(chip, upstream); 505 + if (err) { 506 + dev_err(chip->dev, "Failed to set PTP CPU destination port!\n"); 507 + return err; 508 + } 509 + } 522 510 523 511 chip->ptp_clock = ptp_clock_register(&chip->ptp_clock_info, chip->dev); 524 512 if (IS_ERR(chip->ptp_clock))
+2
drivers/net/dsa/mv88e6xxx/ptp.h
··· 151 151 extern const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops; 152 152 extern const struct mv88e6xxx_ptp_ops mv88e6250_ptp_ops; 153 153 extern const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops; 154 + extern const struct mv88e6xxx_ptp_ops mv88e6390_ptp_ops; 154 155 155 156 #else /* !CONFIG_NET_DSA_MV88E6XXX_PTP */ 156 157 ··· 172 171 static const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops = {}; 173 172 static const struct mv88e6xxx_ptp_ops mv88e6250_ptp_ops = {}; 174 173 static const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {}; 174 + static const struct mv88e6xxx_ptp_ops mv88e6390_ptp_ops = {}; 175 175 176 176 #endif /* CONFIG_NET_DSA_MV88E6XXX_PTP */ 177 177