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

net: dsa: microchip: ptp: enable interrupt for timestamping

PTP Interrupt mask and status register differ from the global and port
interrupt mechanism by two methods. One is that for global/port
interrupt enabling we have to clear the bit but for ptp interrupt we
have to set the bit. And other is bit12:0 is reserved in ptp interrupt
registers. This forced to not use the generic implementation of
global/port interrupt method routine. This patch implement the ptp
interrupt mechanism to read the timestamp register for sync, pdelay_req
and pdelay_resp.

Signed-off-by: Arun Ramadoss <arun.ramadoss@microchip.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Arun Ramadoss and committed by
David S. Miller
cc13ab18 bb01ad30

+259 -2
+13 -2
drivers/net/dsa/microchip/ksz_common.c
··· 2100 2100 ret = ksz_pirq_setup(dev, dp->index); 2101 2101 if (ret) 2102 2102 goto out_girq; 2103 + 2104 + ret = ksz_ptp_irq_setup(ds, dp->index); 2105 + if (ret) 2106 + goto out_pirq; 2103 2107 } 2104 2108 } 2105 2109 2106 2110 ret = ksz_ptp_clock_register(ds); 2107 2111 if (ret) { 2108 2112 dev_err(dev->dev, "Failed to register PTP clock: %d\n", ret); 2109 - goto out_pirq; 2113 + goto out_ptpirq; 2110 2114 } 2111 2115 2112 2116 ret = ksz_mdio_register(dev); ··· 2127 2123 2128 2124 out_ptp_clock_unregister: 2129 2125 ksz_ptp_clock_unregister(ds); 2126 + out_ptpirq: 2127 + if (dev->irq > 0) 2128 + dsa_switch_for_each_user_port(dp, dev->ds) 2129 + ksz_ptp_irq_free(ds, dp->index); 2130 2130 out_pirq: 2131 2131 if (dev->irq > 0) 2132 2132 dsa_switch_for_each_user_port(dp, dev->ds) ··· 2150 2142 ksz_ptp_clock_unregister(ds); 2151 2143 2152 2144 if (dev->irq > 0) { 2153 - dsa_switch_for_each_user_port(dp, dev->ds) 2145 + dsa_switch_for_each_user_port(dp, dev->ds) { 2146 + ksz_ptp_irq_free(ds, dp->index); 2147 + 2154 2148 ksz_irq_free(&dev->ports[dp->index].pirq); 2149 + } 2155 2150 2156 2151 ksz_irq_free(&dev->girq); 2157 2152 }
+11
drivers/net/dsa/microchip/ksz_common.h
··· 20 20 #define KSZ_MAX_NUM_PORTS 8 21 21 22 22 struct ksz_device; 23 + struct ksz_port; 23 24 24 25 struct vlan_table { 25 26 u32 table[3]; ··· 84 83 struct ksz_device *dev; 85 84 }; 86 85 86 + struct ksz_ptp_irq { 87 + struct ksz_port *port; 88 + u16 ts_reg; 89 + char name[16]; 90 + int num; 91 + }; 92 + 87 93 struct ksz_port { 88 94 bool remove_tag; /* Remove Tag flag set, for ksz8795 only */ 89 95 bool learning; ··· 114 106 struct hwtstamp_config tstamp_config; 115 107 bool hwts_tx_en; 116 108 bool hwts_rx_en; 109 + struct ksz_irq ptpirq; 110 + struct ksz_ptp_irq ptpmsg_irq[3]; 117 111 #endif 118 112 }; 119 113 ··· 622 612 #define REG_PORT_INT_MASK 0x001F 623 613 624 614 #define PORT_SRC_PHY_INT 1 615 + #define PORT_SRC_PTP_INT 2 625 616 626 617 #define KSZ8795_HUGE_PACKET_SIZE 2000 627 618 #define KSZ8863_HUGE_PACKET_SIZE 1916
+207
drivers/net/dsa/microchip/ksz_ptp.c
··· 6 6 */ 7 7 8 8 #include <linux/dsa/ksz_common.h> 9 + #include <linux/irq.h> 10 + #include <linux/irqdomain.h> 9 11 #include <linux/kernel.h> 10 12 #include <linux/ptp_classify.h> 11 13 #include <linux/ptp_clock_kernel.h> ··· 26 24 27 25 #define KSZ_PTP_INC_NS 40ULL /* HW clock is incremented every 40 ns (by 40) */ 28 26 #define KSZ_PTP_SUBNS_BITS 32 27 + 28 + #define KSZ_PTP_INT_START 13 29 29 30 30 static int ksz_ptp_enable_mode(struct ksz_device *dev) 31 31 { ··· 421 417 422 418 if (ptp_data->clock) 423 419 ptp_clock_unregister(ptp_data->clock); 420 + } 421 + 422 + static irqreturn_t ksz_ptp_msg_thread_fn(int irq, void *dev_id) 423 + { 424 + return IRQ_NONE; 425 + } 426 + 427 + static irqreturn_t ksz_ptp_irq_thread_fn(int irq, void *dev_id) 428 + { 429 + struct ksz_irq *ptpirq = dev_id; 430 + unsigned int nhandled = 0; 431 + struct ksz_device *dev; 432 + unsigned int sub_irq; 433 + u16 data; 434 + int ret; 435 + u8 n; 436 + 437 + dev = ptpirq->dev; 438 + 439 + ret = ksz_read16(dev, ptpirq->reg_status, &data); 440 + if (ret) 441 + goto out; 442 + 443 + /* Clear the interrupts W1C */ 444 + ret = ksz_write16(dev, ptpirq->reg_status, data); 445 + if (ret) 446 + return IRQ_NONE; 447 + 448 + for (n = 0; n < ptpirq->nirqs; ++n) { 449 + if (data & BIT(n + KSZ_PTP_INT_START)) { 450 + sub_irq = irq_find_mapping(ptpirq->domain, n); 451 + handle_nested_irq(sub_irq); 452 + ++nhandled; 453 + } 454 + } 455 + 456 + out: 457 + return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE); 458 + } 459 + 460 + static void ksz_ptp_irq_mask(struct irq_data *d) 461 + { 462 + struct ksz_irq *kirq = irq_data_get_irq_chip_data(d); 463 + 464 + kirq->masked &= ~BIT(d->hwirq + KSZ_PTP_INT_START); 465 + } 466 + 467 + static void ksz_ptp_irq_unmask(struct irq_data *d) 468 + { 469 + struct ksz_irq *kirq = irq_data_get_irq_chip_data(d); 470 + 471 + kirq->masked |= BIT(d->hwirq + KSZ_PTP_INT_START); 472 + } 473 + 474 + static void ksz_ptp_irq_bus_lock(struct irq_data *d) 475 + { 476 + struct ksz_irq *kirq = irq_data_get_irq_chip_data(d); 477 + 478 + mutex_lock(&kirq->dev->lock_irq); 479 + } 480 + 481 + static void ksz_ptp_irq_bus_sync_unlock(struct irq_data *d) 482 + { 483 + struct ksz_irq *kirq = irq_data_get_irq_chip_data(d); 484 + struct ksz_device *dev = kirq->dev; 485 + int ret; 486 + 487 + ret = ksz_write16(dev, kirq->reg_mask, kirq->masked); 488 + if (ret) 489 + dev_err(dev->dev, "failed to change IRQ mask\n"); 490 + 491 + mutex_unlock(&dev->lock_irq); 492 + } 493 + 494 + static const struct irq_chip ksz_ptp_irq_chip = { 495 + .name = "ksz-irq", 496 + .irq_mask = ksz_ptp_irq_mask, 497 + .irq_unmask = ksz_ptp_irq_unmask, 498 + .irq_bus_lock = ksz_ptp_irq_bus_lock, 499 + .irq_bus_sync_unlock = ksz_ptp_irq_bus_sync_unlock, 500 + }; 501 + 502 + static int ksz_ptp_irq_domain_map(struct irq_domain *d, 503 + unsigned int irq, irq_hw_number_t hwirq) 504 + { 505 + irq_set_chip_data(irq, d->host_data); 506 + irq_set_chip_and_handler(irq, &ksz_ptp_irq_chip, handle_level_irq); 507 + irq_set_noprobe(irq); 508 + 509 + return 0; 510 + } 511 + 512 + static const struct irq_domain_ops ksz_ptp_irq_domain_ops = { 513 + .map = ksz_ptp_irq_domain_map, 514 + .xlate = irq_domain_xlate_twocell, 515 + }; 516 + 517 + static void ksz_ptp_msg_irq_free(struct ksz_port *port, u8 n) 518 + { 519 + struct ksz_ptp_irq *ptpmsg_irq; 520 + 521 + ptpmsg_irq = &port->ptpmsg_irq[n]; 522 + 523 + free_irq(ptpmsg_irq->num, ptpmsg_irq); 524 + irq_dispose_mapping(ptpmsg_irq->num); 525 + } 526 + 527 + static int ksz_ptp_msg_irq_setup(struct ksz_port *port, u8 n) 528 + { 529 + u16 ts_reg[] = {REG_PTP_PORT_PDRESP_TS, REG_PTP_PORT_XDELAY_TS, 530 + REG_PTP_PORT_SYNC_TS}; 531 + static const char * const name[] = {"pdresp-msg", "xdreq-msg", 532 + "sync-msg"}; 533 + const struct ksz_dev_ops *ops = port->ksz_dev->dev_ops; 534 + struct ksz_ptp_irq *ptpmsg_irq; 535 + 536 + ptpmsg_irq = &port->ptpmsg_irq[n]; 537 + 538 + ptpmsg_irq->port = port; 539 + ptpmsg_irq->ts_reg = ops->get_port_addr(port->num, ts_reg[n]); 540 + 541 + snprintf(ptpmsg_irq->name, sizeof(ptpmsg_irq->name), name[n]); 542 + 543 + ptpmsg_irq->num = irq_find_mapping(port->ptpirq.domain, n); 544 + if (ptpmsg_irq->num < 0) 545 + return ptpmsg_irq->num; 546 + 547 + return request_threaded_irq(ptpmsg_irq->num, NULL, 548 + ksz_ptp_msg_thread_fn, IRQF_ONESHOT, 549 + ptpmsg_irq->name, ptpmsg_irq); 550 + } 551 + 552 + int ksz_ptp_irq_setup(struct dsa_switch *ds, u8 p) 553 + { 554 + struct ksz_device *dev = ds->priv; 555 + const struct ksz_dev_ops *ops = dev->dev_ops; 556 + struct ksz_port *port = &dev->ports[p]; 557 + struct ksz_irq *ptpirq = &port->ptpirq; 558 + int irq; 559 + int ret; 560 + 561 + ptpirq->dev = dev; 562 + ptpirq->masked = 0; 563 + ptpirq->nirqs = 3; 564 + ptpirq->reg_mask = ops->get_port_addr(p, REG_PTP_PORT_TX_INT_ENABLE__2); 565 + ptpirq->reg_status = ops->get_port_addr(p, 566 + REG_PTP_PORT_TX_INT_STATUS__2); 567 + snprintf(ptpirq->name, sizeof(ptpirq->name), "ptp-irq-%d", p); 568 + 569 + ptpirq->domain = irq_domain_add_linear(dev->dev->of_node, ptpirq->nirqs, 570 + &ksz_ptp_irq_domain_ops, ptpirq); 571 + if (!ptpirq->domain) 572 + return -ENOMEM; 573 + 574 + for (irq = 0; irq < ptpirq->nirqs; irq++) 575 + irq_create_mapping(ptpirq->domain, irq); 576 + 577 + ptpirq->irq_num = irq_find_mapping(port->pirq.domain, PORT_SRC_PTP_INT); 578 + if (ptpirq->irq_num < 0) { 579 + ret = ptpirq->irq_num; 580 + goto out; 581 + } 582 + 583 + ret = request_threaded_irq(ptpirq->irq_num, NULL, ksz_ptp_irq_thread_fn, 584 + IRQF_ONESHOT, ptpirq->name, ptpirq); 585 + if (ret) 586 + goto out; 587 + 588 + for (irq = 0; irq < ptpirq->nirqs; irq++) { 589 + ret = ksz_ptp_msg_irq_setup(port, irq); 590 + if (ret) 591 + goto out_ptp_msg; 592 + } 593 + 594 + return 0; 595 + 596 + out_ptp_msg: 597 + free_irq(ptpirq->irq_num, ptpirq); 598 + while (irq--) 599 + free_irq(port->ptpmsg_irq[irq].num, &port->ptpmsg_irq[irq]); 600 + out: 601 + for (irq = 0; irq < ptpirq->nirqs; irq++) 602 + irq_dispose_mapping(port->ptpmsg_irq[irq].num); 603 + 604 + irq_domain_remove(ptpirq->domain); 605 + 606 + return ret; 607 + } 608 + 609 + void ksz_ptp_irq_free(struct dsa_switch *ds, u8 p) 610 + { 611 + struct ksz_device *dev = ds->priv; 612 + struct ksz_port *port = &dev->ports[p]; 613 + struct ksz_irq *ptpirq = &port->ptpirq; 614 + u8 n; 615 + 616 + for (n = 0; n < ptpirq->nirqs; n++) 617 + ksz_ptp_msg_irq_free(port, n); 618 + 619 + free_irq(ptpirq->irq_num, ptpirq); 620 + irq_dispose_mapping(ptpirq->irq_num); 621 + 622 + irq_domain_remove(ptpirq->domain); 424 623 } 425 624 426 625 MODULE_AUTHOR("Christian Eggers <ceggers@arri.de>");
+9
drivers/net/dsa/microchip/ksz_ptp.h
··· 30 30 struct ethtool_ts_info *ts); 31 31 int ksz_hwtstamp_get(struct dsa_switch *ds, int port, struct ifreq *ifr); 32 32 int ksz_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr); 33 + int ksz_ptp_irq_setup(struct dsa_switch *ds, u8 p); 34 + void ksz_ptp_irq_free(struct dsa_switch *ds, u8 p); 33 35 34 36 #else 35 37 ··· 46 44 } 47 45 48 46 static inline void ksz_ptp_clock_unregister(struct dsa_switch *ds) { } 47 + 48 + static inline int ksz_ptp_irq_setup(struct dsa_switch *ds, u8 p) 49 + { 50 + return 0; 51 + } 52 + 53 + static inline void ksz_ptp_irq_free(struct dsa_switch *ds, u8 p) {} 49 54 50 55 #define ksz_get_ts_info NULL 51 56
+19
drivers/net/dsa/microchip/ksz_ptp_reg.h
··· 49 49 #define PTP_MASTER BIT(1) 50 50 #define PTP_1STEP BIT(0) 51 51 52 + /* Port PTP Register */ 53 + #define REG_PTP_PORT_RX_DELAY__2 0x0C00 54 + #define REG_PTP_PORT_TX_DELAY__2 0x0C02 55 + #define REG_PTP_PORT_ASYM_DELAY__2 0x0C04 56 + 57 + #define REG_PTP_PORT_XDELAY_TS 0x0C08 58 + #define REG_PTP_PORT_SYNC_TS 0x0C0C 59 + #define REG_PTP_PORT_PDRESP_TS 0x0C10 60 + 61 + #define REG_PTP_PORT_TX_INT_STATUS__2 0x0C14 62 + #define REG_PTP_PORT_TX_INT_ENABLE__2 0x0C16 63 + 64 + #define PTP_PORT_SYNC_INT BIT(15) 65 + #define PTP_PORT_XDELAY_REQ_INT BIT(14) 66 + #define PTP_PORT_PDELAY_RESP_INT BIT(13) 67 + #define KSZ_SYNC_MSG 2 68 + #define KSZ_XDREQ_MSG 1 69 + #define KSZ_PDRES_MSG 0 70 + 52 71 #endif