]>
Commit | Line | Data |
---|---|---|
8ceee660 BH |
1 | /**************************************************************************** |
2 | * Driver for Solarflare Solarstorm network controllers and boards | |
3 | * Copyright 2006-2008 Solarflare Communications Inc. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms of the GNU General Public License version 2 as published | |
7 | * by the Free Software Foundation, incorporated herein by reference. | |
8 | */ | |
9 | ||
10 | #ifndef EFX_MDIO_10G_H | |
11 | #define EFX_MDIO_10G_H | |
12 | ||
13 | /* | |
14 | * Definitions needed for doing 10G MDIO as specified in clause 45 | |
15 | * MDIO, which do not appear in Linux yet. Also some helper functions. | |
16 | */ | |
17 | ||
18 | #include "efx.h" | |
19 | #include "boards.h" | |
20 | ||
21 | /* Numbering of the MDIO Manageable Devices (MMDs) */ | |
22 | /* Physical Medium Attachment/ Physical Medium Dependent sublayer */ | |
23 | #define MDIO_MMD_PMAPMD (1) | |
24 | /* WAN Interface Sublayer */ | |
25 | #define MDIO_MMD_WIS (2) | |
26 | /* Physical Coding Sublayer */ | |
27 | #define MDIO_MMD_PCS (3) | |
28 | /* PHY Extender Sublayer */ | |
29 | #define MDIO_MMD_PHYXS (4) | |
30 | /* Extender Sublayer */ | |
31 | #define MDIO_MMD_DTEXS (5) | |
32 | /* Transmission convergence */ | |
33 | #define MDIO_MMD_TC (6) | |
34 | /* Auto negotiation */ | |
35 | #define MDIO_MMD_AN (7) | |
36 | ||
37 | /* Generic register locations */ | |
38 | #define MDIO_MMDREG_CTRL1 (0) | |
39 | #define MDIO_MMDREG_STAT1 (1) | |
40 | #define MDIO_MMDREG_IDHI (2) | |
41 | #define MDIO_MMDREG_IDLOW (3) | |
42 | #define MDIO_MMDREG_SPEED (4) | |
43 | #define MDIO_MMDREG_DEVS0 (5) | |
44 | #define MDIO_MMDREG_DEVS1 (6) | |
45 | #define MDIO_MMDREG_CTRL2 (7) | |
46 | #define MDIO_MMDREG_STAT2 (8) | |
3273c2e8 | 47 | #define MDIO_MMDREG_TXDIS (9) |
8ceee660 BH |
48 | |
49 | /* Bits in MMDREG_CTRL1 */ | |
50 | /* Reset */ | |
51 | #define MDIO_MMDREG_CTRL1_RESET_LBN (15) | |
52 | #define MDIO_MMDREG_CTRL1_RESET_WIDTH (1) | |
3273c2e8 BH |
53 | /* Loopback */ |
54 | /* Loopback bit for WIS, PCS, PHYSX and DTEXS */ | |
55 | #define MDIO_MMDREG_CTRL1_LBACK_LBN (14) | |
56 | #define MDIO_MMDREG_CTRL1_LBACK_WIDTH (1) | |
3e133c44 BH |
57 | /* Low power */ |
58 | #define MDIO_MMDREG_CTRL1_LPOWER_LBN (11) | |
59 | #define MDIO_MMDREG_CTRL1_LPOWER_WIDTH (1) | |
8ceee660 BH |
60 | |
61 | /* Bits in MMDREG_STAT1 */ | |
62 | #define MDIO_MMDREG_STAT1_FAULT_LBN (7) | |
63 | #define MDIO_MMDREG_STAT1_FAULT_WIDTH (1) | |
64 | /* Link state */ | |
65 | #define MDIO_MMDREG_STAT1_LINK_LBN (2) | |
66 | #define MDIO_MMDREG_STAT1_LINK_WIDTH (1) | |
3273c2e8 BH |
67 | /* Low power ability */ |
68 | #define MDIO_MMDREG_STAT1_LPABLE_LBN (1) | |
69 | #define MDIO_MMDREG_STAT1_LPABLE_WIDTH (1) | |
8ceee660 BH |
70 | |
71 | /* Bits in ID reg */ | |
72 | #define MDIO_ID_REV(_id32) (_id32 & 0xf) | |
73 | #define MDIO_ID_MODEL(_id32) ((_id32 >> 4) & 0x3f) | |
74 | #define MDIO_ID_OUI(_id32) (_id32 >> 10) | |
75 | ||
27dd2cac | 76 | /* Bits in MMDREG_DEVS0/1. Someone thoughtfully layed things out |
8ceee660 BH |
77 | * so the 'bit present' bit number of an MMD is the number of |
78 | * that MMD */ | |
79 | #define DEV_PRESENT_BIT(_b) (1 << _b) | |
80 | ||
27dd2cac BH |
81 | #define MDIO_MMDREG_DEVS_PHYXS DEV_PRESENT_BIT(MDIO_MMD_PHYXS) |
82 | #define MDIO_MMDREG_DEVS_PCS DEV_PRESENT_BIT(MDIO_MMD_PCS) | |
83 | #define MDIO_MMDREG_DEVS_PMAPMD DEV_PRESENT_BIT(MDIO_MMD_PMAPMD) | |
8ceee660 BH |
84 | |
85 | /* Bits in MMDREG_STAT2 */ | |
86 | #define MDIO_MMDREG_STAT2_PRESENT_VAL (2) | |
87 | #define MDIO_MMDREG_STAT2_PRESENT_LBN (14) | |
88 | #define MDIO_MMDREG_STAT2_PRESENT_WIDTH (2) | |
89 | ||
3273c2e8 BH |
90 | /* Bits in MMDREG_TXDIS */ |
91 | #define MDIO_MMDREG_TXDIS_GLOBAL_LBN (0) | |
92 | #define MDIO_MMDREG_TXDIS_GLOBAL_WIDTH (1) | |
93 | ||
94 | /* MMD-specific bits, ordered by MMD, then register */ | |
95 | #define MDIO_PMAPMD_CTRL1_LBACK_LBN (0) | |
96 | #define MDIO_PMAPMD_CTRL1_LBACK_WIDTH (1) | |
97 | ||
8ceee660 BH |
98 | /* PMA type (4 bits) */ |
99 | #define MDIO_PMAPMD_CTRL2_10G_CX4 (0x0) | |
100 | #define MDIO_PMAPMD_CTRL2_10G_EW (0x1) | |
101 | #define MDIO_PMAPMD_CTRL2_10G_LW (0x2) | |
102 | #define MDIO_PMAPMD_CTRL2_10G_SW (0x3) | |
103 | #define MDIO_PMAPMD_CTRL2_10G_LX4 (0x4) | |
104 | #define MDIO_PMAPMD_CTRL2_10G_ER (0x5) | |
105 | #define MDIO_PMAPMD_CTRL2_10G_LR (0x6) | |
106 | #define MDIO_PMAPMD_CTRL2_10G_SR (0x7) | |
107 | /* Reserved */ | |
108 | #define MDIO_PMAPMD_CTRL2_10G_BT (0x9) | |
109 | /* Reserved */ | |
110 | /* Reserved */ | |
111 | #define MDIO_PMAPMD_CTRL2_1G_BT (0xc) | |
112 | /* Reserved */ | |
113 | #define MDIO_PMAPMD_CTRL2_100_BT (0xe) | |
114 | #define MDIO_PMAPMD_CTRL2_10_BT (0xf) | |
115 | #define MDIO_PMAPMD_CTRL2_TYPE_MASK (0xf) | |
116 | ||
707d9827 | 117 | /* PHY XGXS lane state */ |
8ceee660 BH |
118 | #define MDIO_PHYXS_LANE_STATE (0x18) |
119 | #define MDIO_PHYXS_LANE_ALIGNED_LBN (12) | |
120 | ||
121 | /* AN registers */ | |
122 | #define MDIO_AN_STATUS (1) | |
123 | #define MDIO_AN_STATUS_XNP_LBN (7) | |
124 | #define MDIO_AN_STATUS_PAGE_LBN (6) | |
125 | #define MDIO_AN_STATUS_AN_DONE_LBN (5) | |
126 | #define MDIO_AN_STATUS_LP_AN_CAP_LBN (0) | |
127 | ||
128 | #define MDIO_AN_10GBT_STATUS (33) | |
129 | #define MDIO_AN_10GBT_STATUS_MS_FLT_LBN (15) /* MASTER/SLAVE config fault */ | |
130 | #define MDIO_AN_10GBT_STATUS_MS_LBN (14) /* MASTER/SLAVE config */ | |
131 | #define MDIO_AN_10GBT_STATUS_LOC_OK_LBN (13) /* Local OK */ | |
132 | #define MDIO_AN_10GBT_STATUS_REM_OK_LBN (12) /* Remote OK */ | |
133 | #define MDIO_AN_10GBT_STATUS_LP_10G_LBN (11) /* Link partner is 10GBT capable */ | |
134 | #define MDIO_AN_10GBT_STATUS_LP_LTA_LBN (10) /* LP loop timing ability */ | |
135 | #define MDIO_AN_10GBT_STATUS_LP_TRR_LBN (9) /* LP Training Reset Request */ | |
136 | ||
137 | ||
138 | /* Packing of the prt and dev arguments of clause 45 style MDIO into a | |
139 | * single int so they can be passed into the mdio_read/write functions | |
140 | * that currently exist. Note that as Falcon is the only current user, | |
141 | * the packed form is chosen to match what Falcon needs to write into | |
142 | * a register. This is checked at compile-time so do not change it. If | |
143 | * your target chip needs things layed out differently you will need | |
144 | * to unpack the arguments in your chip-specific mdio functions. | |
145 | */ | |
146 | /* These are defined by the standard. */ | |
147 | #define MDIO45_PRT_ID_WIDTH (5) | |
148 | #define MDIO45_DEV_ID_WIDTH (5) | |
149 | ||
150 | /* The prt ID is just packed in immediately to the left of the dev ID */ | |
151 | #define MDIO45_PRT_DEV_WIDTH (MDIO45_PRT_ID_WIDTH + MDIO45_DEV_ID_WIDTH) | |
152 | ||
153 | #define MDIO45_PRT_ID_MASK ((1 << MDIO45_PRT_DEV_WIDTH) - 1) | |
154 | /* This is the prt + dev extended by 1 bit to hold the 'is clause 45' flag. */ | |
155 | #define MDIO45_XPRT_ID_WIDTH (MDIO45_PRT_DEV_WIDTH + 1) | |
156 | #define MDIO45_XPRT_ID_MASK ((1 << MDIO45_XPRT_ID_WIDTH) - 1) | |
157 | #define MDIO45_XPRT_ID_IS10G (1 << (MDIO45_XPRT_ID_WIDTH - 1)) | |
158 | ||
159 | ||
160 | #define MDIO45_PRT_ID_COMP_LBN MDIO45_DEV_ID_WIDTH | |
161 | #define MDIO45_PRT_ID_COMP_WIDTH MDIO45_PRT_ID_WIDTH | |
162 | #define MDIO45_DEV_ID_COMP_LBN 0 | |
163 | #define MDIO45_DEV_ID_COMP_WIDTH MDIO45_DEV_ID_WIDTH | |
164 | ||
165 | /* Compose port and device into a phy_id */ | |
166 | static inline int mdio_clause45_pack(u8 prt, u8 dev) | |
167 | { | |
168 | efx_dword_t phy_id; | |
169 | EFX_POPULATE_DWORD_2(phy_id, MDIO45_PRT_ID_COMP, prt, | |
170 | MDIO45_DEV_ID_COMP, dev); | |
171 | return MDIO45_XPRT_ID_IS10G | EFX_DWORD_VAL(phy_id); | |
172 | } | |
173 | ||
174 | static inline void mdio_clause45_unpack(u32 val, u8 *prt, u8 *dev) | |
175 | { | |
176 | efx_dword_t phy_id; | |
177 | EFX_POPULATE_DWORD_1(phy_id, EFX_DWORD_0, val); | |
178 | *prt = EFX_DWORD_FIELD(phy_id, MDIO45_PRT_ID_COMP); | |
179 | *dev = EFX_DWORD_FIELD(phy_id, MDIO45_DEV_ID_COMP); | |
180 | } | |
181 | ||
182 | static inline int mdio_clause45_read(struct efx_nic *efx, | |
183 | u8 prt, u8 dev, u16 addr) | |
184 | { | |
185 | return efx->mii.mdio_read(efx->net_dev, | |
186 | mdio_clause45_pack(prt, dev), addr); | |
187 | } | |
188 | ||
189 | static inline void mdio_clause45_write(struct efx_nic *efx, | |
190 | u8 prt, u8 dev, u16 addr, int value) | |
191 | { | |
192 | efx->mii.mdio_write(efx->net_dev, | |
193 | mdio_clause45_pack(prt, dev), addr, value); | |
194 | } | |
195 | ||
196 | ||
197 | static inline u32 mdio_clause45_read_id(struct efx_nic *efx, int mmd) | |
198 | { | |
199 | int phy_id = efx->mii.phy_id; | |
200 | u16 id_low = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_IDLOW); | |
201 | u16 id_hi = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_IDHI); | |
202 | return (id_hi << 16) | (id_low); | |
203 | } | |
204 | ||
dc8cfa55 | 205 | static inline bool mdio_clause45_phyxgxs_lane_sync(struct efx_nic *efx) |
8ceee660 | 206 | { |
dc8cfa55 BH |
207 | int i, lane_status; |
208 | bool sync; | |
8ceee660 BH |
209 | |
210 | for (i = 0; i < 2; ++i) | |
211 | lane_status = mdio_clause45_read(efx, efx->mii.phy_id, | |
212 | MDIO_MMD_PHYXS, | |
213 | MDIO_PHYXS_LANE_STATE); | |
214 | ||
dc8cfa55 | 215 | sync = !!(lane_status & (1 << MDIO_PHYXS_LANE_ALIGNED_LBN)); |
8ceee660 | 216 | if (!sync) |
e9713e6f | 217 | EFX_LOG(efx, "XGXS lane status: %x\n", lane_status); |
8ceee660 BH |
218 | return sync; |
219 | } | |
220 | ||
221 | extern const char *mdio_clause45_mmd_name(int mmd); | |
222 | ||
223 | /* | |
224 | * Reset a specific MMD and wait for reset to clear. | |
225 | * Return number of spins left (>0) on success, -%ETIMEDOUT on failure. | |
226 | * | |
227 | * This function will sleep | |
228 | */ | |
229 | extern int mdio_clause45_reset_mmd(struct efx_nic *efx, int mmd, | |
230 | int spins, int spintime); | |
231 | ||
232 | /* As mdio_clause45_check_mmd but for multiple MMDs */ | |
233 | int mdio_clause45_check_mmds(struct efx_nic *efx, | |
234 | unsigned int mmd_mask, unsigned int fatal_mask); | |
235 | ||
236 | /* Check the link status of specified mmds in bit mask */ | |
dc8cfa55 BH |
237 | extern bool mdio_clause45_links_ok(struct efx_nic *efx, |
238 | unsigned int mmd_mask); | |
8ceee660 | 239 | |
3273c2e8 BH |
240 | /* Generic transmit disable support though PMAPMD */ |
241 | extern void mdio_clause45_transmit_disable(struct efx_nic *efx); | |
242 | ||
243 | /* Generic part of reconfigure: set/clear loopback bits */ | |
244 | extern void mdio_clause45_phy_reconfigure(struct efx_nic *efx); | |
245 | ||
3e133c44 BH |
246 | /* Set the power state of the specified MMDs */ |
247 | extern void mdio_clause45_set_mmds_lpower(struct efx_nic *efx, | |
248 | int low_power, unsigned int mmd_mask); | |
249 | ||
8ceee660 BH |
250 | /* Read (some of) the PHY settings over MDIO */ |
251 | extern void mdio_clause45_get_settings(struct efx_nic *efx, | |
252 | struct ethtool_cmd *ecmd); | |
253 | ||
254 | /* Set (some of) the PHY settings over MDIO */ | |
255 | extern int mdio_clause45_set_settings(struct efx_nic *efx, | |
256 | struct ethtool_cmd *ecmd); | |
257 | ||
258 | /* Wait for specified MMDs to exit reset within a timeout */ | |
259 | extern int mdio_clause45_wait_reset_mmds(struct efx_nic *efx, | |
260 | unsigned int mmd_mask); | |
261 | ||
356eebb2 BH |
262 | /* Set or clear flag, debouncing */ |
263 | extern void mdio_clause45_set_flag(struct efx_nic *efx, u8 prt, u8 dev, | |
264 | u16 addr, int bit, bool sense); | |
265 | ||
8ceee660 | 266 | #endif /* EFX_MDIO_10G_H */ |