Commit | Line | Data |
---|---|---|
57ba4c9b IL |
1 | /* |
2 | * Copyright 2008-2015 Freescale Semiconductor Inc. | |
3 | * | |
4 | * Redistribution and use in source and binary forms, with or without | |
5 | * modification, are permitted provided that the following conditions are met: | |
6 | * * Redistributions of source code must retain the above copyright | |
7 | * notice, this list of conditions and the following disclaimer. | |
8 | * * Redistributions in binary form must reproduce the above copyright | |
9 | * notice, this list of conditions and the following disclaimer in the | |
10 | * documentation and/or other materials provided with the distribution. | |
11 | * * Neither the name of Freescale Semiconductor nor the | |
12 | * names of its contributors may be used to endorse or promote products | |
13 | * derived from this software without specific prior written permission. | |
14 | * | |
15 | * | |
16 | * ALTERNATIVELY, this software may be distributed under the terms of the | |
17 | * GNU General Public License ("GPL") as published by the Free Software | |
18 | * Foundation, either version 2 of that License or (at your option) any | |
19 | * later version. | |
20 | * | |
21 | * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY | |
22 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
23 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
24 | * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY | |
25 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
27 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
28 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
31 | */ | |
32 | ||
33 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
34 | ||
35 | #include "fman_dtsec.h" | |
36 | #include "fman.h" | |
37 | ||
38 | #include <linux/slab.h> | |
39 | #include <linux/bitrev.h> | |
40 | #include <linux/io.h> | |
41 | #include <linux/delay.h> | |
42 | #include <linux/phy.h> | |
43 | #include <linux/crc32.h> | |
44 | #include <linux/of_mdio.h> | |
45 | #include <linux/mii.h> | |
46 | ||
47 | /* TBI register addresses */ | |
48 | #define MII_TBICON 0x11 | |
49 | ||
50 | /* TBICON register bit fields */ | |
51 | #define TBICON_SOFT_RESET 0x8000 /* Soft reset */ | |
52 | #define TBICON_DISABLE_RX_DIS 0x2000 /* Disable receive disparity */ | |
53 | #define TBICON_DISABLE_TX_DIS 0x1000 /* Disable transmit disparity */ | |
54 | #define TBICON_AN_SENSE 0x0100 /* Auto-negotiation sense enable */ | |
55 | #define TBICON_CLK_SELECT 0x0020 /* Clock select */ | |
56 | #define TBICON_MI_MODE 0x0010 /* GMII mode (TBI if not set) */ | |
57 | ||
58 | #define TBIANA_SGMII 0x4001 | |
59 | #define TBIANA_1000X 0x01a0 | |
60 | ||
61 | /* Interrupt Mask Register (IMASK) */ | |
62 | #define DTSEC_IMASK_BREN 0x80000000 | |
63 | #define DTSEC_IMASK_RXCEN 0x40000000 | |
64 | #define DTSEC_IMASK_MSROEN 0x04000000 | |
65 | #define DTSEC_IMASK_GTSCEN 0x02000000 | |
66 | #define DTSEC_IMASK_BTEN 0x01000000 | |
67 | #define DTSEC_IMASK_TXCEN 0x00800000 | |
68 | #define DTSEC_IMASK_TXEEN 0x00400000 | |
69 | #define DTSEC_IMASK_LCEN 0x00040000 | |
70 | #define DTSEC_IMASK_CRLEN 0x00020000 | |
71 | #define DTSEC_IMASK_XFUNEN 0x00010000 | |
72 | #define DTSEC_IMASK_ABRTEN 0x00008000 | |
73 | #define DTSEC_IMASK_IFERREN 0x00004000 | |
74 | #define DTSEC_IMASK_MAGEN 0x00000800 | |
75 | #define DTSEC_IMASK_MMRDEN 0x00000400 | |
76 | #define DTSEC_IMASK_MMWREN 0x00000200 | |
77 | #define DTSEC_IMASK_GRSCEN 0x00000100 | |
78 | #define DTSEC_IMASK_TDPEEN 0x00000002 | |
79 | #define DTSEC_IMASK_RDPEEN 0x00000001 | |
80 | ||
81 | #define DTSEC_EVENTS_MASK \ | |
82 | ((u32)(DTSEC_IMASK_BREN | \ | |
83 | DTSEC_IMASK_RXCEN | \ | |
84 | DTSEC_IMASK_BTEN | \ | |
85 | DTSEC_IMASK_TXCEN | \ | |
86 | DTSEC_IMASK_TXEEN | \ | |
87 | DTSEC_IMASK_ABRTEN | \ | |
88 | DTSEC_IMASK_LCEN | \ | |
89 | DTSEC_IMASK_CRLEN | \ | |
90 | DTSEC_IMASK_XFUNEN | \ | |
91 | DTSEC_IMASK_IFERREN | \ | |
92 | DTSEC_IMASK_MAGEN | \ | |
93 | DTSEC_IMASK_TDPEEN | \ | |
94 | DTSEC_IMASK_RDPEEN)) | |
95 | ||
96 | /* dtsec timestamp event bits */ | |
97 | #define TMR_PEMASK_TSREEN 0x00010000 | |
98 | #define TMR_PEVENT_TSRE 0x00010000 | |
99 | ||
100 | /* Group address bit indication */ | |
101 | #define MAC_GROUP_ADDRESS 0x0000010000000000ULL | |
102 | ||
103 | /* Defaults */ | |
104 | #define DEFAULT_HALFDUP_RETRANSMIT 0xf | |
105 | #define DEFAULT_HALFDUP_COLL_WINDOW 0x37 | |
106 | #define DEFAULT_TX_PAUSE_TIME 0xf000 | |
107 | #define DEFAULT_RX_PREPEND 0 | |
108 | #define DEFAULT_PREAMBLE_LEN 7 | |
109 | #define DEFAULT_TX_PAUSE_TIME_EXTD 0 | |
110 | #define DEFAULT_NON_BACK_TO_BACK_IPG1 0x40 | |
111 | #define DEFAULT_NON_BACK_TO_BACK_IPG2 0x60 | |
112 | #define DEFAULT_MIN_IFG_ENFORCEMENT 0x50 | |
113 | #define DEFAULT_BACK_TO_BACK_IPG 0x60 | |
114 | #define DEFAULT_MAXIMUM_FRAME 0x600 | |
115 | ||
116 | /* register related defines (bits, field offsets..) */ | |
117 | #define DTSEC_ID2_INT_REDUCED_OFF 0x00010000 | |
118 | ||
119 | #define DTSEC_ECNTRL_GMIIM 0x00000040 | |
120 | #define DTSEC_ECNTRL_TBIM 0x00000020 | |
121 | #define DTSEC_ECNTRL_SGMIIM 0x00000002 | |
122 | #define DTSEC_ECNTRL_RPM 0x00000010 | |
123 | #define DTSEC_ECNTRL_R100M 0x00000008 | |
124 | #define DTSEC_ECNTRL_QSGMIIM 0x00000001 | |
125 | ||
e37425c2 | 126 | #define TCTRL_GTS 0x00000020 |
57ba4c9b IL |
127 | |
128 | #define RCTRL_PAL_MASK 0x001f0000 | |
129 | #define RCTRL_PAL_SHIFT 16 | |
130 | #define RCTRL_GHTX 0x00000400 | |
131 | #define RCTRL_GRS 0x00000020 | |
132 | #define RCTRL_MPROM 0x00000008 | |
133 | #define RCTRL_RSF 0x00000004 | |
134 | #define RCTRL_UPROM 0x00000001 | |
135 | ||
136 | #define MACCFG1_SOFT_RESET 0x80000000 | |
137 | #define MACCFG1_RX_FLOW 0x00000020 | |
138 | #define MACCFG1_TX_FLOW 0x00000010 | |
139 | #define MACCFG1_TX_EN 0x00000001 | |
140 | #define MACCFG1_RX_EN 0x00000004 | |
141 | ||
142 | #define MACCFG2_NIBBLE_MODE 0x00000100 | |
143 | #define MACCFG2_BYTE_MODE 0x00000200 | |
144 | #define MACCFG2_PAD_CRC_EN 0x00000004 | |
145 | #define MACCFG2_FULL_DUPLEX 0x00000001 | |
146 | #define MACCFG2_PREAMBLE_LENGTH_MASK 0x0000f000 | |
147 | #define MACCFG2_PREAMBLE_LENGTH_SHIFT 12 | |
148 | ||
149 | #define IPGIFG_NON_BACK_TO_BACK_IPG_1_SHIFT 24 | |
150 | #define IPGIFG_NON_BACK_TO_BACK_IPG_2_SHIFT 16 | |
151 | #define IPGIFG_MIN_IFG_ENFORCEMENT_SHIFT 8 | |
152 | ||
153 | #define IPGIFG_NON_BACK_TO_BACK_IPG_1 0x7F000000 | |
154 | #define IPGIFG_NON_BACK_TO_BACK_IPG_2 0x007F0000 | |
155 | #define IPGIFG_MIN_IFG_ENFORCEMENT 0x0000FF00 | |
156 | #define IPGIFG_BACK_TO_BACK_IPG 0x0000007F | |
157 | ||
158 | #define HAFDUP_EXCESS_DEFER 0x00010000 | |
159 | #define HAFDUP_COLLISION_WINDOW 0x000003ff | |
160 | #define HAFDUP_RETRANSMISSION_MAX_SHIFT 12 | |
161 | #define HAFDUP_RETRANSMISSION_MAX 0x0000f000 | |
162 | ||
163 | #define NUM_OF_HASH_REGS 8 /* Number of hash table registers */ | |
164 | ||
165 | #define PTV_PTE_MASK 0xffff0000 | |
166 | #define PTV_PT_MASK 0x0000ffff | |
167 | #define PTV_PTE_SHIFT 16 | |
168 | ||
169 | #define MAX_PACKET_ALIGNMENT 31 | |
170 | #define MAX_INTER_PACKET_GAP 0x7f | |
171 | #define MAX_RETRANSMISSION 0x0f | |
172 | #define MAX_COLLISION_WINDOW 0x03ff | |
173 | ||
174 | /* Hash table size (32 bits*8 regs) */ | |
175 | #define DTSEC_HASH_TABLE_SIZE 256 | |
176 | /* Extended Hash table size (32 bits*16 regs) */ | |
177 | #define EXTENDED_HASH_TABLE_SIZE 512 | |
178 | ||
179 | /* dTSEC Memory Map registers */ | |
180 | struct dtsec_regs { | |
181 | /* dTSEC General Control and Status Registers */ | |
182 | u32 tsec_id; /* 0x000 ETSEC_ID register */ | |
183 | u32 tsec_id2; /* 0x004 ETSEC_ID2 register */ | |
184 | u32 ievent; /* 0x008 Interrupt event register */ | |
185 | u32 imask; /* 0x00C Interrupt mask register */ | |
186 | u32 reserved0010[1]; | |
187 | u32 ecntrl; /* 0x014 E control register */ | |
188 | u32 ptv; /* 0x018 Pause time value register */ | |
189 | u32 tbipa; /* 0x01C TBI PHY address register */ | |
190 | u32 tmr_ctrl; /* 0x020 Time-stamp Control register */ | |
191 | u32 tmr_pevent; /* 0x024 Time-stamp event register */ | |
192 | u32 tmr_pemask; /* 0x028 Timer event mask register */ | |
193 | u32 reserved002c[5]; | |
194 | u32 tctrl; /* 0x040 Transmit control register */ | |
195 | u32 reserved0044[3]; | |
196 | u32 rctrl; /* 0x050 Receive control register */ | |
197 | u32 reserved0054[11]; | |
198 | u32 igaddr[8]; /* 0x080-0x09C Individual/group address */ | |
199 | u32 gaddr[8]; /* 0x0A0-0x0BC Group address registers 0-7 */ | |
200 | u32 reserved00c0[16]; | |
201 | u32 maccfg1; /* 0x100 MAC configuration #1 */ | |
202 | u32 maccfg2; /* 0x104 MAC configuration #2 */ | |
203 | u32 ipgifg; /* 0x108 IPG/IFG */ | |
204 | u32 hafdup; /* 0x10C Half-duplex */ | |
205 | u32 maxfrm; /* 0x110 Maximum frame */ | |
206 | u32 reserved0114[10]; | |
207 | u32 ifstat; /* 0x13C Interface status */ | |
208 | u32 macstnaddr1; /* 0x140 Station Address,part 1 */ | |
209 | u32 macstnaddr2; /* 0x144 Station Address,part 2 */ | |
210 | struct { | |
211 | u32 exact_match1; /* octets 1-4 */ | |
212 | u32 exact_match2; /* octets 5-6 */ | |
213 | } macaddr[15]; /* 0x148-0x1BC mac exact match addresses 1-15 */ | |
214 | u32 reserved01c0[16]; | |
215 | u32 tr64; /* 0x200 Tx and Rx 64 byte frame counter */ | |
216 | u32 tr127; /* 0x204 Tx and Rx 65 to 127 byte frame counter */ | |
217 | u32 tr255; /* 0x208 Tx and Rx 128 to 255 byte frame counter */ | |
218 | u32 tr511; /* 0x20C Tx and Rx 256 to 511 byte frame counter */ | |
219 | u32 tr1k; /* 0x210 Tx and Rx 512 to 1023 byte frame counter */ | |
220 | u32 trmax; /* 0x214 Tx and Rx 1024 to 1518 byte frame counter */ | |
221 | u32 trmgv; | |
222 | /* 0x218 Tx and Rx 1519 to 1522 byte good VLAN frame count */ | |
223 | u32 rbyt; /* 0x21C receive byte counter */ | |
224 | u32 rpkt; /* 0x220 receive packet counter */ | |
225 | u32 rfcs; /* 0x224 receive FCS error counter */ | |
226 | u32 rmca; /* 0x228 RMCA Rx multicast packet counter */ | |
227 | u32 rbca; /* 0x22C Rx broadcast packet counter */ | |
228 | u32 rxcf; /* 0x230 Rx control frame packet counter */ | |
229 | u32 rxpf; /* 0x234 Rx pause frame packet counter */ | |
230 | u32 rxuo; /* 0x238 Rx unknown OP code counter */ | |
231 | u32 raln; /* 0x23C Rx alignment error counter */ | |
232 | u32 rflr; /* 0x240 Rx frame length error counter */ | |
233 | u32 rcde; /* 0x244 Rx code error counter */ | |
234 | u32 rcse; /* 0x248 Rx carrier sense error counter */ | |
235 | u32 rund; /* 0x24C Rx undersize packet counter */ | |
236 | u32 rovr; /* 0x250 Rx oversize packet counter */ | |
237 | u32 rfrg; /* 0x254 Rx fragments counter */ | |
238 | u32 rjbr; /* 0x258 Rx jabber counter */ | |
239 | u32 rdrp; /* 0x25C Rx drop */ | |
240 | u32 tbyt; /* 0x260 Tx byte counter */ | |
241 | u32 tpkt; /* 0x264 Tx packet counter */ | |
242 | u32 tmca; /* 0x268 Tx multicast packet counter */ | |
243 | u32 tbca; /* 0x26C Tx broadcast packet counter */ | |
244 | u32 txpf; /* 0x270 Tx pause control frame counter */ | |
245 | u32 tdfr; /* 0x274 Tx deferral packet counter */ | |
246 | u32 tedf; /* 0x278 Tx excessive deferral packet counter */ | |
247 | u32 tscl; /* 0x27C Tx single collision packet counter */ | |
248 | u32 tmcl; /* 0x280 Tx multiple collision packet counter */ | |
249 | u32 tlcl; /* 0x284 Tx late collision packet counter */ | |
250 | u32 txcl; /* 0x288 Tx excessive collision packet counter */ | |
251 | u32 tncl; /* 0x28C Tx total collision counter */ | |
252 | u32 reserved0290[1]; | |
253 | u32 tdrp; /* 0x294 Tx drop frame counter */ | |
254 | u32 tjbr; /* 0x298 Tx jabber frame counter */ | |
255 | u32 tfcs; /* 0x29C Tx FCS error counter */ | |
256 | u32 txcf; /* 0x2A0 Tx control frame counter */ | |
257 | u32 tovr; /* 0x2A4 Tx oversize frame counter */ | |
258 | u32 tund; /* 0x2A8 Tx undersize frame counter */ | |
259 | u32 tfrg; /* 0x2AC Tx fragments frame counter */ | |
260 | u32 car1; /* 0x2B0 carry register one register* */ | |
261 | u32 car2; /* 0x2B4 carry register two register* */ | |
262 | u32 cam1; /* 0x2B8 carry register one mask register */ | |
263 | u32 cam2; /* 0x2BC carry register two mask register */ | |
264 | u32 reserved02c0[848]; | |
265 | }; | |
266 | ||
267 | /* struct dtsec_cfg - dTSEC configuration | |
268 | * Transmit half-duplex flow control, under software control for 10/100-Mbps | |
269 | * half-duplex media. If set, back pressure is applied to media by raising | |
270 | * carrier. | |
271 | * halfdup_retransmit: | |
272 | * Number of retransmission attempts following a collision. | |
273 | * If this is exceeded dTSEC aborts transmission due to excessive collisions. | |
274 | * The standard specifies the attempt limit to be 15. | |
275 | * halfdup_coll_window: | |
276 | * The number of bytes of the frame during which collisions may occur. | |
277 | * The default value of 55 corresponds to the frame byte at the end of the | |
278 | * standard 512-bit slot time window. If collisions are detected after this | |
279 | * byte, the late collision event is asserted and transmission of current | |
280 | * frame is aborted. | |
281 | * tx_pad_crc: | |
282 | * Pad and append CRC. If set, the MAC pads all ransmitted short frames and | |
283 | * appends a CRC to every frame regardless of padding requirement. | |
284 | * tx_pause_time: | |
285 | * Transmit pause time value. This pause value is used as part of the pause | |
286 | * frame to be sent when a transmit pause frame is initiated. | |
287 | * If set to 0 this disables transmission of pause frames. | |
288 | * preamble_len: | |
289 | * Length, in bytes, of the preamble field preceding each Ethernet | |
290 | * start-of-frame delimiter byte. The default value of 0x7 should be used in | |
291 | * order to guarantee reliable operation with IEEE 802.3 compliant hardware. | |
292 | * rx_prepend: | |
293 | * Packet alignment padding length. The specified number of bytes (1-31) | |
294 | * of zero padding are inserted before the start of each received frame. | |
295 | * For Ethernet, where optional preamble extraction is enabled, the padding | |
296 | * appears before the preamble, otherwise the padding precedes the | |
297 | * layer 2 header. | |
298 | * | |
299 | * This structure contains basic dTSEC configuration and must be passed to | |
300 | * init() function. A default set of configuration values can be | |
301 | * obtained by calling set_dflts(). | |
302 | */ | |
303 | struct dtsec_cfg { | |
304 | u16 halfdup_retransmit; | |
305 | u16 halfdup_coll_window; | |
306 | bool tx_pad_crc; | |
307 | u16 tx_pause_time; | |
308 | bool ptp_tsu_en; | |
309 | bool ptp_exception_en; | |
310 | u32 preamble_len; | |
311 | u32 rx_prepend; | |
312 | u16 tx_pause_time_extd; | |
313 | u16 maximum_frame; | |
314 | u32 non_back_to_back_ipg1; | |
315 | u32 non_back_to_back_ipg2; | |
316 | u32 min_ifg_enforcement; | |
317 | u32 back_to_back_ipg; | |
318 | }; | |
319 | ||
320 | struct fman_mac { | |
321 | /* pointer to dTSEC memory mapped registers */ | |
322 | struct dtsec_regs __iomem *regs; | |
323 | /* MAC address of device */ | |
324 | u64 addr; | |
325 | /* Ethernet physical interface */ | |
326 | phy_interface_t phy_if; | |
327 | u16 max_speed; | |
328 | void *dev_id; /* device cookie used by the exception cbs */ | |
329 | fman_mac_exception_cb *exception_cb; | |
330 | fman_mac_exception_cb *event_cb; | |
331 | /* Number of individual addresses in registers for this station */ | |
332 | u8 num_of_ind_addr_in_regs; | |
333 | /* pointer to driver's global address hash table */ | |
334 | struct eth_hash_t *multicast_addr_hash; | |
335 | /* pointer to driver's individual address hash table */ | |
336 | struct eth_hash_t *unicast_addr_hash; | |
337 | u8 mac_id; | |
338 | u32 exceptions; | |
339 | bool ptp_tsu_enabled; | |
f74f92be | 340 | bool en_tsu_err_exception; |
57ba4c9b IL |
341 | struct dtsec_cfg *dtsec_drv_param; |
342 | void *fm; | |
343 | struct fman_rev_info fm_rev_info; | |
344 | bool basex_if; | |
345 | struct phy_device *tbiphy; | |
346 | }; | |
347 | ||
348 | static void set_dflts(struct dtsec_cfg *cfg) | |
349 | { | |
350 | cfg->halfdup_retransmit = DEFAULT_HALFDUP_RETRANSMIT; | |
351 | cfg->halfdup_coll_window = DEFAULT_HALFDUP_COLL_WINDOW; | |
352 | cfg->tx_pad_crc = true; | |
353 | cfg->tx_pause_time = DEFAULT_TX_PAUSE_TIME; | |
354 | /* PHY address 0 is reserved (DPAA RM) */ | |
355 | cfg->rx_prepend = DEFAULT_RX_PREPEND; | |
356 | cfg->ptp_tsu_en = true; | |
357 | cfg->ptp_exception_en = true; | |
358 | cfg->preamble_len = DEFAULT_PREAMBLE_LEN; | |
359 | cfg->tx_pause_time_extd = DEFAULT_TX_PAUSE_TIME_EXTD; | |
360 | cfg->non_back_to_back_ipg1 = DEFAULT_NON_BACK_TO_BACK_IPG1; | |
361 | cfg->non_back_to_back_ipg2 = DEFAULT_NON_BACK_TO_BACK_IPG2; | |
362 | cfg->min_ifg_enforcement = DEFAULT_MIN_IFG_ENFORCEMENT; | |
363 | cfg->back_to_back_ipg = DEFAULT_BACK_TO_BACK_IPG; | |
364 | cfg->maximum_frame = DEFAULT_MAXIMUM_FRAME; | |
365 | } | |
366 | ||
367 | static int init(struct dtsec_regs __iomem *regs, struct dtsec_cfg *cfg, | |
368 | phy_interface_t iface, u16 iface_speed, u8 *macaddr, | |
369 | u32 exception_mask, u8 tbi_addr) | |
370 | { | |
371 | bool is_rgmii, is_sgmii, is_qsgmii; | |
372 | int i; | |
373 | u32 tmp; | |
374 | ||
375 | /* Soft reset */ | |
376 | iowrite32be(MACCFG1_SOFT_RESET, ®s->maccfg1); | |
377 | iowrite32be(0, ®s->maccfg1); | |
378 | ||
379 | /* dtsec_id2 */ | |
380 | tmp = ioread32be(®s->tsec_id2); | |
381 | ||
382 | /* check RGMII support */ | |
383 | if (iface == PHY_INTERFACE_MODE_RGMII || | |
b07e675b MB |
384 | iface == PHY_INTERFACE_MODE_RGMII_ID || |
385 | iface == PHY_INTERFACE_MODE_RGMII_RXID || | |
386 | iface == PHY_INTERFACE_MODE_RGMII_TXID || | |
57ba4c9b IL |
387 | iface == PHY_INTERFACE_MODE_RMII) |
388 | if (tmp & DTSEC_ID2_INT_REDUCED_OFF) | |
389 | return -EINVAL; | |
390 | ||
391 | if (iface == PHY_INTERFACE_MODE_SGMII || | |
392 | iface == PHY_INTERFACE_MODE_MII) | |
393 | if (tmp & DTSEC_ID2_INT_REDUCED_OFF) | |
394 | return -EINVAL; | |
395 | ||
b07e675b MB |
396 | is_rgmii = iface == PHY_INTERFACE_MODE_RGMII || |
397 | iface == PHY_INTERFACE_MODE_RGMII_ID || | |
398 | iface == PHY_INTERFACE_MODE_RGMII_RXID || | |
399 | iface == PHY_INTERFACE_MODE_RGMII_TXID; | |
57ba4c9b IL |
400 | is_sgmii = iface == PHY_INTERFACE_MODE_SGMII; |
401 | is_qsgmii = iface == PHY_INTERFACE_MODE_QSGMII; | |
402 | ||
403 | tmp = 0; | |
404 | if (is_rgmii || iface == PHY_INTERFACE_MODE_GMII) | |
405 | tmp |= DTSEC_ECNTRL_GMIIM; | |
406 | if (is_sgmii) | |
407 | tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM); | |
408 | if (is_qsgmii) | |
409 | tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM | | |
410 | DTSEC_ECNTRL_QSGMIIM); | |
411 | if (is_rgmii) | |
412 | tmp |= DTSEC_ECNTRL_RPM; | |
413 | if (iface_speed == SPEED_100) | |
414 | tmp |= DTSEC_ECNTRL_R100M; | |
415 | ||
416 | iowrite32be(tmp, ®s->ecntrl); | |
417 | ||
418 | tmp = 0; | |
419 | ||
420 | if (cfg->tx_pause_time) | |
421 | tmp |= cfg->tx_pause_time; | |
422 | if (cfg->tx_pause_time_extd) | |
423 | tmp |= cfg->tx_pause_time_extd << PTV_PTE_SHIFT; | |
424 | iowrite32be(tmp, ®s->ptv); | |
425 | ||
426 | tmp = 0; | |
427 | tmp |= (cfg->rx_prepend << RCTRL_PAL_SHIFT) & RCTRL_PAL_MASK; | |
428 | /* Accept short frames */ | |
429 | tmp |= RCTRL_RSF; | |
430 | ||
431 | iowrite32be(tmp, ®s->rctrl); | |
432 | ||
433 | /* Assign a Phy Address to the TBI (TBIPA). | |
434 | * Done also in cases where TBI is not selected to avoid conflict with | |
435 | * the external PHY's Physical address | |
436 | */ | |
437 | iowrite32be(tbi_addr, ®s->tbipa); | |
438 | ||
439 | iowrite32be(0, ®s->tmr_ctrl); | |
440 | ||
441 | if (cfg->ptp_tsu_en) { | |
442 | tmp = 0; | |
443 | tmp |= TMR_PEVENT_TSRE; | |
444 | iowrite32be(tmp, ®s->tmr_pevent); | |
445 | ||
446 | if (cfg->ptp_exception_en) { | |
447 | tmp = 0; | |
448 | tmp |= TMR_PEMASK_TSREEN; | |
449 | iowrite32be(tmp, ®s->tmr_pemask); | |
450 | } | |
451 | } | |
452 | ||
453 | tmp = 0; | |
454 | tmp |= MACCFG1_RX_FLOW; | |
455 | tmp |= MACCFG1_TX_FLOW; | |
456 | iowrite32be(tmp, ®s->maccfg1); | |
457 | ||
458 | tmp = 0; | |
459 | ||
460 | if (iface_speed < SPEED_1000) | |
461 | tmp |= MACCFG2_NIBBLE_MODE; | |
462 | else if (iface_speed == SPEED_1000) | |
463 | tmp |= MACCFG2_BYTE_MODE; | |
464 | ||
465 | tmp |= (cfg->preamble_len << MACCFG2_PREAMBLE_LENGTH_SHIFT) & | |
466 | MACCFG2_PREAMBLE_LENGTH_MASK; | |
467 | if (cfg->tx_pad_crc) | |
468 | tmp |= MACCFG2_PAD_CRC_EN; | |
469 | /* Full Duplex */ | |
470 | tmp |= MACCFG2_FULL_DUPLEX; | |
471 | iowrite32be(tmp, ®s->maccfg2); | |
472 | ||
473 | tmp = (((cfg->non_back_to_back_ipg1 << | |
474 | IPGIFG_NON_BACK_TO_BACK_IPG_1_SHIFT) | |
475 | & IPGIFG_NON_BACK_TO_BACK_IPG_1) | |
476 | | ((cfg->non_back_to_back_ipg2 << | |
477 | IPGIFG_NON_BACK_TO_BACK_IPG_2_SHIFT) | |
478 | & IPGIFG_NON_BACK_TO_BACK_IPG_2) | |
479 | | ((cfg->min_ifg_enforcement << IPGIFG_MIN_IFG_ENFORCEMENT_SHIFT) | |
480 | & IPGIFG_MIN_IFG_ENFORCEMENT) | |
481 | | (cfg->back_to_back_ipg & IPGIFG_BACK_TO_BACK_IPG)); | |
482 | iowrite32be(tmp, ®s->ipgifg); | |
483 | ||
484 | tmp = 0; | |
485 | tmp |= HAFDUP_EXCESS_DEFER; | |
486 | tmp |= ((cfg->halfdup_retransmit << HAFDUP_RETRANSMISSION_MAX_SHIFT) | |
487 | & HAFDUP_RETRANSMISSION_MAX); | |
488 | tmp |= (cfg->halfdup_coll_window & HAFDUP_COLLISION_WINDOW); | |
489 | ||
490 | iowrite32be(tmp, ®s->hafdup); | |
491 | ||
492 | /* Initialize Maximum frame length */ | |
493 | iowrite32be(cfg->maximum_frame, ®s->maxfrm); | |
494 | ||
495 | iowrite32be(0xffffffff, ®s->cam1); | |
496 | iowrite32be(0xffffffff, ®s->cam2); | |
497 | ||
498 | iowrite32be(exception_mask, ®s->imask); | |
499 | ||
500 | iowrite32be(0xffffffff, ®s->ievent); | |
501 | ||
502 | tmp = (u32)((macaddr[5] << 24) | | |
503 | (macaddr[4] << 16) | (macaddr[3] << 8) | macaddr[2]); | |
504 | iowrite32be(tmp, ®s->macstnaddr1); | |
505 | ||
506 | tmp = (u32)((macaddr[1] << 24) | (macaddr[0] << 16)); | |
507 | iowrite32be(tmp, ®s->macstnaddr2); | |
508 | ||
509 | /* HASH */ | |
510 | for (i = 0; i < NUM_OF_HASH_REGS; i++) { | |
511 | /* Initialize IADDRx */ | |
512 | iowrite32be(0, ®s->igaddr[i]); | |
513 | /* Initialize GADDRx */ | |
514 | iowrite32be(0, ®s->gaddr[i]); | |
515 | } | |
516 | ||
517 | return 0; | |
518 | } | |
519 | ||
520 | static void set_mac_address(struct dtsec_regs __iomem *regs, u8 *adr) | |
521 | { | |
522 | u32 tmp; | |
523 | ||
524 | tmp = (u32)((adr[5] << 24) | | |
525 | (adr[4] << 16) | (adr[3] << 8) | adr[2]); | |
526 | iowrite32be(tmp, ®s->macstnaddr1); | |
527 | ||
528 | tmp = (u32)((adr[1] << 24) | (adr[0] << 16)); | |
529 | iowrite32be(tmp, ®s->macstnaddr2); | |
530 | } | |
531 | ||
532 | static void set_bucket(struct dtsec_regs __iomem *regs, int bucket, | |
533 | bool enable) | |
534 | { | |
535 | int reg_idx = (bucket >> 5) & 0xf; | |
536 | int bit_idx = bucket & 0x1f; | |
537 | u32 bit_mask = 0x80000000 >> bit_idx; | |
538 | u32 __iomem *reg; | |
539 | ||
540 | if (reg_idx > 7) | |
541 | reg = ®s->gaddr[reg_idx - 8]; | |
542 | else | |
543 | reg = ®s->igaddr[reg_idx]; | |
544 | ||
545 | if (enable) | |
546 | iowrite32be(ioread32be(reg) | bit_mask, reg); | |
547 | else | |
548 | iowrite32be(ioread32be(reg) & (~bit_mask), reg); | |
549 | } | |
550 | ||
551 | static int check_init_parameters(struct fman_mac *dtsec) | |
552 | { | |
553 | if (dtsec->max_speed >= SPEED_10000) { | |
554 | pr_err("1G MAC driver supports 1G or lower speeds\n"); | |
555 | return -EINVAL; | |
556 | } | |
557 | if (dtsec->addr == 0) { | |
558 | pr_err("Ethernet MAC Must have a valid MAC Address\n"); | |
559 | return -EINVAL; | |
560 | } | |
561 | if ((dtsec->dtsec_drv_param)->rx_prepend > | |
562 | MAX_PACKET_ALIGNMENT) { | |
563 | pr_err("packetAlignmentPadding can't be > than %d\n", | |
564 | MAX_PACKET_ALIGNMENT); | |
565 | return -EINVAL; | |
566 | } | |
567 | if (((dtsec->dtsec_drv_param)->non_back_to_back_ipg1 > | |
568 | MAX_INTER_PACKET_GAP) || | |
569 | ((dtsec->dtsec_drv_param)->non_back_to_back_ipg2 > | |
570 | MAX_INTER_PACKET_GAP) || | |
571 | ((dtsec->dtsec_drv_param)->back_to_back_ipg > | |
572 | MAX_INTER_PACKET_GAP)) { | |
573 | pr_err("Inter packet gap can't be greater than %d\n", | |
574 | MAX_INTER_PACKET_GAP); | |
575 | return -EINVAL; | |
576 | } | |
577 | if ((dtsec->dtsec_drv_param)->halfdup_retransmit > | |
578 | MAX_RETRANSMISSION) { | |
579 | pr_err("maxRetransmission can't be greater than %d\n", | |
580 | MAX_RETRANSMISSION); | |
581 | return -EINVAL; | |
582 | } | |
583 | if ((dtsec->dtsec_drv_param)->halfdup_coll_window > | |
584 | MAX_COLLISION_WINDOW) { | |
585 | pr_err("collisionWindow can't be greater than %d\n", | |
586 | MAX_COLLISION_WINDOW); | |
587 | return -EINVAL; | |
588 | /* If Auto negotiation process is disabled, need to set up the PHY | |
589 | * using the MII Management Interface | |
590 | */ | |
591 | } | |
592 | if (!dtsec->exception_cb) { | |
593 | pr_err("uninitialized exception_cb\n"); | |
594 | return -EINVAL; | |
595 | } | |
596 | if (!dtsec->event_cb) { | |
597 | pr_err("uninitialized event_cb\n"); | |
598 | return -EINVAL; | |
599 | } | |
600 | ||
601 | return 0; | |
602 | } | |
603 | ||
604 | static int get_exception_flag(enum fman_mac_exceptions exception) | |
605 | { | |
606 | u32 bit_mask; | |
607 | ||
608 | switch (exception) { | |
609 | case FM_MAC_EX_1G_BAB_RX: | |
610 | bit_mask = DTSEC_IMASK_BREN; | |
611 | break; | |
612 | case FM_MAC_EX_1G_RX_CTL: | |
613 | bit_mask = DTSEC_IMASK_RXCEN; | |
614 | break; | |
615 | case FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET: | |
616 | bit_mask = DTSEC_IMASK_GTSCEN; | |
617 | break; | |
618 | case FM_MAC_EX_1G_BAB_TX: | |
619 | bit_mask = DTSEC_IMASK_BTEN; | |
620 | break; | |
621 | case FM_MAC_EX_1G_TX_CTL: | |
622 | bit_mask = DTSEC_IMASK_TXCEN; | |
623 | break; | |
624 | case FM_MAC_EX_1G_TX_ERR: | |
625 | bit_mask = DTSEC_IMASK_TXEEN; | |
626 | break; | |
627 | case FM_MAC_EX_1G_LATE_COL: | |
628 | bit_mask = DTSEC_IMASK_LCEN; | |
629 | break; | |
630 | case FM_MAC_EX_1G_COL_RET_LMT: | |
631 | bit_mask = DTSEC_IMASK_CRLEN; | |
632 | break; | |
633 | case FM_MAC_EX_1G_TX_FIFO_UNDRN: | |
634 | bit_mask = DTSEC_IMASK_XFUNEN; | |
635 | break; | |
636 | case FM_MAC_EX_1G_MAG_PCKT: | |
637 | bit_mask = DTSEC_IMASK_MAGEN; | |
638 | break; | |
639 | case FM_MAC_EX_1G_MII_MNG_RD_COMPLET: | |
640 | bit_mask = DTSEC_IMASK_MMRDEN; | |
641 | break; | |
642 | case FM_MAC_EX_1G_MII_MNG_WR_COMPLET: | |
643 | bit_mask = DTSEC_IMASK_MMWREN; | |
644 | break; | |
645 | case FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET: | |
646 | bit_mask = DTSEC_IMASK_GRSCEN; | |
647 | break; | |
648 | case FM_MAC_EX_1G_DATA_ERR: | |
649 | bit_mask = DTSEC_IMASK_TDPEEN; | |
650 | break; | |
651 | case FM_MAC_EX_1G_RX_MIB_CNT_OVFL: | |
652 | bit_mask = DTSEC_IMASK_MSROEN; | |
653 | break; | |
654 | default: | |
655 | bit_mask = 0; | |
656 | break; | |
657 | } | |
658 | ||
659 | return bit_mask; | |
660 | } | |
661 | ||
662 | static bool is_init_done(struct dtsec_cfg *dtsec_drv_params) | |
663 | { | |
664 | /* Checks if dTSEC driver parameters were initialized */ | |
665 | if (!dtsec_drv_params) | |
666 | return true; | |
667 | ||
668 | return false; | |
669 | } | |
670 | ||
671 | static u16 dtsec_get_max_frame_length(struct fman_mac *dtsec) | |
672 | { | |
673 | struct dtsec_regs __iomem *regs = dtsec->regs; | |
674 | ||
675 | if (is_init_done(dtsec->dtsec_drv_param)) | |
676 | return 0; | |
677 | ||
678 | return (u16)ioread32be(®s->maxfrm); | |
679 | } | |
680 | ||
681 | static void dtsec_isr(void *handle) | |
682 | { | |
683 | struct fman_mac *dtsec = (struct fman_mac *)handle; | |
684 | struct dtsec_regs __iomem *regs = dtsec->regs; | |
685 | u32 event; | |
686 | ||
687 | /* do not handle MDIO events */ | |
688 | event = ioread32be(®s->ievent) & | |
689 | (u32)(~(DTSEC_IMASK_MMRDEN | DTSEC_IMASK_MMWREN)); | |
690 | ||
691 | event &= ioread32be(®s->imask); | |
692 | ||
693 | iowrite32be(event, ®s->ievent); | |
694 | ||
695 | if (event & DTSEC_IMASK_BREN) | |
696 | dtsec->exception_cb(dtsec->dev_id, FM_MAC_EX_1G_BAB_RX); | |
697 | if (event & DTSEC_IMASK_RXCEN) | |
698 | dtsec->exception_cb(dtsec->dev_id, FM_MAC_EX_1G_RX_CTL); | |
699 | if (event & DTSEC_IMASK_GTSCEN) | |
700 | dtsec->exception_cb(dtsec->dev_id, | |
701 | FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET); | |
702 | if (event & DTSEC_IMASK_BTEN) | |
703 | dtsec->exception_cb(dtsec->dev_id, FM_MAC_EX_1G_BAB_TX); | |
704 | if (event & DTSEC_IMASK_TXCEN) | |
705 | dtsec->exception_cb(dtsec->dev_id, FM_MAC_EX_1G_TX_CTL); | |
706 | if (event & DTSEC_IMASK_TXEEN) | |
707 | dtsec->exception_cb(dtsec->dev_id, FM_MAC_EX_1G_TX_ERR); | |
708 | if (event & DTSEC_IMASK_LCEN) | |
709 | dtsec->exception_cb(dtsec->dev_id, FM_MAC_EX_1G_LATE_COL); | |
710 | if (event & DTSEC_IMASK_CRLEN) | |
711 | dtsec->exception_cb(dtsec->dev_id, FM_MAC_EX_1G_COL_RET_LMT); | |
712 | if (event & DTSEC_IMASK_XFUNEN) { | |
713 | /* FM_TX_LOCKUP_ERRATA_DTSEC6 Errata workaround */ | |
714 | if (dtsec->fm_rev_info.major == 2) { | |
715 | u32 tpkt1, tmp_reg1, tpkt2, tmp_reg2, i; | |
716 | /* a. Write 0x00E0_0C00 to DTSEC_ID | |
717 | * This is a read only register | |
718 | * b. Read and save the value of TPKT | |
719 | */ | |
720 | tpkt1 = ioread32be(®s->tpkt); | |
721 | ||
722 | /* c. Read the register at dTSEC address offset 0x32C */ | |
723 | tmp_reg1 = ioread32be(®s->reserved02c0[27]); | |
724 | ||
725 | /* d. Compare bits [9:15] to bits [25:31] of the | |
726 | * register at address offset 0x32C. | |
727 | */ | |
728 | if ((tmp_reg1 & 0x007F0000) != | |
729 | (tmp_reg1 & 0x0000007F)) { | |
730 | /* If they are not equal, save the value of | |
731 | * this register and wait for at least | |
732 | * MAXFRM*16 ns | |
733 | */ | |
734 | usleep_range((u32)(min | |
735 | (dtsec_get_max_frame_length(dtsec) * | |
736 | 16 / 1000, 1)), (u32) | |
737 | (min(dtsec_get_max_frame_length | |
738 | (dtsec) * 16 / 1000, 1) + 1)); | |
739 | } | |
740 | ||
741 | /* e. Read and save TPKT again and read the register | |
742 | * at dTSEC address offset 0x32C again | |
743 | */ | |
744 | tpkt2 = ioread32be(®s->tpkt); | |
745 | tmp_reg2 = ioread32be(®s->reserved02c0[27]); | |
746 | ||
747 | /* f. Compare the value of TPKT saved in step b to | |
748 | * value read in step e. Also compare bits [9:15] of | |
749 | * the register at offset 0x32C saved in step d to the | |
750 | * value of bits [9:15] saved in step e. If the two | |
751 | * registers values are unchanged, then the transmit | |
752 | * portion of the dTSEC controller is locked up and | |
753 | * the user should proceed to the recover sequence. | |
754 | */ | |
755 | if ((tpkt1 == tpkt2) && ((tmp_reg1 & 0x007F0000) == | |
756 | (tmp_reg2 & 0x007F0000))) { | |
757 | /* recover sequence */ | |
758 | ||
759 | /* a.Write a 1 to RCTRL[GRS] */ | |
760 | ||
761 | iowrite32be(ioread32be(®s->rctrl) | | |
762 | RCTRL_GRS, ®s->rctrl); | |
763 | ||
764 | /* b.Wait until IEVENT[GRSC]=1, or at least | |
765 | * 100 us has elapsed. | |
766 | */ | |
767 | for (i = 0; i < 100; i++) { | |
768 | if (ioread32be(®s->ievent) & | |
769 | DTSEC_IMASK_GRSCEN) | |
770 | break; | |
771 | udelay(1); | |
772 | } | |
773 | if (ioread32be(®s->ievent) & | |
774 | DTSEC_IMASK_GRSCEN) | |
775 | iowrite32be(DTSEC_IMASK_GRSCEN, | |
776 | ®s->ievent); | |
777 | else | |
778 | pr_debug("Rx lockup due to Tx lockup\n"); | |
779 | ||
780 | /* c.Write a 1 to bit n of FM_RSTC | |
781 | * (offset 0x0CC of FPM) | |
782 | */ | |
783 | fman_reset_mac(dtsec->fm, dtsec->mac_id); | |
784 | ||
785 | /* d.Wait 4 Tx clocks (32 ns) */ | |
786 | udelay(1); | |
787 | ||
788 | /* e.Write a 0 to bit n of FM_RSTC. */ | |
789 | /* cleared by FMAN | |
790 | */ | |
791 | } | |
792 | } | |
793 | ||
794 | dtsec->exception_cb(dtsec->dev_id, FM_MAC_EX_1G_TX_FIFO_UNDRN); | |
795 | } | |
796 | if (event & DTSEC_IMASK_MAGEN) | |
797 | dtsec->exception_cb(dtsec->dev_id, FM_MAC_EX_1G_MAG_PCKT); | |
798 | if (event & DTSEC_IMASK_GRSCEN) | |
799 | dtsec->exception_cb(dtsec->dev_id, | |
800 | FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET); | |
801 | if (event & DTSEC_IMASK_TDPEEN) | |
802 | dtsec->exception_cb(dtsec->dev_id, FM_MAC_EX_1G_DATA_ERR); | |
803 | if (event & DTSEC_IMASK_RDPEEN) | |
804 | dtsec->exception_cb(dtsec->dev_id, FM_MAC_1G_RX_DATA_ERR); | |
805 | ||
806 | /* masked interrupts */ | |
807 | WARN_ON(event & DTSEC_IMASK_ABRTEN); | |
808 | WARN_ON(event & DTSEC_IMASK_IFERREN); | |
809 | } | |
810 | ||
811 | static void dtsec_1588_isr(void *handle) | |
812 | { | |
813 | struct fman_mac *dtsec = (struct fman_mac *)handle; | |
814 | struct dtsec_regs __iomem *regs = dtsec->regs; | |
815 | u32 event; | |
816 | ||
817 | if (dtsec->ptp_tsu_enabled) { | |
818 | event = ioread32be(®s->tmr_pevent); | |
819 | event &= ioread32be(®s->tmr_pemask); | |
820 | ||
821 | if (event) { | |
822 | iowrite32be(event, ®s->tmr_pevent); | |
823 | WARN_ON(event & TMR_PEVENT_TSRE); | |
824 | dtsec->exception_cb(dtsec->dev_id, | |
825 | FM_MAC_EX_1G_1588_TS_RX_ERR); | |
826 | } | |
827 | } | |
828 | } | |
829 | ||
830 | static void free_init_resources(struct fman_mac *dtsec) | |
831 | { | |
832 | fman_unregister_intr(dtsec->fm, FMAN_MOD_MAC, dtsec->mac_id, | |
833 | FMAN_INTR_TYPE_ERR); | |
834 | fman_unregister_intr(dtsec->fm, FMAN_MOD_MAC, dtsec->mac_id, | |
835 | FMAN_INTR_TYPE_NORMAL); | |
836 | ||
837 | /* release the driver's group hash table */ | |
838 | free_hash_table(dtsec->multicast_addr_hash); | |
839 | dtsec->multicast_addr_hash = NULL; | |
840 | ||
841 | /* release the driver's individual hash table */ | |
842 | free_hash_table(dtsec->unicast_addr_hash); | |
843 | dtsec->unicast_addr_hash = NULL; | |
844 | } | |
845 | ||
846 | int dtsec_cfg_max_frame_len(struct fman_mac *dtsec, u16 new_val) | |
847 | { | |
848 | if (is_init_done(dtsec->dtsec_drv_param)) | |
849 | return -EINVAL; | |
850 | ||
851 | dtsec->dtsec_drv_param->maximum_frame = new_val; | |
852 | ||
853 | return 0; | |
854 | } | |
855 | ||
856 | int dtsec_cfg_pad_and_crc(struct fman_mac *dtsec, bool new_val) | |
857 | { | |
858 | if (is_init_done(dtsec->dtsec_drv_param)) | |
859 | return -EINVAL; | |
860 | ||
861 | dtsec->dtsec_drv_param->tx_pad_crc = new_val; | |
862 | ||
863 | return 0; | |
864 | } | |
865 | ||
e37425c2 FI |
866 | static void graceful_start(struct fman_mac *dtsec, enum comm_mode mode) |
867 | { | |
868 | struct dtsec_regs __iomem *regs = dtsec->regs; | |
869 | ||
870 | if (mode & COMM_MODE_TX) | |
871 | iowrite32be(ioread32be(®s->tctrl) & | |
872 | ~TCTRL_GTS, ®s->tctrl); | |
873 | if (mode & COMM_MODE_RX) | |
874 | iowrite32be(ioread32be(®s->rctrl) & | |
875 | ~RCTRL_GRS, ®s->rctrl); | |
876 | } | |
877 | ||
878 | static void graceful_stop(struct fman_mac *dtsec, enum comm_mode mode) | |
879 | { | |
880 | struct dtsec_regs __iomem *regs = dtsec->regs; | |
881 | u32 tmp; | |
882 | ||
883 | /* Graceful stop - Assert the graceful Rx stop bit */ | |
884 | if (mode & COMM_MODE_RX) { | |
885 | tmp = ioread32be(®s->rctrl) | RCTRL_GRS; | |
886 | iowrite32be(tmp, ®s->rctrl); | |
887 | ||
888 | if (dtsec->fm_rev_info.major == 2) { | |
889 | /* Workaround for dTSEC Errata A002 */ | |
890 | usleep_range(100, 200); | |
891 | } else { | |
892 | /* Workaround for dTSEC Errata A004839 */ | |
893 | usleep_range(10, 50); | |
894 | } | |
895 | } | |
896 | ||
897 | /* Graceful stop - Assert the graceful Tx stop bit */ | |
898 | if (mode & COMM_MODE_TX) { | |
899 | if (dtsec->fm_rev_info.major == 2) { | |
900 | /* dTSEC Errata A004: Do not use TCTRL[GTS]=1 */ | |
901 | pr_debug("GTS not supported due to DTSEC_A004 Errata.\n"); | |
902 | } else { | |
903 | tmp = ioread32be(®s->tctrl) | TCTRL_GTS; | |
904 | iowrite32be(tmp, ®s->tctrl); | |
905 | ||
906 | /* Workaround for dTSEC Errata A0012, A0014 */ | |
907 | usleep_range(10, 50); | |
908 | } | |
909 | } | |
910 | } | |
911 | ||
57ba4c9b IL |
912 | int dtsec_enable(struct fman_mac *dtsec, enum comm_mode mode) |
913 | { | |
914 | struct dtsec_regs __iomem *regs = dtsec->regs; | |
915 | u32 tmp; | |
916 | ||
917 | if (!is_init_done(dtsec->dtsec_drv_param)) | |
918 | return -EINVAL; | |
919 | ||
920 | /* Enable */ | |
921 | tmp = ioread32be(®s->maccfg1); | |
922 | if (mode & COMM_MODE_RX) | |
923 | tmp |= MACCFG1_RX_EN; | |
924 | if (mode & COMM_MODE_TX) | |
925 | tmp |= MACCFG1_TX_EN; | |
926 | ||
927 | iowrite32be(tmp, ®s->maccfg1); | |
928 | ||
e37425c2 FI |
929 | /* Graceful start - clear the graceful Rx/Tx stop bit */ |
930 | graceful_start(dtsec, mode); | |
57ba4c9b IL |
931 | |
932 | return 0; | |
933 | } | |
934 | ||
935 | int dtsec_disable(struct fman_mac *dtsec, enum comm_mode mode) | |
936 | { | |
937 | struct dtsec_regs __iomem *regs = dtsec->regs; | |
938 | u32 tmp; | |
939 | ||
940 | if (!is_init_done(dtsec->dtsec_drv_param)) | |
941 | return -EINVAL; | |
942 | ||
e37425c2 FI |
943 | /* Graceful stop - Assert the graceful Rx/Tx stop bit */ |
944 | graceful_stop(dtsec, mode); | |
57ba4c9b IL |
945 | |
946 | tmp = ioread32be(®s->maccfg1); | |
947 | if (mode & COMM_MODE_RX) | |
948 | tmp &= ~MACCFG1_RX_EN; | |
949 | if (mode & COMM_MODE_TX) | |
950 | tmp &= ~MACCFG1_TX_EN; | |
951 | ||
952 | iowrite32be(tmp, ®s->maccfg1); | |
953 | ||
954 | return 0; | |
955 | } | |
956 | ||
957 | int dtsec_set_tx_pause_frames(struct fman_mac *dtsec, | |
958 | u8 __maybe_unused priority, | |
959 | u16 pause_time, u16 __maybe_unused thresh_time) | |
960 | { | |
961 | struct dtsec_regs __iomem *regs = dtsec->regs; | |
e37425c2 | 962 | enum comm_mode mode = COMM_MODE_NONE; |
57ba4c9b IL |
963 | u32 ptv = 0; |
964 | ||
965 | if (!is_init_done(dtsec->dtsec_drv_param)) | |
966 | return -EINVAL; | |
967 | ||
e37425c2 FI |
968 | if ((ioread32be(®s->rctrl) & RCTRL_GRS) == 0) |
969 | mode |= COMM_MODE_RX; | |
970 | if ((ioread32be(®s->tctrl) & TCTRL_GTS) == 0) | |
971 | mode |= COMM_MODE_TX; | |
972 | ||
973 | graceful_stop(dtsec, mode); | |
974 | ||
7c82a7b9 IL |
975 | if (pause_time) { |
976 | /* FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 Errata workaround */ | |
977 | if (dtsec->fm_rev_info.major == 2 && pause_time <= 320) { | |
57ba4c9b IL |
978 | pr_warn("pause-time: %d illegal.Should be > 320\n", |
979 | pause_time); | |
980 | return -EINVAL; | |
981 | } | |
982 | ||
57ba4c9b IL |
983 | ptv = ioread32be(®s->ptv); |
984 | ptv &= PTV_PTE_MASK; | |
985 | ptv |= pause_time & PTV_PT_MASK; | |
986 | iowrite32be(ptv, ®s->ptv); | |
987 | ||
988 | /* trigger the transmission of a flow-control pause frame */ | |
989 | iowrite32be(ioread32be(®s->maccfg1) | MACCFG1_TX_FLOW, | |
990 | ®s->maccfg1); | |
991 | } else | |
992 | iowrite32be(ioread32be(®s->maccfg1) & ~MACCFG1_TX_FLOW, | |
993 | ®s->maccfg1); | |
994 | ||
e37425c2 FI |
995 | graceful_start(dtsec, mode); |
996 | ||
57ba4c9b IL |
997 | return 0; |
998 | } | |
999 | ||
1000 | int dtsec_accept_rx_pause_frames(struct fman_mac *dtsec, bool en) | |
1001 | { | |
1002 | struct dtsec_regs __iomem *regs = dtsec->regs; | |
e37425c2 | 1003 | enum comm_mode mode = COMM_MODE_NONE; |
57ba4c9b IL |
1004 | u32 tmp; |
1005 | ||
1006 | if (!is_init_done(dtsec->dtsec_drv_param)) | |
1007 | return -EINVAL; | |
1008 | ||
e37425c2 FI |
1009 | if ((ioread32be(®s->rctrl) & RCTRL_GRS) == 0) |
1010 | mode |= COMM_MODE_RX; | |
1011 | if ((ioread32be(®s->tctrl) & TCTRL_GTS) == 0) | |
1012 | mode |= COMM_MODE_TX; | |
1013 | ||
1014 | graceful_stop(dtsec, mode); | |
1015 | ||
57ba4c9b IL |
1016 | tmp = ioread32be(®s->maccfg1); |
1017 | if (en) | |
1018 | tmp |= MACCFG1_RX_FLOW; | |
1019 | else | |
1020 | tmp &= ~MACCFG1_RX_FLOW; | |
1021 | iowrite32be(tmp, ®s->maccfg1); | |
1022 | ||
e37425c2 FI |
1023 | graceful_start(dtsec, mode); |
1024 | ||
57ba4c9b IL |
1025 | return 0; |
1026 | } | |
1027 | ||
1028 | int dtsec_modify_mac_address(struct fman_mac *dtsec, enet_addr_t *enet_addr) | |
1029 | { | |
e37425c2 FI |
1030 | struct dtsec_regs __iomem *regs = dtsec->regs; |
1031 | enum comm_mode mode = COMM_MODE_NONE; | |
1032 | ||
57ba4c9b IL |
1033 | if (!is_init_done(dtsec->dtsec_drv_param)) |
1034 | return -EINVAL; | |
1035 | ||
e37425c2 FI |
1036 | if ((ioread32be(®s->rctrl) & RCTRL_GRS) == 0) |
1037 | mode |= COMM_MODE_RX; | |
1038 | if ((ioread32be(®s->tctrl) & TCTRL_GTS) == 0) | |
1039 | mode |= COMM_MODE_TX; | |
1040 | ||
1041 | graceful_stop(dtsec, mode); | |
1042 | ||
57ba4c9b IL |
1043 | /* Initialize MAC Station Address registers (1 & 2) |
1044 | * Station address have to be swapped (big endian to little endian | |
1045 | */ | |
1046 | dtsec->addr = ENET_ADDR_TO_UINT64(*enet_addr); | |
1047 | set_mac_address(dtsec->regs, (u8 *)(*enet_addr)); | |
1048 | ||
e37425c2 FI |
1049 | graceful_start(dtsec, mode); |
1050 | ||
57ba4c9b IL |
1051 | return 0; |
1052 | } | |
1053 | ||
1054 | int dtsec_add_hash_mac_address(struct fman_mac *dtsec, enet_addr_t *eth_addr) | |
1055 | { | |
1056 | struct dtsec_regs __iomem *regs = dtsec->regs; | |
1057 | struct eth_hash_entry *hash_entry; | |
1058 | u64 addr; | |
1059 | s32 bucket; | |
1060 | u32 crc = 0xFFFFFFFF; | |
1061 | bool mcast, ghtx; | |
1062 | ||
1063 | if (!is_init_done(dtsec->dtsec_drv_param)) | |
1064 | return -EINVAL; | |
1065 | ||
1066 | addr = ENET_ADDR_TO_UINT64(*eth_addr); | |
1067 | ||
1068 | ghtx = (bool)((ioread32be(®s->rctrl) & RCTRL_GHTX) ? true : false); | |
1069 | mcast = (bool)((addr & MAC_GROUP_ADDRESS) ? true : false); | |
1070 | ||
1071 | /* Cannot handle unicast mac addr when GHTX is on */ | |
1072 | if (ghtx && !mcast) { | |
1073 | pr_err("Could not compute hash bucket\n"); | |
1074 | return -EINVAL; | |
1075 | } | |
1076 | crc = crc32_le(crc, (u8 *)eth_addr, ETH_ALEN); | |
1077 | crc = bitrev32(crc); | |
1078 | ||
1079 | /* considering the 9 highest order bits in crc H[8:0]: | |
1080 | *if ghtx = 0 H[8:6] (highest order 3 bits) identify the hash register | |
1081 | *and H[5:1] (next 5 bits) identify the hash bit | |
1082 | *if ghts = 1 H[8:5] (highest order 4 bits) identify the hash register | |
1083 | *and H[4:0] (next 5 bits) identify the hash bit. | |
1084 | * | |
1085 | *In bucket index output the low 5 bits identify the hash register | |
1086 | *bit, while the higher 4 bits identify the hash register | |
1087 | */ | |
1088 | ||
1089 | if (ghtx) { | |
1090 | bucket = (s32)((crc >> 23) & 0x1ff); | |
1091 | } else { | |
1092 | bucket = (s32)((crc >> 24) & 0xff); | |
1093 | /* if !ghtx and mcast the bit must be set in gaddr instead of | |
1094 | *igaddr. | |
1095 | */ | |
1096 | if (mcast) | |
1097 | bucket += 0x100; | |
1098 | } | |
1099 | ||
1100 | set_bucket(dtsec->regs, bucket, true); | |
1101 | ||
1102 | /* Create element to be added to the driver hash table */ | |
803fafbe | 1103 | hash_entry = kmalloc(sizeof(*hash_entry), GFP_ATOMIC); |
57ba4c9b IL |
1104 | if (!hash_entry) |
1105 | return -ENOMEM; | |
1106 | hash_entry->addr = addr; | |
1107 | INIT_LIST_HEAD(&hash_entry->node); | |
1108 | ||
1109 | if (addr & MAC_GROUP_ADDRESS) | |
1110 | /* Group Address */ | |
1111 | list_add_tail(&hash_entry->node, | |
1112 | &dtsec->multicast_addr_hash->lsts[bucket]); | |
1113 | else | |
1114 | list_add_tail(&hash_entry->node, | |
1115 | &dtsec->unicast_addr_hash->lsts[bucket]); | |
1116 | ||
1117 | return 0; | |
1118 | } | |
1119 | ||
1120 | int dtsec_del_hash_mac_address(struct fman_mac *dtsec, enet_addr_t *eth_addr) | |
1121 | { | |
1122 | struct dtsec_regs __iomem *regs = dtsec->regs; | |
1123 | struct list_head *pos; | |
1124 | struct eth_hash_entry *hash_entry = NULL; | |
1125 | u64 addr; | |
1126 | s32 bucket; | |
1127 | u32 crc = 0xFFFFFFFF; | |
1128 | bool mcast, ghtx; | |
1129 | ||
1130 | if (!is_init_done(dtsec->dtsec_drv_param)) | |
1131 | return -EINVAL; | |
1132 | ||
1133 | addr = ENET_ADDR_TO_UINT64(*eth_addr); | |
1134 | ||
1135 | ghtx = (bool)((ioread32be(®s->rctrl) & RCTRL_GHTX) ? true : false); | |
1136 | mcast = (bool)((addr & MAC_GROUP_ADDRESS) ? true : false); | |
1137 | ||
1138 | /* Cannot handle unicast mac addr when GHTX is on */ | |
1139 | if (ghtx && !mcast) { | |
1140 | pr_err("Could not compute hash bucket\n"); | |
1141 | return -EINVAL; | |
1142 | } | |
1143 | crc = crc32_le(crc, (u8 *)eth_addr, ETH_ALEN); | |
1144 | crc = bitrev32(crc); | |
1145 | ||
1146 | if (ghtx) { | |
1147 | bucket = (s32)((crc >> 23) & 0x1ff); | |
1148 | } else { | |
1149 | bucket = (s32)((crc >> 24) & 0xff); | |
1150 | /* if !ghtx and mcast the bit must be set | |
1151 | * in gaddr instead of igaddr. | |
1152 | */ | |
1153 | if (mcast) | |
1154 | bucket += 0x100; | |
1155 | } | |
1156 | ||
1157 | if (addr & MAC_GROUP_ADDRESS) { | |
1158 | /* Group Address */ | |
1159 | list_for_each(pos, | |
1160 | &dtsec->multicast_addr_hash->lsts[bucket]) { | |
1161 | hash_entry = ETH_HASH_ENTRY_OBJ(pos); | |
1162 | if (hash_entry->addr == addr) { | |
1163 | list_del_init(&hash_entry->node); | |
1164 | kfree(hash_entry); | |
1165 | break; | |
1166 | } | |
1167 | } | |
1168 | if (list_empty(&dtsec->multicast_addr_hash->lsts[bucket])) | |
1169 | set_bucket(dtsec->regs, bucket, false); | |
1170 | } else { | |
1171 | /* Individual Address */ | |
1172 | list_for_each(pos, | |
1173 | &dtsec->unicast_addr_hash->lsts[bucket]) { | |
1174 | hash_entry = ETH_HASH_ENTRY_OBJ(pos); | |
1175 | if (hash_entry->addr == addr) { | |
1176 | list_del_init(&hash_entry->node); | |
1177 | kfree(hash_entry); | |
1178 | break; | |
1179 | } | |
1180 | } | |
1181 | if (list_empty(&dtsec->unicast_addr_hash->lsts[bucket])) | |
1182 | set_bucket(dtsec->regs, bucket, false); | |
1183 | } | |
1184 | ||
1185 | /* address does not exist */ | |
1186 | WARN_ON(!hash_entry); | |
1187 | ||
1188 | return 0; | |
1189 | } | |
1190 | ||
1191 | int dtsec_set_promiscuous(struct fman_mac *dtsec, bool new_val) | |
1192 | { | |
1193 | struct dtsec_regs __iomem *regs = dtsec->regs; | |
1194 | u32 tmp; | |
1195 | ||
1196 | if (!is_init_done(dtsec->dtsec_drv_param)) | |
1197 | return -EINVAL; | |
1198 | ||
1199 | /* Set unicast promiscuous */ | |
1200 | tmp = ioread32be(®s->rctrl); | |
1201 | if (new_val) | |
1202 | tmp |= RCTRL_UPROM; | |
1203 | else | |
1204 | tmp &= ~RCTRL_UPROM; | |
1205 | ||
1206 | iowrite32be(tmp, ®s->rctrl); | |
1207 | ||
1208 | /* Set multicast promiscuous */ | |
1209 | tmp = ioread32be(®s->rctrl); | |
1210 | if (new_val) | |
1211 | tmp |= RCTRL_MPROM; | |
1212 | else | |
1213 | tmp &= ~RCTRL_MPROM; | |
1214 | ||
1215 | iowrite32be(tmp, ®s->rctrl); | |
1216 | ||
1217 | return 0; | |
1218 | } | |
1219 | ||
1220 | int dtsec_adjust_link(struct fman_mac *dtsec, u16 speed) | |
1221 | { | |
1222 | struct dtsec_regs __iomem *regs = dtsec->regs; | |
e37425c2 | 1223 | enum comm_mode mode = COMM_MODE_NONE; |
57ba4c9b IL |
1224 | u32 tmp; |
1225 | ||
1226 | if (!is_init_done(dtsec->dtsec_drv_param)) | |
1227 | return -EINVAL; | |
1228 | ||
e37425c2 FI |
1229 | if ((ioread32be(®s->rctrl) & RCTRL_GRS) == 0) |
1230 | mode |= COMM_MODE_RX; | |
1231 | if ((ioread32be(®s->tctrl) & TCTRL_GTS) == 0) | |
1232 | mode |= COMM_MODE_TX; | |
1233 | ||
1234 | graceful_stop(dtsec, mode); | |
1235 | ||
57ba4c9b IL |
1236 | tmp = ioread32be(®s->maccfg2); |
1237 | ||
1238 | /* Full Duplex */ | |
1239 | tmp |= MACCFG2_FULL_DUPLEX; | |
1240 | ||
1241 | tmp &= ~(MACCFG2_NIBBLE_MODE | MACCFG2_BYTE_MODE); | |
1242 | if (speed < SPEED_1000) | |
1243 | tmp |= MACCFG2_NIBBLE_MODE; | |
1244 | else if (speed == SPEED_1000) | |
1245 | tmp |= MACCFG2_BYTE_MODE; | |
1246 | iowrite32be(tmp, ®s->maccfg2); | |
1247 | ||
1248 | tmp = ioread32be(®s->ecntrl); | |
1249 | if (speed == SPEED_100) | |
1250 | tmp |= DTSEC_ECNTRL_R100M; | |
1251 | else | |
1252 | tmp &= ~DTSEC_ECNTRL_R100M; | |
1253 | iowrite32be(tmp, ®s->ecntrl); | |
1254 | ||
e37425c2 FI |
1255 | graceful_start(dtsec, mode); |
1256 | ||
57ba4c9b IL |
1257 | return 0; |
1258 | } | |
1259 | ||
1260 | int dtsec_restart_autoneg(struct fman_mac *dtsec) | |
1261 | { | |
1262 | u16 tmp_reg16; | |
1263 | ||
1264 | if (!is_init_done(dtsec->dtsec_drv_param)) | |
1265 | return -EINVAL; | |
1266 | ||
1267 | tmp_reg16 = phy_read(dtsec->tbiphy, MII_BMCR); | |
1268 | ||
1269 | tmp_reg16 &= ~(BMCR_SPEED100 | BMCR_SPEED1000); | |
1270 | tmp_reg16 |= (BMCR_ANENABLE | BMCR_ANRESTART | | |
1271 | BMCR_FULLDPLX | BMCR_SPEED1000); | |
1272 | ||
1273 | phy_write(dtsec->tbiphy, MII_BMCR, tmp_reg16); | |
1274 | ||
1275 | return 0; | |
1276 | } | |
1277 | ||
1278 | int dtsec_get_version(struct fman_mac *dtsec, u32 *mac_version) | |
1279 | { | |
1280 | struct dtsec_regs __iomem *regs = dtsec->regs; | |
1281 | ||
1282 | if (!is_init_done(dtsec->dtsec_drv_param)) | |
1283 | return -EINVAL; | |
1284 | ||
1285 | *mac_version = ioread32be(®s->tsec_id); | |
1286 | ||
1287 | return 0; | |
1288 | } | |
1289 | ||
1290 | int dtsec_set_exception(struct fman_mac *dtsec, | |
1291 | enum fman_mac_exceptions exception, bool enable) | |
1292 | { | |
1293 | struct dtsec_regs __iomem *regs = dtsec->regs; | |
1294 | u32 bit_mask = 0; | |
1295 | ||
1296 | if (!is_init_done(dtsec->dtsec_drv_param)) | |
1297 | return -EINVAL; | |
1298 | ||
1299 | if (exception != FM_MAC_EX_1G_1588_TS_RX_ERR) { | |
1300 | bit_mask = get_exception_flag(exception); | |
1301 | if (bit_mask) { | |
1302 | if (enable) | |
1303 | dtsec->exceptions |= bit_mask; | |
1304 | else | |
1305 | dtsec->exceptions &= ~bit_mask; | |
1306 | } else { | |
1307 | pr_err("Undefined exception\n"); | |
1308 | return -EINVAL; | |
1309 | } | |
1310 | if (enable) | |
1311 | iowrite32be(ioread32be(®s->imask) | bit_mask, | |
1312 | ®s->imask); | |
1313 | else | |
1314 | iowrite32be(ioread32be(®s->imask) & ~bit_mask, | |
1315 | ®s->imask); | |
1316 | } else { | |
1317 | if (!dtsec->ptp_tsu_enabled) { | |
1318 | pr_err("Exception valid for 1588 only\n"); | |
1319 | return -EINVAL; | |
1320 | } | |
1321 | switch (exception) { | |
1322 | case FM_MAC_EX_1G_1588_TS_RX_ERR: | |
1323 | if (enable) { | |
f74f92be | 1324 | dtsec->en_tsu_err_exception = true; |
57ba4c9b IL |
1325 | iowrite32be(ioread32be(®s->tmr_pemask) | |
1326 | TMR_PEMASK_TSREEN, | |
1327 | ®s->tmr_pemask); | |
1328 | } else { | |
f74f92be | 1329 | dtsec->en_tsu_err_exception = false; |
57ba4c9b IL |
1330 | iowrite32be(ioread32be(®s->tmr_pemask) & |
1331 | ~TMR_PEMASK_TSREEN, | |
1332 | ®s->tmr_pemask); | |
1333 | } | |
1334 | break; | |
1335 | default: | |
1336 | pr_err("Undefined exception\n"); | |
1337 | return -EINVAL; | |
1338 | } | |
1339 | } | |
1340 | ||
1341 | return 0; | |
1342 | } | |
1343 | ||
1344 | int dtsec_init(struct fman_mac *dtsec) | |
1345 | { | |
1346 | struct dtsec_regs __iomem *regs = dtsec->regs; | |
1347 | struct dtsec_cfg *dtsec_drv_param; | |
1348 | int err; | |
1349 | u16 max_frm_ln; | |
1350 | enet_addr_t eth_addr; | |
1351 | ||
1352 | if (is_init_done(dtsec->dtsec_drv_param)) | |
1353 | return -EINVAL; | |
1354 | ||
1355 | if (DEFAULT_RESET_ON_INIT && | |
1356 | (fman_reset_mac(dtsec->fm, dtsec->mac_id) != 0)) { | |
1357 | pr_err("Can't reset MAC!\n"); | |
1358 | return -EINVAL; | |
1359 | } | |
1360 | ||
1361 | err = check_init_parameters(dtsec); | |
1362 | if (err) | |
1363 | return err; | |
1364 | ||
1365 | dtsec_drv_param = dtsec->dtsec_drv_param; | |
1366 | ||
1367 | MAKE_ENET_ADDR_FROM_UINT64(dtsec->addr, eth_addr); | |
1368 | ||
1369 | err = init(dtsec->regs, dtsec_drv_param, dtsec->phy_if, | |
1370 | dtsec->max_speed, (u8 *)eth_addr, dtsec->exceptions, | |
e5a03bfd | 1371 | dtsec->tbiphy->mdio.addr); |
57ba4c9b IL |
1372 | if (err) { |
1373 | free_init_resources(dtsec); | |
1374 | pr_err("DTSEC version doesn't support this i/f mode\n"); | |
1375 | return err; | |
1376 | } | |
1377 | ||
1378 | if (dtsec->phy_if == PHY_INTERFACE_MODE_SGMII) { | |
1379 | u16 tmp_reg16; | |
1380 | ||
1381 | /* Configure the TBI PHY Control Register */ | |
1382 | tmp_reg16 = TBICON_CLK_SELECT | TBICON_SOFT_RESET; | |
1383 | phy_write(dtsec->tbiphy, MII_TBICON, tmp_reg16); | |
1384 | ||
1385 | tmp_reg16 = TBICON_CLK_SELECT; | |
1386 | phy_write(dtsec->tbiphy, MII_TBICON, tmp_reg16); | |
1387 | ||
1388 | tmp_reg16 = (BMCR_RESET | BMCR_ANENABLE | | |
1389 | BMCR_FULLDPLX | BMCR_SPEED1000); | |
1390 | phy_write(dtsec->tbiphy, MII_BMCR, tmp_reg16); | |
1391 | ||
1392 | if (dtsec->basex_if) | |
1393 | tmp_reg16 = TBIANA_1000X; | |
1394 | else | |
1395 | tmp_reg16 = TBIANA_SGMII; | |
1396 | phy_write(dtsec->tbiphy, MII_ADVERTISE, tmp_reg16); | |
1397 | ||
1398 | tmp_reg16 = (BMCR_ANENABLE | BMCR_ANRESTART | | |
1399 | BMCR_FULLDPLX | BMCR_SPEED1000); | |
1400 | ||
1401 | phy_write(dtsec->tbiphy, MII_BMCR, tmp_reg16); | |
1402 | } | |
1403 | ||
1404 | /* Max Frame Length */ | |
1405 | max_frm_ln = (u16)ioread32be(®s->maxfrm); | |
1406 | err = fman_set_mac_max_frame(dtsec->fm, dtsec->mac_id, max_frm_ln); | |
1407 | if (err) { | |
1408 | pr_err("Setting max frame length failed\n"); | |
1409 | free_init_resources(dtsec); | |
1410 | return -EINVAL; | |
1411 | } | |
1412 | ||
1413 | dtsec->multicast_addr_hash = | |
1414 | alloc_hash_table(EXTENDED_HASH_TABLE_SIZE); | |
1415 | if (!dtsec->multicast_addr_hash) { | |
1416 | free_init_resources(dtsec); | |
1417 | pr_err("MC hash table is failed\n"); | |
1418 | return -ENOMEM; | |
1419 | } | |
1420 | ||
1421 | dtsec->unicast_addr_hash = alloc_hash_table(DTSEC_HASH_TABLE_SIZE); | |
1422 | if (!dtsec->unicast_addr_hash) { | |
1423 | free_init_resources(dtsec); | |
1424 | pr_err("UC hash table is failed\n"); | |
1425 | return -ENOMEM; | |
1426 | } | |
1427 | ||
1428 | /* register err intr handler for dtsec to FPM (err) */ | |
1429 | fman_register_intr(dtsec->fm, FMAN_MOD_MAC, dtsec->mac_id, | |
1430 | FMAN_INTR_TYPE_ERR, dtsec_isr, dtsec); | |
1431 | /* register 1588 intr handler for TMR to FPM (normal) */ | |
1432 | fman_register_intr(dtsec->fm, FMAN_MOD_MAC, dtsec->mac_id, | |
1433 | FMAN_INTR_TYPE_NORMAL, dtsec_1588_isr, dtsec); | |
1434 | ||
1435 | kfree(dtsec_drv_param); | |
1436 | dtsec->dtsec_drv_param = NULL; | |
1437 | ||
1438 | return 0; | |
1439 | } | |
1440 | ||
1441 | int dtsec_free(struct fman_mac *dtsec) | |
1442 | { | |
1443 | free_init_resources(dtsec); | |
1444 | ||
1445 | kfree(dtsec->dtsec_drv_param); | |
1446 | dtsec->dtsec_drv_param = NULL; | |
1447 | kfree(dtsec); | |
1448 | ||
1449 | return 0; | |
1450 | } | |
1451 | ||
1452 | struct fman_mac *dtsec_config(struct fman_mac_params *params) | |
1453 | { | |
1454 | struct fman_mac *dtsec; | |
1455 | struct dtsec_cfg *dtsec_drv_param; | |
1456 | void __iomem *base_addr; | |
1457 | ||
1458 | base_addr = params->base_addr; | |
1459 | ||
1460 | /* allocate memory for the UCC GETH data structure. */ | |
1461 | dtsec = kzalloc(sizeof(*dtsec), GFP_KERNEL); | |
1462 | if (!dtsec) | |
1463 | return NULL; | |
1464 | ||
1465 | /* allocate memory for the d_tsec driver parameters data structure. */ | |
1466 | dtsec_drv_param = kzalloc(sizeof(*dtsec_drv_param), GFP_KERNEL); | |
1467 | if (!dtsec_drv_param) | |
1468 | goto err_dtsec; | |
1469 | ||
1470 | /* Plant parameter structure pointer */ | |
1471 | dtsec->dtsec_drv_param = dtsec_drv_param; | |
1472 | ||
1473 | set_dflts(dtsec_drv_param); | |
1474 | ||
1475 | dtsec->regs = base_addr; | |
1476 | dtsec->addr = ENET_ADDR_TO_UINT64(params->addr); | |
1477 | dtsec->max_speed = params->max_speed; | |
1478 | dtsec->phy_if = params->phy_if; | |
1479 | dtsec->mac_id = params->mac_id; | |
1480 | dtsec->exceptions = (DTSEC_IMASK_BREN | | |
1481 | DTSEC_IMASK_RXCEN | | |
1482 | DTSEC_IMASK_BTEN | | |
1483 | DTSEC_IMASK_TXCEN | | |
1484 | DTSEC_IMASK_TXEEN | | |
1485 | DTSEC_IMASK_ABRTEN | | |
1486 | DTSEC_IMASK_LCEN | | |
1487 | DTSEC_IMASK_CRLEN | | |
1488 | DTSEC_IMASK_XFUNEN | | |
1489 | DTSEC_IMASK_IFERREN | | |
1490 | DTSEC_IMASK_MAGEN | | |
1491 | DTSEC_IMASK_TDPEEN | | |
1492 | DTSEC_IMASK_RDPEEN); | |
1493 | dtsec->exception_cb = params->exception_cb; | |
1494 | dtsec->event_cb = params->event_cb; | |
1495 | dtsec->dev_id = params->dev_id; | |
1496 | dtsec->ptp_tsu_enabled = dtsec->dtsec_drv_param->ptp_tsu_en; | |
f74f92be | 1497 | dtsec->en_tsu_err_exception = dtsec->dtsec_drv_param->ptp_exception_en; |
57ba4c9b IL |
1498 | |
1499 | dtsec->fm = params->fm; | |
1500 | dtsec->basex_if = params->basex_if; | |
1501 | ||
1502 | if (!params->internal_phy_node) { | |
1503 | pr_err("TBI PHY node is not available\n"); | |
1504 | goto err_dtsec_drv_param; | |
1505 | } | |
1506 | ||
1507 | dtsec->tbiphy = of_phy_find_device(params->internal_phy_node); | |
1508 | if (!dtsec->tbiphy) { | |
1509 | pr_err("of_phy_find_device (TBI PHY) failed\n"); | |
57ba4c9b IL |
1510 | goto err_dtsec_drv_param; |
1511 | } | |
1512 | ||
e5a03bfd | 1513 | put_device(&dtsec->tbiphy->mdio.dev); |
57ba4c9b IL |
1514 | |
1515 | /* Save FMan revision */ | |
1516 | fman_get_revision(dtsec->fm, &dtsec->fm_rev_info); | |
1517 | ||
1518 | return dtsec; | |
1519 | ||
1520 | err_dtsec_drv_param: | |
1521 | kfree(dtsec_drv_param); | |
1522 | err_dtsec: | |
1523 | kfree(dtsec); | |
1524 | return NULL; | |
1525 | } |