1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * stmmac_pcs.h: Physical Coding Sublayer Header File 4 * 5 * Copyright (C) 2016 STMicroelectronics (R&D) Limited 6 * Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> 7 */ 8 9 #ifndef __STMMAC_PCS_H__ 10 #define __STMMAC_PCS_H__ 11 12 #include <linux/slab.h> 13 #include <linux/io.h> 14 #include "common.h" 15 16 /* PCS registers (AN/TBI/SGMII/RGMII) offsets */ 17 #define GMAC_AN_CTRL(x) (x) /* AN control */ 18 #define GMAC_AN_STATUS(x) (x + 0x4) /* AN status */ 19 #define GMAC_ANE_ADV(x) (x + 0x8) /* ANE Advertisement */ 20 #define GMAC_ANE_LPA(x) (x + 0xc) /* ANE link partener ability */ 21 #define GMAC_ANE_EXP(x) (x + 0x10) /* ANE expansion */ 22 #define GMAC_TBI(x) (x + 0x14) /* TBI extend status */ 23 24 /* AN Configuration defines */ 25 #define GMAC_AN_CTRL_RAN BIT(9) /* Restart Auto-Negotiation */ 26 #define GMAC_AN_CTRL_ANE BIT(12) /* Auto-Negotiation Enable */ 27 #define GMAC_AN_CTRL_ELE BIT(14) /* External Loopback Enable */ 28 #define GMAC_AN_CTRL_ECD BIT(16) /* Enable Comma Detect */ 29 #define GMAC_AN_CTRL_LR BIT(17) /* Lock to Reference */ 30 #define GMAC_AN_CTRL_SGMRAL BIT(18) /* SGMII RAL Control */ 31 32 /* AN Status defines */ 33 #define GMAC_AN_STATUS_LS BIT(2) /* Link Status 0:down 1:up */ 34 #define GMAC_AN_STATUS_ANA BIT(3) /* Auto-Negotiation Ability */ 35 #define GMAC_AN_STATUS_ANC BIT(5) /* Auto-Negotiation Complete */ 36 #define GMAC_AN_STATUS_ES BIT(8) /* Extended Status */ 37 38 /* ADV and LPA defines */ 39 #define GMAC_ANE_FD BIT(5) 40 #define GMAC_ANE_HD BIT(6) 41 #define GMAC_ANE_PSE GENMASK(8, 7) 42 #define GMAC_ANE_PSE_SHIFT 7 43 #define GMAC_ANE_RFE GENMASK(13, 12) 44 #define GMAC_ANE_RFE_SHIFT 12 45 #define GMAC_ANE_ACK BIT(14) 46 47 /** 48 * dwmac_pcs_isr - TBI, RTBI, or SGMII PHY ISR 49 * @ioaddr: IO registers pointer 50 * @reg: Base address of the AN Control Register. 51 * @intr_status: GMAC core interrupt status 52 * @x: pointer to log these events as stats 53 * Description: it is the ISR for PCS events: Auto-Negotiation Completed and 54 * Link status. 55 */ 56 static inline void dwmac_pcs_isr(void __iomem *ioaddr, u32 reg, 57 unsigned int intr_status, 58 struct stmmac_extra_stats *x) 59 { 60 u32 val = readl(ioaddr + GMAC_AN_STATUS(reg)); 61 62 if (intr_status & PCS_ANE_IRQ) { 63 x->irq_pcs_ane_n++; 64 if (val & GMAC_AN_STATUS_ANC) 65 pr_info("stmmac_pcs: ANE process completed\n"); 66 } 67 68 if (intr_status & PCS_LINK_IRQ) { 69 x->irq_pcs_link_n++; 70 if (val & GMAC_AN_STATUS_LS) 71 pr_info("stmmac_pcs: Link Up\n"); 72 else 73 pr_info("stmmac_pcs: Link Down\n"); 74 } 75 } 76 77 /** 78 * dwmac_ctrl_ane - To program the AN Control Register. 79 * @ioaddr: IO registers pointer 80 * @reg: Base address of the AN Control Register. 81 * @ane: to enable the auto-negotiation 82 * @srgmi_ral: to manage MAC-2-MAC SGMII connections. 83 * @loopback: to cause the PHY to loopback tx data into rx path. 84 * Description: this is the main function to configure the AN control register 85 * and init the ANE, select loopback (usually for debugging purpose) and 86 * configure SGMII RAL. 87 */ 88 static inline void dwmac_ctrl_ane(void __iomem *ioaddr, u32 reg, bool ane, 89 bool srgmi_ral, bool loopback) 90 { 91 u32 value = readl(ioaddr + GMAC_AN_CTRL(reg)); 92 93 /* Enable and restart the Auto-Negotiation */ 94 if (ane) 95 value |= GMAC_AN_CTRL_ANE | GMAC_AN_CTRL_RAN; 96 else 97 value &= ~GMAC_AN_CTRL_ANE; 98 99 /* In case of MAC-2-MAC connection, block is configured to operate 100 * according to MAC conf register. 101 */ 102 if (srgmi_ral) 103 value |= GMAC_AN_CTRL_SGMRAL; 104 105 if (loopback) 106 value |= GMAC_AN_CTRL_ELE; 107 108 writel(value, ioaddr + GMAC_AN_CTRL(reg)); 109 } 110 111 /** 112 * dwmac_get_adv_lp - Get ADV and LP cap 113 * @ioaddr: IO registers pointer 114 * @reg: Base address of the AN Control Register. 115 * @adv_lp: structure to store the adv,lp status 116 * Description: this is to expose the ANE advertisement and Link partner ability 117 * status to ethtool support. 118 */ 119 static inline void dwmac_get_adv_lp(void __iomem *ioaddr, u32 reg, 120 struct rgmii_adv *adv_lp) 121 { 122 u32 value = readl(ioaddr + GMAC_ANE_ADV(reg)); 123 124 if (value & GMAC_ANE_FD) 125 adv_lp->duplex = DUPLEX_FULL; 126 if (value & GMAC_ANE_HD) 127 adv_lp->duplex |= DUPLEX_HALF; 128 129 adv_lp->pause = (value & GMAC_ANE_PSE) >> GMAC_ANE_PSE_SHIFT; 130 131 value = readl(ioaddr + GMAC_ANE_LPA(reg)); 132 133 if (value & GMAC_ANE_FD) 134 adv_lp->lp_duplex = DUPLEX_FULL; 135 if (value & GMAC_ANE_HD) 136 adv_lp->lp_duplex = DUPLEX_HALF; 137 138 adv_lp->lp_pause = (value & GMAC_ANE_PSE) >> GMAC_ANE_PSE_SHIFT; 139 } 140 #endif /* __STMMAC_PCS_H__ */ 141