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