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.

Merge branch 'net-pcs-rzn1-miic-support-configurable-phy_link-polarity'

Lad Prabhakar says:

====================
net: pcs: rzn1-miic: Support configurable PHY_LINK polarity

This series adds support for configuring the active level of MIIC
PHY_LINK status signals on Renesas RZ/N1 and RZ/T2H/N2H platforms.

The MIIC block provides dedicated hardware PHY_LINK signals that indicate
EtherPHY link-up and link-down status independently of whether the MAC
(GMAC) or Ethernet switch (ETHSW) is used. While GMAC-based systems
typically obtain link state via MDIO and handle it in software, the
ETHSW relies on these PHY_LINK pins for both CPU-assisted operation and
switch-only forwarding paths that do not involve the host processor.

These hardware PHY_LINK signals are particularly important for use cases
requiring fast reaction to link-down events, such as redundancy protocols
including Device Level Ring (DLR). In such scenarios, relying solely on
software-based link detection introduces latency that can negatively
impact recovery time. The ETHSW therefore exposes PHY_LINK signals to
enable immediate hardware-level detection of cable or port failures.

Some systems require the PHY_LINK signal polarity to be configured as
active low rather than the default active high. This series introduces a
new DT property to describe the required polarity and adds corresponding
driver support to program the MIIC PHY_LINK register accordingly. The
configuration is accumulated during DT parsing and applied once hardware
initialization is complete, taking into account SoC-specific differences
between RZ/N1 and RZ/T2H/N2H.
====================

Link: https://patch.msgid.link/20260112173555.1166714-1-prabhakar.mahadev-lad.rj@bp.renesas.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+109 -3
+7
Documentation/devicetree/bindings/net/pcs/renesas,rzn1-miic.yaml
··· 86 86 and include/dt-bindings/net/renesas,r9a09g077-pcs-miic.h for RZ/N2H, RZ/T2H SoCs. 87 87 $ref: /schemas/types.yaml#/definitions/uint32 88 88 89 + renesas,miic-phy-link-active-low: 90 + type: boolean 91 + description: Indicates that the PHY-link signal provided by the Ethernet switch, 92 + EtherCAT, or SERCOS3 interface is active low. When present, this property 93 + sets the corresponding signal polarity to active low. When omitted, the signal 94 + defaults to active high. 95 + 89 96 required: 90 97 - reg 91 98 - renesas,miic-input
+102 -3
drivers/net/pcs/pcs-rzn1-miic.c
··· 28 28 29 29 #define MIIC_MODCTRL 0x8 30 30 31 + #define MIIC_PHY_LINK 0x14 32 + 31 33 #define MIIC_CONVCTRL(port) (0x100 + (port) * 4) 32 34 33 35 #define MIIC_CONVCTRL_CONV_SPEED GENMASK(1, 0) ··· 180 178 }; 181 179 182 180 /** 181 + * struct miic_phy_link_cfg - MIIC PHY_LINK configuration 182 + * @mask: Mask of phy_link bits 183 + * @val: Value of phy_link bits 184 + */ 185 + struct miic_phy_link_cfg { 186 + u32 mask; 187 + u32 val; 188 + }; 189 + 190 + /** 183 191 * struct miic - MII converter structure 184 192 * @base: base address of the MII converter 185 193 * @dev: Device associated to the MII converter 186 194 * @lock: Lock used for read-modify-write access 187 195 * @rsts: Reset controls for the MII converter 188 196 * @of_data: Pointer to OF data 197 + * @link_cfg: MIIC PHY_LINK configuration 189 198 */ 190 199 struct miic { 191 200 void __iomem *base; ··· 204 191 spinlock_t lock; 205 192 struct reset_control_bulk_data rsts[MIIC_MAX_NUM_RSTS]; 206 193 const struct miic_of_data *of_data; 194 + struct miic_phy_link_cfg link_cfg; 195 + }; 196 + 197 + enum miic_type { 198 + MIIC_TYPE_RZN1, 199 + MIIC_TYPE_RZT2H, 207 200 }; 208 201 209 202 /** ··· 229 210 * @init_unlock_lock_regs: Flag to indicate if registers need to be unlocked 230 211 * before access. 231 212 * @miic_write: Function pointer to write a value to a MIIC register 213 + * @type: Type of MIIC 232 214 */ 233 215 struct miic_of_data { 234 216 struct modctrl_match *match_table; ··· 246 226 u8 reset_count; 247 227 bool init_unlock_lock_regs; 248 228 void (*miic_write)(struct miic *miic, int offset, u32 value); 229 + enum miic_type type; 249 230 }; 250 231 251 232 /** ··· 602 581 return -EINVAL; 603 582 } 604 583 584 + static void miic_configure_phy_link(struct miic *miic, u32 conf, 585 + u32 port, bool active_low) 586 + { 587 + bool polarity_active_high; 588 + u32 mask, shift; 589 + 590 + /* determine shift and polarity for this conf */ 591 + if (miic->of_data->type == MIIC_TYPE_RZN1) { 592 + switch (conf) { 593 + /* switch ports => bits [3:0] (shift 0), active when low */ 594 + case MIIC_SWITCH_PORTA: 595 + case MIIC_SWITCH_PORTB: 596 + case MIIC_SWITCH_PORTC: 597 + case MIIC_SWITCH_PORTD: 598 + shift = 0; 599 + polarity_active_high = false; 600 + break; 601 + 602 + /* EtherCAT ports => bits [7:4] (shift 4), active when high */ 603 + case MIIC_ETHERCAT_PORTA: 604 + case MIIC_ETHERCAT_PORTB: 605 + case MIIC_ETHERCAT_PORTC: 606 + shift = 4; 607 + polarity_active_high = true; 608 + break; 609 + 610 + /* Sercos ports => bits [11:8] (shift 8), active when high */ 611 + case MIIC_SERCOS_PORTA: 612 + case MIIC_SERCOS_PORTB: 613 + shift = 8; 614 + polarity_active_high = true; 615 + break; 616 + 617 + default: 618 + return; 619 + } 620 + } else { 621 + switch (conf) { 622 + /* ETHSW ports => bits [3:0] (shift 0), active when low */ 623 + case ETHSS_ETHSW_PORT0: 624 + case ETHSS_ETHSW_PORT1: 625 + case ETHSS_ETHSW_PORT2: 626 + shift = 0; 627 + polarity_active_high = false; 628 + break; 629 + 630 + /* ESC ports => bits [7:4] (shift 4), active when high */ 631 + case ETHSS_ESC_PORT0: 632 + case ETHSS_ESC_PORT1: 633 + case ETHSS_ESC_PORT2: 634 + shift = 4; 635 + polarity_active_high = true; 636 + break; 637 + 638 + default: 639 + return; 640 + } 641 + } 642 + 643 + mask = BIT(port + shift); 644 + 645 + miic->link_cfg.mask |= mask; 646 + if (polarity_active_high != active_low) 647 + miic->link_cfg.val |= mask; 648 + else 649 + miic->link_cfg.val &= ~mask; 650 + } 651 + 605 652 static int miic_parse_dt(struct miic *miic, u32 *mode_cfg) 606 653 { 607 654 struct device_node *np = miic->dev->of_node; 608 655 struct device_node *conv; 656 + bool active_low; 609 657 int port, ret; 610 658 s8 *dt_val; 611 659 u32 conf; ··· 693 603 if (of_property_read_u32(conv, "reg", &port)) 694 604 continue; 695 605 606 + if (of_property_read_u32(conv, "renesas,miic-input", &conf)) 607 + continue; 608 + 696 609 /* Adjust for 0 based index */ 697 - port += !miic->of_data->miic_port_start; 698 - if (of_property_read_u32(conv, "renesas,miic-input", &conf) == 0) 699 - dt_val[port] = conf; 610 + dt_val[port + !miic->of_data->miic_port_start] = conf; 611 + 612 + active_low = of_property_read_bool(conv, "renesas,miic-phy-link-active-low"); 613 + 614 + miic_configure_phy_link(miic, conf, port, active_low); 700 615 } 701 616 702 617 ret = miic_match_dt_conf(miic, dt_val, mode_cfg); ··· 791 696 if (ret) 792 697 goto disable_runtime_pm; 793 698 699 + miic_reg_rmw(miic, MIIC_PHY_LINK, miic->link_cfg.mask, miic->link_cfg.val); 700 + 794 701 /* miic_create() relies on that fact that data are attached to the 795 702 * platform device to determine if the driver is ready so this needs to 796 703 * be the last thing to be done after everything is initialized ··· 826 729 .sw_mode_mask = GENMASK(4, 0), 827 730 .init_unlock_lock_regs = true, 828 731 .miic_write = miic_reg_writel_unlocked, 732 + .type = MIIC_TYPE_RZN1, 829 733 }; 830 734 831 735 static struct miic_of_data rzt2h_miic_of_data = { ··· 843 745 .reset_ids = rzt2h_reset_ids, 844 746 .reset_count = ARRAY_SIZE(rzt2h_reset_ids), 845 747 .miic_write = miic_reg_writel_locked, 748 + .type = MIIC_TYPE_RZT2H, 846 749 }; 847 750 848 751 static const struct of_device_id miic_of_mtable[] = {