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(addr: 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_rane - To restart ANE |
79 | * @ioaddr: IO registers pointer |
80 | * @reg: Base address of the AN Control Register. |
81 | * @restart: to restart ANE |
82 | * Description: this is to just restart the Auto-Negotiation. |
83 | */ |
84 | static inline void dwmac_rane(void __iomem *ioaddr, u32 reg, bool restart) |
85 | { |
86 | u32 value = readl(addr: ioaddr + GMAC_AN_CTRL(reg)); |
87 | |
88 | if (restart) |
89 | value |= GMAC_AN_CTRL_RAN; |
90 | |
91 | writel(val: value, addr: ioaddr + GMAC_AN_CTRL(reg)); |
92 | } |
93 | |
94 | /** |
95 | * dwmac_ctrl_ane - To program the AN Control Register. |
96 | * @ioaddr: IO registers pointer |
97 | * @reg: Base address of the AN Control Register. |
98 | * @ane: to enable the auto-negotiation |
99 | * @srgmi_ral: to manage MAC-2-MAC SGMII connections. |
100 | * @loopback: to cause the PHY to loopback tx data into rx path. |
101 | * Description: this is the main function to configure the AN control register |
102 | * and init the ANE, select loopback (usually for debugging purpose) and |
103 | * configure SGMII RAL. |
104 | */ |
105 | static inline void dwmac_ctrl_ane(void __iomem *ioaddr, u32 reg, bool ane, |
106 | bool srgmi_ral, bool loopback) |
107 | { |
108 | u32 value = readl(addr: ioaddr + GMAC_AN_CTRL(reg)); |
109 | |
110 | /* Enable and restart the Auto-Negotiation */ |
111 | if (ane) |
112 | value |= GMAC_AN_CTRL_ANE | GMAC_AN_CTRL_RAN; |
113 | else |
114 | value &= ~GMAC_AN_CTRL_ANE; |
115 | |
116 | /* In case of MAC-2-MAC connection, block is configured to operate |
117 | * according to MAC conf register. |
118 | */ |
119 | if (srgmi_ral) |
120 | value |= GMAC_AN_CTRL_SGMRAL; |
121 | |
122 | if (loopback) |
123 | value |= GMAC_AN_CTRL_ELE; |
124 | |
125 | writel(val: value, addr: ioaddr + GMAC_AN_CTRL(reg)); |
126 | } |
127 | |
128 | /** |
129 | * dwmac_get_adv_lp - Get ADV and LP cap |
130 | * @ioaddr: IO registers pointer |
131 | * @reg: Base address of the AN Control Register. |
132 | * @adv_lp: structure to store the adv,lp status |
133 | * Description: this is to expose the ANE advertisement and Link partner ability |
134 | * status to ethtool support. |
135 | */ |
136 | static inline void dwmac_get_adv_lp(void __iomem *ioaddr, u32 reg, |
137 | struct rgmii_adv *adv_lp) |
138 | { |
139 | u32 value = readl(addr: ioaddr + GMAC_ANE_ADV(reg)); |
140 | |
141 | if (value & GMAC_ANE_FD) |
142 | adv_lp->duplex = DUPLEX_FULL; |
143 | if (value & GMAC_ANE_HD) |
144 | adv_lp->duplex |= DUPLEX_HALF; |
145 | |
146 | adv_lp->pause = (value & GMAC_ANE_PSE) >> GMAC_ANE_PSE_SHIFT; |
147 | |
148 | value = readl(addr: ioaddr + GMAC_ANE_LPA(reg)); |
149 | |
150 | if (value & GMAC_ANE_FD) |
151 | adv_lp->lp_duplex = DUPLEX_FULL; |
152 | if (value & GMAC_ANE_HD) |
153 | adv_lp->lp_duplex = DUPLEX_HALF; |
154 | |
155 | adv_lp->lp_pause = (value & GMAC_ANE_PSE) >> GMAC_ANE_PSE_SHIFT; |
156 | } |
157 | #endif /* __STMMAC_PCS_H__ */ |
158 | |