]> err.no Git - linux-2.6/blob - drivers/net/chelsio/pm3393.c
Merge /spare/repo/linux-2.6/
[linux-2.6] / drivers / net / chelsio / pm3393.c
1 /*****************************************************************************
2  *                                                                           *
3  * File: pm3393.c                                                            *
4  * $Revision: 1.9 $                                                          *
5  * $Date: 2005/03/23 07:41:27 $                                              *
6  * Description:                                                              *
7  *  PMC/SIERRA (pm3393) MAC-PHY functionality.                               *
8  *  part of the Chelsio 10Gb Ethernet Driver.                                *
9  *                                                                           *
10  * This program is free software; you can redistribute it and/or modify      *
11  * it under the terms of the GNU General Public License, version 2, as       *
12  * published by the Free Software Foundation.                                *
13  *                                                                           *
14  * You should have received a copy of the GNU General Public License along   *
15  * with this program; if not, write to the Free Software Foundation, Inc.,   *
16  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.                 *
17  *                                                                           *
18  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
19  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
20  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.                     *
21  *                                                                           *
22  * http://www.chelsio.com                                                    *
23  *                                                                           *
24  * Copyright (c) 2003 - 2005 Chelsio Communications, Inc.                    *
25  * All rights reserved.                                                      *
26  *                                                                           *
27  * Maintainers: maintainers@chelsio.com                                      *
28  *                                                                           *
29  * Authors: Dimitrios Michailidis   <dm@chelsio.com>                         *
30  *          Tina Yang               <tainay@chelsio.com>                     *
31  *          Felix Marti             <felix@chelsio.com>                      *
32  *          Scott Bardone           <sbardone@chelsio.com>                   *
33  *          Kurt Ottaway            <kottaway@chelsio.com>                   *
34  *          Frank DiMambro          <frank@chelsio.com>                      *
35  *                                                                           *
36  * History:                                                                  *
37  *                                                                           *
38  ****************************************************************************/
39
40 #include "common.h"
41 #include "regs.h"
42 #include "gmac.h"
43 #include "elmer0.h"
44 #include "suni1x10gexp_regs.h"
45
46 /* 802.3ae 10Gb/s MDIO Manageable Device(MMD)
47  */
48 #define MMD_RESERVED        0
49 #define MMD_PMAPMD          1
50 #define MMD_WIS             2
51 #define MMD_PCS             3
52 #define MMD_PHY_XGXS        4   /* XGMII Extender Sublayer */
53 #define MMD_DTE_XGXS        5
54
55 #define PHY_XGXS_CTRL_1     0
56 #define PHY_XGXS_STATUS_1   1
57
58 #define OFFSET(REG_ADDR)    (REG_ADDR << 2)
59
60 /* Max frame size PM3393 can handle. Includes Ethernet header and CRC. */
61 #define MAX_FRAME_SIZE  9600
62
63 #define IPG 12
64 #define TXXG_CONF1_VAL ((IPG << SUNI1x10GEXP_BITOFF_TXXG_IPGT) | \
65         SUNI1x10GEXP_BITMSK_TXXG_32BIT_ALIGN | SUNI1x10GEXP_BITMSK_TXXG_CRCEN | \
66         SUNI1x10GEXP_BITMSK_TXXG_PADEN)
67 #define RXXG_CONF1_VAL (SUNI1x10GEXP_BITMSK_RXXG_PUREP | 0x14 | \
68         SUNI1x10GEXP_BITMSK_RXXG_FLCHK | SUNI1x10GEXP_BITMSK_RXXG_CRC_STRIP)
69
70 /* Update statistics every 15 minutes */
71 #define STATS_TICK_SECS (15 * 60)
72
73 enum {                     /* RMON registers */
74         RxOctetsReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_1_LOW,
75         RxUnicastFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_4_LOW,
76         RxMulticastFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_5_LOW,
77         RxBroadcastFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_6_LOW,
78         RxPAUSEMACCtrlFramesReceived = SUNI1x10GEXP_REG_MSTAT_COUNTER_8_LOW,
79         RxFrameCheckSequenceErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_10_LOW,
80         RxFramesLostDueToInternalMACErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_11_LOW,
81         RxSymbolErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_12_LOW,
82         RxInRangeLengthErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_13_LOW,
83         RxFramesTooLongErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_15_LOW,
84         RxJabbers = SUNI1x10GEXP_REG_MSTAT_COUNTER_16_LOW,
85         RxFragments = SUNI1x10GEXP_REG_MSTAT_COUNTER_17_LOW,
86         RxUndersizedFrames =  SUNI1x10GEXP_REG_MSTAT_COUNTER_18_LOW,
87
88         TxOctetsTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW,
89         TxFramesLostDueToInternalMACTransmissionError = SUNI1x10GEXP_REG_MSTAT_COUNTER_35_LOW,
90         TxTransmitSystemError = SUNI1x10GEXP_REG_MSTAT_COUNTER_36_LOW,
91         TxUnicastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_38_LOW,
92         TxMulticastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_40_LOW,
93         TxBroadcastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_42_LOW,
94         TxPAUSEMACCtrlFramesTransmitted = SUNI1x10GEXP_REG_MSTAT_COUNTER_43_LOW
95 };
96
97 struct _cmac_instance {
98         u8 enabled;
99         u8 fc;
100         u8 mac_addr[6];
101 };
102
103 static int pmread(struct cmac *cmac, u32 reg, u32 * data32)
104 {
105         t1_tpi_read(cmac->adapter, OFFSET(reg), data32);
106         return 0;
107 }
108
109 static int pmwrite(struct cmac *cmac, u32 reg, u32 data32)
110 {
111         t1_tpi_write(cmac->adapter, OFFSET(reg), data32);
112         return 0;
113 }
114
115 /* Port reset. */
116 static int pm3393_reset(struct cmac *cmac)
117 {
118         return 0;
119 }
120
121 /*
122  * Enable interrupts for the PM3393
123
124         1. Enable PM3393 BLOCK interrupts.
125         2. Enable PM3393 Master Interrupt bit(INTE)
126         3. Enable ELMER's PM3393 bit.
127         4. Enable Terminator external interrupt.
128 */
129 static int pm3393_interrupt_enable(struct cmac *cmac)
130 {
131         u32 pl_intr;
132
133         /* PM3393 - Enabling all hardware block interrupts.
134          */
135         pmwrite(cmac, SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_ENABLE, 0xffff);
136         pmwrite(cmac, SUNI1x10GEXP_REG_XRF_INTERRUPT_ENABLE, 0xffff);
137         pmwrite(cmac, SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_ENABLE, 0xffff);
138         pmwrite(cmac, SUNI1x10GEXP_REG_RXOAM_INTERRUPT_ENABLE, 0xffff);
139
140         /* Don't interrupt on statistics overflow, we are polling */
141         pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_0, 0);
142         pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_1, 0);
143         pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_2, 0);
144         pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_3, 0);
145
146         pmwrite(cmac, SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_ENABLE, 0xffff);
147         pmwrite(cmac, SUNI1x10GEXP_REG_PL4ODP_INTERRUPT_MASK, 0xffff);
148         pmwrite(cmac, SUNI1x10GEXP_REG_XTEF_INTERRUPT_ENABLE, 0xffff);
149         pmwrite(cmac, SUNI1x10GEXP_REG_TXOAM_INTERRUPT_ENABLE, 0xffff);
150         pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_3, 0xffff);
151         pmwrite(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_MASK, 0xffff);
152         pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_3, 0xffff);
153         pmwrite(cmac, SUNI1x10GEXP_REG_PL4IDU_INTERRUPT_MASK, 0xffff);
154         pmwrite(cmac, SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_ENABLE, 0xffff);
155
156         /* PM3393 - Global interrupt enable
157          */
158         /* TBD XXX Disable for now until we figure out why error interrupts keep asserting. */
159         pmwrite(cmac, SUNI1x10GEXP_REG_GLOBAL_INTERRUPT_ENABLE,
160                 0 /*SUNI1x10GEXP_BITMSK_TOP_INTE */ );
161
162         /* TERMINATOR - PL_INTERUPTS_EXT */
163         pl_intr = t1_read_reg_4(cmac->adapter, A_PL_ENABLE);
164         pl_intr |= F_PL_INTR_EXT;
165         t1_write_reg_4(cmac->adapter, A_PL_ENABLE, pl_intr);
166         return 0;
167 }
168
169 static int pm3393_interrupt_disable(struct cmac *cmac)
170 {
171         u32 elmer;
172
173         /* PM3393 - Enabling HW interrupt blocks. */
174         pmwrite(cmac, SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_ENABLE, 0);
175         pmwrite(cmac, SUNI1x10GEXP_REG_XRF_INTERRUPT_ENABLE, 0);
176         pmwrite(cmac, SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_ENABLE, 0);
177         pmwrite(cmac, SUNI1x10GEXP_REG_RXOAM_INTERRUPT_ENABLE, 0);
178         pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_0, 0);
179         pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_1, 0);
180         pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_2, 0);
181         pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_3, 0);
182         pmwrite(cmac, SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_ENABLE, 0);
183         pmwrite(cmac, SUNI1x10GEXP_REG_PL4ODP_INTERRUPT_MASK, 0);
184         pmwrite(cmac, SUNI1x10GEXP_REG_XTEF_INTERRUPT_ENABLE, 0);
185         pmwrite(cmac, SUNI1x10GEXP_REG_TXOAM_INTERRUPT_ENABLE, 0);
186         pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_3, 0);
187         pmwrite(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_MASK, 0);
188         pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_3, 0);
189         pmwrite(cmac, SUNI1x10GEXP_REG_PL4IDU_INTERRUPT_MASK, 0);
190         pmwrite(cmac, SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_ENABLE, 0);
191
192         /* PM3393 - Global interrupt enable */
193         pmwrite(cmac, SUNI1x10GEXP_REG_GLOBAL_INTERRUPT_ENABLE, 0);
194
195         /* ELMER - External chip interrupts. */
196         t1_tpi_read(cmac->adapter, A_ELMER0_INT_ENABLE, &elmer);
197         elmer &= ~ELMER0_GP_BIT1;
198         t1_tpi_write(cmac->adapter, A_ELMER0_INT_ENABLE, elmer);
199
200         /* TERMINATOR - PL_INTERUPTS_EXT */
201         /* DO NOT DISABLE TERMINATOR's EXTERNAL INTERRUPTS. ANOTHER CHIP
202          * COULD WANT THEM ENABLED. We disable PM3393 at the ELMER level.
203          */
204
205         return 0;
206 }
207
208 static int pm3393_interrupt_clear(struct cmac *cmac)
209 {
210         u32 elmer;
211         u32 pl_intr;
212         u32 val32;
213
214         /* PM3393 - Clearing HW interrupt blocks. Note, this assumes
215          *          bit WCIMODE=0 for a clear-on-read.
216          */
217         pmread(cmac, SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_STATUS, &val32);
218         pmread(cmac, SUNI1x10GEXP_REG_XRF_INTERRUPT_STATUS, &val32);
219         pmread(cmac, SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_STATUS, &val32);
220         pmread(cmac, SUNI1x10GEXP_REG_RXOAM_INTERRUPT_STATUS, &val32);
221         pmread(cmac, SUNI1x10GEXP_REG_PL4ODP_INTERRUPT, &val32);
222         pmread(cmac, SUNI1x10GEXP_REG_XTEF_INTERRUPT_STATUS, &val32);
223         pmread(cmac, SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_INTERRUPT, &val32);
224         pmread(cmac, SUNI1x10GEXP_REG_TXOAM_INTERRUPT_STATUS, &val32);
225         pmread(cmac, SUNI1x10GEXP_REG_RXXG_INTERRUPT, &val32);
226         pmread(cmac, SUNI1x10GEXP_REG_TXXG_INTERRUPT, &val32);
227         pmread(cmac, SUNI1x10GEXP_REG_PL4IDU_INTERRUPT, &val32);
228         pmread(cmac, SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_INDICATION,
229                &val32);
230         pmread(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_STATUS, &val32);
231         pmread(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_CHANGE, &val32);
232
233         /* PM3393 - Global interrupt status
234          */
235         pmread(cmac, SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS, &val32);
236
237         /* ELMER - External chip interrupts.
238          */
239         t1_tpi_read(cmac->adapter, A_ELMER0_INT_CAUSE, &elmer);
240         elmer |= ELMER0_GP_BIT1;
241         t1_tpi_write(cmac->adapter, A_ELMER0_INT_CAUSE, elmer);
242
243         /* TERMINATOR - PL_INTERUPTS_EXT
244          */
245         pl_intr = t1_read_reg_4(cmac->adapter, A_PL_CAUSE);
246         pl_intr |= F_PL_INTR_EXT;
247         t1_write_reg_4(cmac->adapter, A_PL_CAUSE, pl_intr);
248
249         return 0;
250 }
251
252 /* Interrupt handler */
253 static int pm3393_interrupt_handler(struct cmac *cmac)
254 {
255         u32 master_intr_status;
256 /*
257         1. Read master interrupt register.
258         2. Read BLOCK's interrupt status registers.
259         3. Handle BLOCK interrupts.
260 */
261         /* Read the master interrupt status register. */
262         pmread(cmac, SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS,
263                &master_intr_status);
264         CH_DBG(cmac->adapter, INTR, "PM3393 intr cause 0x%x\n",
265                master_intr_status);
266
267         /* TBD XXX Lets just clear everything for now */
268         pm3393_interrupt_clear(cmac);
269
270         return 0;
271 }
272
273 static int pm3393_enable(struct cmac *cmac, int which)
274 {
275         if (which & MAC_DIRECTION_RX)
276                 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_1,
277                         (RXXG_CONF1_VAL | SUNI1x10GEXP_BITMSK_RXXG_RXEN));
278
279         if (which & MAC_DIRECTION_TX) {
280                 u32 val = TXXG_CONF1_VAL | SUNI1x10GEXP_BITMSK_TXXG_TXEN0;
281
282                 if (cmac->instance->fc & PAUSE_RX)
283                         val |= SUNI1x10GEXP_BITMSK_TXXG_FCRX;
284                 if (cmac->instance->fc & PAUSE_TX)
285                         val |= SUNI1x10GEXP_BITMSK_TXXG_FCTX;
286                 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_1, val);
287         }
288
289         cmac->instance->enabled |= which;
290         return 0;
291 }
292
293 static int pm3393_enable_port(struct cmac *cmac, int which)
294 {
295         /* Clear port statistics */
296         pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_CONTROL,
297                 SUNI1x10GEXP_BITMSK_MSTAT_CLEAR);
298         udelay(2);
299         memset(&cmac->stats, 0, sizeof(struct cmac_statistics));
300
301         pm3393_enable(cmac, which);
302
303         /*
304          * XXX This should be done by the PHY and preferrably not at all.
305          * The PHY doesn't give us link status indication on its own so have
306          * the link management code query it instead.
307          */
308         {
309                 extern void link_changed(adapter_t *adapter, int port_id);
310
311                 link_changed(cmac->adapter, 0);
312         }
313         return 0;
314 }
315
316 static int pm3393_disable(struct cmac *cmac, int which)
317 {
318         if (which & MAC_DIRECTION_RX)
319                 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_1, RXXG_CONF1_VAL);
320         if (which & MAC_DIRECTION_TX)
321                 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_1, TXXG_CONF1_VAL);
322
323         /*
324          * The disable is graceful. Give the PM3393 time.  Can't wait very
325          * long here, we may be holding locks.
326          */
327         udelay(20);
328
329         cmac->instance->enabled &= ~which;
330         return 0;
331 }
332
333 static int pm3393_loopback_enable(struct cmac *cmac)
334 {
335         return 0;
336 }
337
338 static int pm3393_loopback_disable(struct cmac *cmac)
339 {
340         return 0;
341 }
342
343 static int pm3393_set_mtu(struct cmac *cmac, int mtu)
344 {
345         int enabled = cmac->instance->enabled;
346
347         /* MAX_FRAME_SIZE includes header + FCS, mtu doesn't */
348         mtu += 14 + 4;
349         if (mtu > MAX_FRAME_SIZE)
350                 return -EINVAL;
351
352         /* Disable Rx/Tx MAC before configuring it. */
353         if (enabled)
354                 pm3393_disable(cmac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
355
356         pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MAX_FRAME_LENGTH, mtu);
357         pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_MAX_FRAME_SIZE, mtu);
358
359         if (enabled)
360                 pm3393_enable(cmac, enabled);
361         return 0;
362 }
363
364 static u32 calc_crc(u8 *b, int len)
365 {
366         int i;
367         u32 crc = (u32)~0;
368
369         /* calculate crc one bit at a time */
370         while (len--) {
371                 crc ^= *b++;
372                 for (i = 0; i < 8; i++) {
373                         if (crc & 0x1)
374                                 crc = (crc >> 1) ^ 0xedb88320;
375                         else
376                                 crc = (crc >> 1);
377                 }
378         }
379
380         /* reverse bits */
381         crc = ((crc >> 4) & 0x0f0f0f0f) | ((crc << 4) & 0xf0f0f0f0);
382         crc = ((crc >> 2) & 0x33333333) | ((crc << 2) & 0xcccccccc);
383         crc = ((crc >> 1) & 0x55555555) | ((crc << 1) & 0xaaaaaaaa);
384         /* swap bytes */
385         crc = (crc >> 16) | (crc << 16);
386         crc = (crc >> 8 & 0x00ff00ff) | (crc << 8 & 0xff00ff00);
387
388         return crc;
389 }
390
391 static int pm3393_set_rx_mode(struct cmac *cmac, struct t1_rx_mode *rm)
392 {
393         int enabled = cmac->instance->enabled & MAC_DIRECTION_RX;
394         u32 rx_mode;
395
396         /* Disable MAC RX before reconfiguring it */
397         if (enabled)
398                 pm3393_disable(cmac, MAC_DIRECTION_RX);
399
400         pmread(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2, &rx_mode);
401         rx_mode &= ~(SUNI1x10GEXP_BITMSK_RXXG_PMODE |
402                      SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN);
403         pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2,
404                 (u16)rx_mode);
405
406         if (t1_rx_mode_promisc(rm)) {
407                 /* Promiscuous mode. */
408                 rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_PMODE;
409         }
410         if (t1_rx_mode_allmulti(rm)) {
411                 /* Accept all multicast. */
412                 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW, 0xffff);
413                 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDLOW, 0xffff);
414                 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDHIGH, 0xffff);
415                 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_HIGH, 0xffff);
416                 rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN;
417         } else if (t1_rx_mode_mc_cnt(rm)) {
418                 /* Accept one or more multicast(s). */
419                 u8 *addr;
420                 int bit;
421                 u16 mc_filter[4] = { 0, };
422
423                 while ((addr = t1_get_next_mcaddr(rm))) {
424                         bit = (calc_crc(addr, ETH_ALEN) >> 23) & 0x3f;  /* bit[23:28] */
425                         mc_filter[bit >> 4] |= 1 << (bit & 0xf);
426                 }
427                 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW, mc_filter[0]);
428                 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDLOW, mc_filter[1]);
429                 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDHIGH, mc_filter[2]);
430                 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_HIGH, mc_filter[3]);
431                 rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN;
432         }
433
434         pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2, (u16)rx_mode);
435
436         if (enabled)
437                 pm3393_enable(cmac, MAC_DIRECTION_RX);
438
439         return 0;
440 }
441
442 static int pm3393_get_speed_duplex_fc(struct cmac *cmac, int *speed,
443                                       int *duplex, int *fc)
444 {
445         if (speed)
446                 *speed = SPEED_10000;
447         if (duplex)
448                 *duplex = DUPLEX_FULL;
449         if (fc)
450                 *fc = cmac->instance->fc;
451         return 0;
452 }
453
454 static int pm3393_set_speed_duplex_fc(struct cmac *cmac, int speed, int duplex,
455                                       int fc)
456 {
457         if (speed >= 0 && speed != SPEED_10000)
458                 return -1;
459         if (duplex >= 0 && duplex != DUPLEX_FULL)
460                 return -1;
461         if (fc & ~(PAUSE_TX | PAUSE_RX))
462                 return -1;
463
464         if (fc != cmac->instance->fc) {
465                 cmac->instance->fc = (u8) fc;
466                 if (cmac->instance->enabled & MAC_DIRECTION_TX)
467                         pm3393_enable(cmac, MAC_DIRECTION_TX);
468         }
469         return 0;
470 }
471
472 #define RMON_UPDATE(mac, name, stat_name) \
473         { \
474                 t1_tpi_read((mac)->adapter, OFFSET(name), &val0);       \
475                 t1_tpi_read((mac)->adapter, OFFSET(((name)+1)), &val1); \
476                 t1_tpi_read((mac)->adapter, OFFSET(((name)+2)), &val2); \
477                 (mac)->stats.stat_name = ((u64)val0 & 0xffff) | \
478                                                 (((u64)val1 & 0xffff) << 16) | \
479                                                 (((u64)val2 & 0xff) << 32) | \
480                                                 ((mac)->stats.stat_name & \
481                                                         (~(u64)0 << 40)); \
482                 if (ro &        \
483                         ((name -  SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW) >> 2)) \
484                         (mac)->stats.stat_name += ((u64)1 << 40); \
485         }
486
487 static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac,
488                                                               int flag)
489 {
490         u64     ro;
491         u32     val0, val1, val2, val3;
492
493         /* Snap the counters */
494         pmwrite(mac, SUNI1x10GEXP_REG_MSTAT_CONTROL,
495                 SUNI1x10GEXP_BITMSK_MSTAT_SNAP);
496
497         /* Counter rollover, clear on read */
498         pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_0, &val0);
499         pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_1, &val1);
500         pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_2, &val2);
501         pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_3, &val3);
502         ro = ((u64)val0 & 0xffff) | (((u64)val1 & 0xffff) << 16) |
503                 (((u64)val2 & 0xffff) << 32) | (((u64)val3 & 0xffff) << 48);
504
505         /* Rx stats */
506         RMON_UPDATE(mac, RxOctetsReceivedOK, RxOctetsOK);
507         RMON_UPDATE(mac, RxUnicastFramesReceivedOK, RxUnicastFramesOK);
508         RMON_UPDATE(mac, RxMulticastFramesReceivedOK, RxMulticastFramesOK);
509         RMON_UPDATE(mac, RxBroadcastFramesReceivedOK, RxBroadcastFramesOK);
510         RMON_UPDATE(mac, RxPAUSEMACCtrlFramesReceived, RxPauseFrames);
511         RMON_UPDATE(mac, RxFrameCheckSequenceErrors, RxFCSErrors);
512         RMON_UPDATE(mac, RxFramesLostDueToInternalMACErrors,
513                                 RxInternalMACRcvError);
514         RMON_UPDATE(mac, RxSymbolErrors, RxSymbolErrors);
515         RMON_UPDATE(mac, RxInRangeLengthErrors, RxInRangeLengthErrors);
516         RMON_UPDATE(mac, RxFramesTooLongErrors , RxFrameTooLongErrors);
517         RMON_UPDATE(mac, RxJabbers, RxJabberErrors);
518         RMON_UPDATE(mac, RxFragments, RxRuntErrors);
519         RMON_UPDATE(mac, RxUndersizedFrames, RxRuntErrors);
520
521         /* Tx stats */
522         RMON_UPDATE(mac, TxOctetsTransmittedOK, TxOctetsOK);
523         RMON_UPDATE(mac, TxFramesLostDueToInternalMACTransmissionError,
524                                 TxInternalMACXmitError);
525         RMON_UPDATE(mac, TxTransmitSystemError, TxFCSErrors);
526         RMON_UPDATE(mac, TxUnicastFramesTransmittedOK, TxUnicastFramesOK);
527         RMON_UPDATE(mac, TxMulticastFramesTransmittedOK, TxMulticastFramesOK);
528         RMON_UPDATE(mac, TxBroadcastFramesTransmittedOK, TxBroadcastFramesOK);
529         RMON_UPDATE(mac, TxPAUSEMACCtrlFramesTransmitted, TxPauseFrames);
530
531         return &mac->stats;
532 }
533
534 static int pm3393_macaddress_get(struct cmac *cmac, u8 mac_addr[6])
535 {
536         memcpy(mac_addr, cmac->instance->mac_addr, 6);
537         return 0;
538 }
539
540 static int pm3393_macaddress_set(struct cmac *cmac, u8 ma[6])
541 {
542         u32 val, lo, mid, hi, enabled = cmac->instance->enabled;
543
544         /*
545          * MAC addr: 00:07:43:00:13:09
546          *
547          * ma[5] = 0x09
548          * ma[4] = 0x13
549          * ma[3] = 0x00
550          * ma[2] = 0x43
551          * ma[1] = 0x07
552          * ma[0] = 0x00
553          *
554          * The PM3393 requires byte swapping and reverse order entry
555          * when programming MAC addresses:
556          *
557          * low_bits[15:0]    = ma[1]:ma[0]
558          * mid_bits[31:16]   = ma[3]:ma[2]
559          * high_bits[47:32]  = ma[5]:ma[4]
560          */
561
562         /* Store local copy */
563         memcpy(cmac->instance->mac_addr, ma, 6);
564
565         lo = ((u32) ma[1] << 8) | (u32) ma[0];
566         mid = ((u32) ma[3] << 8) | (u32) ma[2];
567         hi = ((u32) ma[5] << 8) | (u32) ma[4];
568
569         /* Disable Rx/Tx MAC before configuring it. */
570         if (enabled)
571                 pm3393_disable(cmac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
572
573         /* Set RXXG Station Address */
574         pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_15_0, lo);
575         pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_31_16, mid);
576         pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_47_32, hi);
577
578         /* Set TXXG Station Address */
579         pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_15_0, lo);
580         pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_31_16, mid);
581         pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_47_32, hi);
582
583         /* Setup Exact Match Filter 1 with our MAC address
584          *
585          * Must disable exact match filter before configuring it.
586          */
587         pmread(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, &val);
588         val &= 0xff0f;
589         pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, val);
590
591         pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_LOW, lo);
592         pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_MID, mid);
593         pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_HIGH, hi);
594
595         val |= 0x0090;
596         pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, val);
597
598         if (enabled)
599                 pm3393_enable(cmac, enabled);
600         return 0;
601 }
602
603 static void pm3393_destroy(struct cmac *cmac)
604 {
605         kfree(cmac);
606 }
607
608 static struct cmac_ops pm3393_ops = {
609         .destroy                 = pm3393_destroy,
610         .reset                   = pm3393_reset,
611         .interrupt_enable        = pm3393_interrupt_enable,
612         .interrupt_disable       = pm3393_interrupt_disable,
613         .interrupt_clear         = pm3393_interrupt_clear,
614         .interrupt_handler       = pm3393_interrupt_handler,
615         .enable                  = pm3393_enable_port,
616         .disable                 = pm3393_disable,
617         .loopback_enable         = pm3393_loopback_enable,
618         .loopback_disable        = pm3393_loopback_disable,
619         .set_mtu                 = pm3393_set_mtu,
620         .set_rx_mode             = pm3393_set_rx_mode,
621         .get_speed_duplex_fc     = pm3393_get_speed_duplex_fc,
622         .set_speed_duplex_fc     = pm3393_set_speed_duplex_fc,
623         .statistics_update       = pm3393_update_statistics,
624         .macaddress_get          = pm3393_macaddress_get,
625         .macaddress_set          = pm3393_macaddress_set
626 };
627
628 static struct cmac *pm3393_mac_create(adapter_t *adapter, int index)
629 {
630         struct cmac *cmac;
631
632         cmac = kmalloc(sizeof(*cmac) + sizeof(cmac_instance), GFP_KERNEL);
633         if (!cmac)
634                 return NULL;
635         memset(cmac, 0, sizeof(*cmac));
636
637         cmac->ops = &pm3393_ops;
638         cmac->instance = (cmac_instance *) (cmac + 1);
639         cmac->adapter = adapter;
640         cmac->instance->fc = PAUSE_TX | PAUSE_RX;
641
642         t1_tpi_write(adapter, OFFSET(0x0001), 0x00008000);
643         t1_tpi_write(adapter, OFFSET(0x0001), 0x00000000);
644         t1_tpi_write(adapter, OFFSET(0x2308), 0x00009800);
645         t1_tpi_write(adapter, OFFSET(0x2305), 0x00001001);   /* PL4IO Enable */
646         t1_tpi_write(adapter, OFFSET(0x2320), 0x00008800);
647         t1_tpi_write(adapter, OFFSET(0x2321), 0x00008800);
648         t1_tpi_write(adapter, OFFSET(0x2322), 0x00008800);
649         t1_tpi_write(adapter, OFFSET(0x2323), 0x00008800);
650         t1_tpi_write(adapter, OFFSET(0x2324), 0x00008800);
651         t1_tpi_write(adapter, OFFSET(0x2325), 0x00008800);
652         t1_tpi_write(adapter, OFFSET(0x2326), 0x00008800);
653         t1_tpi_write(adapter, OFFSET(0x2327), 0x00008800);
654         t1_tpi_write(adapter, OFFSET(0x2328), 0x00008800);
655         t1_tpi_write(adapter, OFFSET(0x2329), 0x00008800);
656         t1_tpi_write(adapter, OFFSET(0x232a), 0x00008800);
657         t1_tpi_write(adapter, OFFSET(0x232b), 0x00008800);
658         t1_tpi_write(adapter, OFFSET(0x232c), 0x00008800);
659         t1_tpi_write(adapter, OFFSET(0x232d), 0x00008800);
660         t1_tpi_write(adapter, OFFSET(0x232e), 0x00008800);
661         t1_tpi_write(adapter, OFFSET(0x232f), 0x00008800);
662         t1_tpi_write(adapter, OFFSET(0x230d), 0x00009c00);
663         t1_tpi_write(adapter, OFFSET(0x2304), 0x00000202);      /* PL4IO Calendar Repetitions */
664
665         t1_tpi_write(adapter, OFFSET(0x3200), 0x00008080);      /* EFLX Enable */
666         t1_tpi_write(adapter, OFFSET(0x3210), 0x00000000);      /* EFLX Channel Deprovision */
667         t1_tpi_write(adapter, OFFSET(0x3203), 0x00000000);      /* EFLX Low Limit */
668         t1_tpi_write(adapter, OFFSET(0x3204), 0x00000040);      /* EFLX High Limit */
669         t1_tpi_write(adapter, OFFSET(0x3205), 0x000002cc);      /* EFLX Almost Full */
670         t1_tpi_write(adapter, OFFSET(0x3206), 0x00000199);      /* EFLX Almost Empty */
671         t1_tpi_write(adapter, OFFSET(0x3207), 0x00000240);      /* EFLX Cut Through Threshold */
672         t1_tpi_write(adapter, OFFSET(0x3202), 0x00000000);      /* EFLX Indirect Register Update */
673         t1_tpi_write(adapter, OFFSET(0x3210), 0x00000001);      /* EFLX Channel Provision */
674         t1_tpi_write(adapter, OFFSET(0x3208), 0x0000ffff);      /* EFLX Undocumented */
675         t1_tpi_write(adapter, OFFSET(0x320a), 0x0000ffff);      /* EFLX Undocumented */
676         t1_tpi_write(adapter, OFFSET(0x320c), 0x0000ffff);      /* EFLX enable overflow interrupt The other bit are undocumented */
677         t1_tpi_write(adapter, OFFSET(0x320e), 0x0000ffff);      /* EFLX Undocumented */
678
679         t1_tpi_write(adapter, OFFSET(0x2200), 0x0000c000);      /* IFLX Configuration - enable */
680         t1_tpi_write(adapter, OFFSET(0x2201), 0x00000000);      /* IFLX Channel Deprovision */
681         t1_tpi_write(adapter, OFFSET(0x220e), 0x00000000);      /* IFLX Low Limit */
682         t1_tpi_write(adapter, OFFSET(0x220f), 0x00000100);      /* IFLX High Limit */
683         t1_tpi_write(adapter, OFFSET(0x2210), 0x00000c00);      /* IFLX Almost Full Limit */
684         t1_tpi_write(adapter, OFFSET(0x2211), 0x00000599);      /* IFLX Almost Empty Limit */
685         t1_tpi_write(adapter, OFFSET(0x220d), 0x00000000);      /* IFLX Indirect Register Update */
686         t1_tpi_write(adapter, OFFSET(0x2201), 0x00000001);      /* IFLX Channel Provision */
687         t1_tpi_write(adapter, OFFSET(0x2203), 0x0000ffff);      /* IFLX Undocumented */
688         t1_tpi_write(adapter, OFFSET(0x2205), 0x0000ffff);      /* IFLX Undocumented */
689         t1_tpi_write(adapter, OFFSET(0x2209), 0x0000ffff);      /* IFLX Enable overflow interrupt.  The other bit are undocumented */
690
691         t1_tpi_write(adapter, OFFSET(0x2241), 0xfffffffe);      /* PL4MOS Undocumented */
692         t1_tpi_write(adapter, OFFSET(0x2242), 0x0000ffff);      /* PL4MOS Undocumented */
693         t1_tpi_write(adapter, OFFSET(0x2243), 0x00000008);      /* PL4MOS Starving Burst Size */
694         t1_tpi_write(adapter, OFFSET(0x2244), 0x00000008);      /* PL4MOS Hungry Burst Size */
695         t1_tpi_write(adapter, OFFSET(0x2245), 0x00000008);      /* PL4MOS Transfer Size */
696         t1_tpi_write(adapter, OFFSET(0x2240), 0x00000005);      /* PL4MOS Disable */
697
698         t1_tpi_write(adapter, OFFSET(0x2280), 0x00002103);      /* PL4ODP Training Repeat and SOP rule */
699         t1_tpi_write(adapter, OFFSET(0x2284), 0x00000000);      /* PL4ODP MAX_T setting */
700
701         t1_tpi_write(adapter, OFFSET(0x3280), 0x00000087);      /* PL4IDU Enable data forward, port state machine. Set ALLOW_NON_ZERO_OLB */
702         t1_tpi_write(adapter, OFFSET(0x3282), 0x0000001f);      /* PL4IDU Enable Dip4 check error interrupts */
703
704         t1_tpi_write(adapter, OFFSET(0x3040), 0x0c32);  /* # TXXG Config */
705         /* For T1 use timer based Mac flow control. */
706         if (t1_is_T1B(adapter))
707                 t1_tpi_write(adapter, OFFSET(0x304d), 0x8000);
708         t1_tpi_write(adapter, OFFSET(0x2040), 0x059c);  /* # RXXG Config */
709         t1_tpi_write(adapter, OFFSET(0x2049), 0x0000);  /* # RXXG Cut Through */
710         t1_tpi_write(adapter, OFFSET(0x2070), 0x0000);  /* # Disable promiscuous mode */
711
712         /* Setup Exact Match Filter 0 to allow broadcast packets.
713          */
714         t1_tpi_write(adapter, OFFSET(0x206e), 0x0000);  /* # Disable Match Enable bit */
715         t1_tpi_write(adapter, OFFSET(0x204a), 0xffff);  /* # low addr */
716         t1_tpi_write(adapter, OFFSET(0x204b), 0xffff);  /* # mid addr */
717         t1_tpi_write(adapter, OFFSET(0x204c), 0xffff);  /* # high addr */
718         t1_tpi_write(adapter, OFFSET(0x206e), 0x0009);  /* # Enable Match Enable bit */
719
720         t1_tpi_write(adapter, OFFSET(0x0003), 0x0000);  /* # NO SOP/ PAD_EN setup */
721         t1_tpi_write(adapter, OFFSET(0x0100), 0x0ff0);  /* # RXEQB disabled */
722         t1_tpi_write(adapter, OFFSET(0x0101), 0x0f0f);  /* # No Preemphasis */
723
724         return cmac;
725 }
726
727 static int pm3393_mac_reset(adapter_t * adapter)
728 {
729         u32 val;
730         u32 x;
731         u32 is_pl4_reset_finished;
732         u32 is_pl4_outof_lock;
733         u32 is_xaui_mabc_pll_locked;
734         u32 successful_reset;
735         int i;
736
737         /* The following steps are required to properly reset
738          * the PM3393. This information is provided in the
739          * PM3393 datasheet (Issue 2: November 2002)
740          * section 13.1 -- Device Reset.
741          *
742          * The PM3393 has three types of components that are
743          * individually reset:
744          *
745          * DRESETB      - Digital circuitry
746          * PL4_ARESETB  - PL4 analog circuitry
747          * XAUI_ARESETB - XAUI bus analog circuitry
748          *
749          * Steps to reset PM3393 using RSTB pin:
750          *
751          * 1. Assert RSTB pin low ( write 0 )
752          * 2. Wait at least 1ms to initiate a complete initialization of device.
753          * 3. Wait until all external clocks and REFSEL are stable.
754          * 4. Wait minimum of 1ms. (after external clocks and REFEL are stable)
755          * 5. De-assert RSTB ( write 1 )
756          * 6. Wait until internal timers to expires after ~14ms.
757          *    - Allows analog clock synthesizer(PL4CSU) to stabilize to
758          *      selected reference frequency before allowing the digital
759          *      portion of the device to operate.
760          * 7. Wait at least 200us for XAUI interface to stabilize.
761          * 8. Verify the PM3393 came out of reset successfully.
762          *    Set successful reset flag if everything worked else try again
763          *    a few more times.
764          */
765
766         successful_reset = 0;
767         for (i = 0; i < 3 && !successful_reset; i++) {
768                 /* 1 */
769                 t1_tpi_read(adapter, A_ELMER0_GPO, &val);
770                 val &= ~1;
771                 t1_tpi_write(adapter, A_ELMER0_GPO, val);
772
773                 /* 2 */
774                 msleep(1);
775
776                 /* 3 */
777                 msleep(1);
778
779                 /* 4 */
780                 msleep(2 /*1 extra ms for safety */ );
781
782                 /* 5 */
783                 val |= 1;
784                 t1_tpi_write(adapter, A_ELMER0_GPO, val);
785
786                 /* 6 */
787                 msleep(15 /*1 extra ms for safety */ );
788
789                 /* 7 */
790                 msleep(1);
791
792                 /* 8 */
793
794                 /* Has PL4 analog block come out of reset correctly? */
795                 t1_tpi_read(adapter, OFFSET(SUNI1x10GEXP_REG_DEVICE_STATUS), &val);
796                 is_pl4_reset_finished = (val & SUNI1x10GEXP_BITMSK_TOP_EXPIRED);
797
798                 /* TBD XXX SUNI1x10GEXP_BITMSK_TOP_PL4_IS_DOOL gets locked later in the init sequence
799                  *         figure out why? */
800
801                 /* Have all PL4 block clocks locked? */
802                 x = (SUNI1x10GEXP_BITMSK_TOP_PL4_ID_DOOL
803                      /*| SUNI1x10GEXP_BITMSK_TOP_PL4_IS_DOOL */  |
804                      SUNI1x10GEXP_BITMSK_TOP_PL4_ID_ROOL |
805                      SUNI1x10GEXP_BITMSK_TOP_PL4_IS_ROOL |
806                      SUNI1x10GEXP_BITMSK_TOP_PL4_OUT_ROOL);
807                 is_pl4_outof_lock = (val & x);
808
809                 /* ??? If this fails, might be able to software reset the XAUI part
810                  *     and try to recover... thus saving us from doing another HW reset */
811                 /* Has the XAUI MABC PLL circuitry stablized? */
812                 is_xaui_mabc_pll_locked =
813                     (val & SUNI1x10GEXP_BITMSK_TOP_SXRA_EXPIRED);
814
815                 successful_reset = (is_pl4_reset_finished && !is_pl4_outof_lock
816                                     && is_xaui_mabc_pll_locked);
817
818                 CH_DBG(adapter, HW,
819                        "PM3393 HW reset %d: pl4_reset 0x%x, val 0x%x, "
820                        "is_pl4_outof_lock 0x%x, xaui_locked 0x%x\n",
821                        i, is_pl4_reset_finished, val, is_pl4_outof_lock,
822                        is_xaui_mabc_pll_locked);
823         }
824         return successful_reset ? 0 : 1;
825 }
826
827 struct gmac t1_pm3393_ops = {
828         STATS_TICK_SECS,
829         pm3393_mac_create,
830         pm3393_mac_reset
831 };