1 /*****************************************************************************
5 * $Date: 2005/05/14 00:59:32 $ *
7 * PMC/SIERRA (pm3393) MAC-PHY functionality. *
8 * part of the Chelsio 10Gb Ethernet Driver. *
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. *
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. *
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. *
22 * http://www.chelsio.com *
24 * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
25 * All rights reserved. *
27 * Maintainers: maintainers@chelsio.com *
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> *
38 ****************************************************************************/
44 #include "suni1x10gexp_regs.h"
46 /* 802.3ae 10Gb/s MDIO Manageable Device(MMD)
53 MMD_PHY_XGXS, /* XGMII Extender Sublayer */
62 #define OFFSET(REG_ADDR) (REG_ADDR << 2)
64 /* Max frame size PM3393 can handle. Includes Ethernet header and CRC. */
65 #define MAX_FRAME_SIZE 9600
68 #define TXXG_CONF1_VAL ((IPG << SUNI1x10GEXP_BITOFF_TXXG_IPGT) | \
69 SUNI1x10GEXP_BITMSK_TXXG_32BIT_ALIGN | SUNI1x10GEXP_BITMSK_TXXG_CRCEN | \
70 SUNI1x10GEXP_BITMSK_TXXG_PADEN)
71 #define RXXG_CONF1_VAL (SUNI1x10GEXP_BITMSK_RXXG_PUREP | 0x14 | \
72 SUNI1x10GEXP_BITMSK_RXXG_FLCHK | SUNI1x10GEXP_BITMSK_RXXG_CRC_STRIP)
74 /* Update statistics every 15 minutes */
75 #define STATS_TICK_SECS (15 * 60)
77 enum { /* RMON registers */
78 RxOctetsReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_1_LOW,
79 RxUnicastFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_4_LOW,
80 RxMulticastFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_5_LOW,
81 RxBroadcastFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_6_LOW,
82 RxPAUSEMACCtrlFramesReceived = SUNI1x10GEXP_REG_MSTAT_COUNTER_8_LOW,
83 RxFrameCheckSequenceErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_10_LOW,
84 RxFramesLostDueToInternalMACErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_11_LOW,
85 RxSymbolErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_12_LOW,
86 RxInRangeLengthErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_13_LOW,
87 RxFramesTooLongErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_15_LOW,
88 RxJabbers = SUNI1x10GEXP_REG_MSTAT_COUNTER_16_LOW,
89 RxFragments = SUNI1x10GEXP_REG_MSTAT_COUNTER_17_LOW,
90 RxUndersizedFrames = SUNI1x10GEXP_REG_MSTAT_COUNTER_18_LOW,
91 RxJumboFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_25_LOW,
92 RxJumboOctetsReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_26_LOW,
94 TxOctetsTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW,
95 TxFramesLostDueToInternalMACTransmissionError = SUNI1x10GEXP_REG_MSTAT_COUNTER_35_LOW,
96 TxTransmitSystemError = SUNI1x10GEXP_REG_MSTAT_COUNTER_36_LOW,
97 TxUnicastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_38_LOW,
98 TxMulticastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_40_LOW,
99 TxBroadcastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_42_LOW,
100 TxPAUSEMACCtrlFramesTransmitted = SUNI1x10GEXP_REG_MSTAT_COUNTER_43_LOW,
101 TxJumboFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_51_LOW,
102 TxJumboOctetsReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_52_LOW
105 struct _cmac_instance {
111 static int pmread(struct cmac *cmac, u32 reg, u32 * data32)
113 t1_tpi_read(cmac->adapter, OFFSET(reg), data32);
117 static int pmwrite(struct cmac *cmac, u32 reg, u32 data32)
119 t1_tpi_write(cmac->adapter, OFFSET(reg), data32);
124 static int pm3393_reset(struct cmac *cmac)
130 * Enable interrupts for the PM3393
132 1. Enable PM3393 BLOCK interrupts.
133 2. Enable PM3393 Master Interrupt bit(INTE)
134 3. Enable ELMER's PM3393 bit.
135 4. Enable Terminator external interrupt.
137 static int pm3393_interrupt_enable(struct cmac *cmac)
141 /* PM3393 - Enabling all hardware block interrupts.
143 pmwrite(cmac, SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_ENABLE, 0xffff);
144 pmwrite(cmac, SUNI1x10GEXP_REG_XRF_INTERRUPT_ENABLE, 0xffff);
145 pmwrite(cmac, SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_ENABLE, 0xffff);
146 pmwrite(cmac, SUNI1x10GEXP_REG_RXOAM_INTERRUPT_ENABLE, 0xffff);
148 /* Don't interrupt on statistics overflow, we are polling */
149 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_0, 0);
150 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_1, 0);
151 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_2, 0);
152 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_3, 0);
154 pmwrite(cmac, SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_ENABLE, 0xffff);
155 pmwrite(cmac, SUNI1x10GEXP_REG_PL4ODP_INTERRUPT_MASK, 0xffff);
156 pmwrite(cmac, SUNI1x10GEXP_REG_XTEF_INTERRUPT_ENABLE, 0xffff);
157 pmwrite(cmac, SUNI1x10GEXP_REG_TXOAM_INTERRUPT_ENABLE, 0xffff);
158 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_3, 0xffff);
159 pmwrite(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_MASK, 0xffff);
160 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_3, 0xffff);
161 pmwrite(cmac, SUNI1x10GEXP_REG_PL4IDU_INTERRUPT_MASK, 0xffff);
162 pmwrite(cmac, SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_ENABLE, 0xffff);
164 /* PM3393 - Global interrupt enable
166 /* TBD XXX Disable for now until we figure out why error interrupts keep asserting. */
167 pmwrite(cmac, SUNI1x10GEXP_REG_GLOBAL_INTERRUPT_ENABLE,
168 0 /*SUNI1x10GEXP_BITMSK_TOP_INTE */ );
170 /* TERMINATOR - PL_INTERUPTS_EXT */
171 pl_intr = readl(cmac->adapter->regs + A_PL_ENABLE);
172 pl_intr |= F_PL_INTR_EXT;
173 writel(pl_intr, cmac->adapter->regs + A_PL_ENABLE);
177 static int pm3393_interrupt_disable(struct cmac *cmac)
181 /* PM3393 - Enabling HW interrupt blocks. */
182 pmwrite(cmac, SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_ENABLE, 0);
183 pmwrite(cmac, SUNI1x10GEXP_REG_XRF_INTERRUPT_ENABLE, 0);
184 pmwrite(cmac, SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_ENABLE, 0);
185 pmwrite(cmac, SUNI1x10GEXP_REG_RXOAM_INTERRUPT_ENABLE, 0);
186 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_0, 0);
187 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_1, 0);
188 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_2, 0);
189 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_3, 0);
190 pmwrite(cmac, SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_ENABLE, 0);
191 pmwrite(cmac, SUNI1x10GEXP_REG_PL4ODP_INTERRUPT_MASK, 0);
192 pmwrite(cmac, SUNI1x10GEXP_REG_XTEF_INTERRUPT_ENABLE, 0);
193 pmwrite(cmac, SUNI1x10GEXP_REG_TXOAM_INTERRUPT_ENABLE, 0);
194 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_3, 0);
195 pmwrite(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_MASK, 0);
196 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_3, 0);
197 pmwrite(cmac, SUNI1x10GEXP_REG_PL4IDU_INTERRUPT_MASK, 0);
198 pmwrite(cmac, SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_ENABLE, 0);
200 /* PM3393 - Global interrupt enable */
201 pmwrite(cmac, SUNI1x10GEXP_REG_GLOBAL_INTERRUPT_ENABLE, 0);
203 /* ELMER - External chip interrupts. */
204 t1_tpi_read(cmac->adapter, A_ELMER0_INT_ENABLE, &elmer);
205 elmer &= ~ELMER0_GP_BIT1;
206 t1_tpi_write(cmac->adapter, A_ELMER0_INT_ENABLE, elmer);
208 /* TERMINATOR - PL_INTERUPTS_EXT */
209 /* DO NOT DISABLE TERMINATOR's EXTERNAL INTERRUPTS. ANOTHER CHIP
210 * COULD WANT THEM ENABLED. We disable PM3393 at the ELMER level.
216 static int pm3393_interrupt_clear(struct cmac *cmac)
222 /* PM3393 - Clearing HW interrupt blocks. Note, this assumes
223 * bit WCIMODE=0 for a clear-on-read.
225 pmread(cmac, SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_STATUS, &val32);
226 pmread(cmac, SUNI1x10GEXP_REG_XRF_INTERRUPT_STATUS, &val32);
227 pmread(cmac, SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_STATUS, &val32);
228 pmread(cmac, SUNI1x10GEXP_REG_RXOAM_INTERRUPT_STATUS, &val32);
229 pmread(cmac, SUNI1x10GEXP_REG_PL4ODP_INTERRUPT, &val32);
230 pmread(cmac, SUNI1x10GEXP_REG_XTEF_INTERRUPT_STATUS, &val32);
231 pmread(cmac, SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_INTERRUPT, &val32);
232 pmread(cmac, SUNI1x10GEXP_REG_TXOAM_INTERRUPT_STATUS, &val32);
233 pmread(cmac, SUNI1x10GEXP_REG_RXXG_INTERRUPT, &val32);
234 pmread(cmac, SUNI1x10GEXP_REG_TXXG_INTERRUPT, &val32);
235 pmread(cmac, SUNI1x10GEXP_REG_PL4IDU_INTERRUPT, &val32);
236 pmread(cmac, SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_INDICATION,
238 pmread(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_STATUS, &val32);
239 pmread(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_CHANGE, &val32);
241 /* PM3393 - Global interrupt status
243 pmread(cmac, SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS, &val32);
245 /* ELMER - External chip interrupts.
247 t1_tpi_read(cmac->adapter, A_ELMER0_INT_CAUSE, &elmer);
248 elmer |= ELMER0_GP_BIT1;
249 t1_tpi_write(cmac->adapter, A_ELMER0_INT_CAUSE, elmer);
251 /* TERMINATOR - PL_INTERUPTS_EXT
253 pl_intr = readl(cmac->adapter->regs + A_PL_CAUSE);
254 pl_intr |= F_PL_INTR_EXT;
255 writel(pl_intr, cmac->adapter->regs + A_PL_CAUSE);
260 /* Interrupt handler */
261 static int pm3393_interrupt_handler(struct cmac *cmac)
263 u32 master_intr_status;
265 1. Read master interrupt register.
266 2. Read BLOCK's interrupt status registers.
267 3. Handle BLOCK interrupts.
269 /* Read the master interrupt status register. */
270 pmread(cmac, SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS,
271 &master_intr_status);
272 CH_DBG(cmac->adapter, INTR, "PM3393 intr cause 0x%x\n",
275 /* TBD XXX Lets just clear everything for now */
276 pm3393_interrupt_clear(cmac);
281 static int pm3393_enable(struct cmac *cmac, int which)
283 if (which & MAC_DIRECTION_RX)
284 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_1,
285 (RXXG_CONF1_VAL | SUNI1x10GEXP_BITMSK_RXXG_RXEN));
287 if (which & MAC_DIRECTION_TX) {
288 u32 val = TXXG_CONF1_VAL | SUNI1x10GEXP_BITMSK_TXXG_TXEN0;
290 if (cmac->instance->fc & PAUSE_RX)
291 val |= SUNI1x10GEXP_BITMSK_TXXG_FCRX;
292 if (cmac->instance->fc & PAUSE_TX)
293 val |= SUNI1x10GEXP_BITMSK_TXXG_FCTX;
294 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_1, val);
297 cmac->instance->enabled |= which;
301 static int pm3393_enable_port(struct cmac *cmac, int which)
303 /* Clear port statistics */
304 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_CONTROL,
305 SUNI1x10GEXP_BITMSK_MSTAT_CLEAR);
307 memset(&cmac->stats, 0, sizeof(struct cmac_statistics));
309 pm3393_enable(cmac, which);
312 * XXX This should be done by the PHY and preferrably not at all.
313 * The PHY doesn't give us link status indication on its own so have
314 * the link management code query it instead.
316 t1_link_changed(cmac->adapter, 0);
320 static int pm3393_disable(struct cmac *cmac, int which)
322 if (which & MAC_DIRECTION_RX)
323 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_1, RXXG_CONF1_VAL);
324 if (which & MAC_DIRECTION_TX)
325 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_1, TXXG_CONF1_VAL);
328 * The disable is graceful. Give the PM3393 time. Can't wait very
329 * long here, we may be holding locks.
333 cmac->instance->enabled &= ~which;
337 static int pm3393_loopback_enable(struct cmac *cmac)
342 static int pm3393_loopback_disable(struct cmac *cmac)
347 static int pm3393_set_mtu(struct cmac *cmac, int mtu)
349 int enabled = cmac->instance->enabled;
351 /* MAX_FRAME_SIZE includes header + FCS, mtu doesn't */
353 if (mtu > MAX_FRAME_SIZE)
356 /* Disable Rx/Tx MAC before configuring it. */
358 pm3393_disable(cmac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
360 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MAX_FRAME_LENGTH, mtu);
361 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_MAX_FRAME_SIZE, mtu);
364 pm3393_enable(cmac, enabled);
368 static u32 calc_crc(u8 *b, int len)
373 /* calculate crc one bit at a time */
376 for (i = 0; i < 8; i++) {
378 crc = (crc >> 1) ^ 0xedb88320;
385 crc = ((crc >> 4) & 0x0f0f0f0f) | ((crc << 4) & 0xf0f0f0f0);
386 crc = ((crc >> 2) & 0x33333333) | ((crc << 2) & 0xcccccccc);
387 crc = ((crc >> 1) & 0x55555555) | ((crc << 1) & 0xaaaaaaaa);
389 crc = (crc >> 16) | (crc << 16);
390 crc = (crc >> 8 & 0x00ff00ff) | (crc << 8 & 0xff00ff00);
395 static int pm3393_set_rx_mode(struct cmac *cmac, struct t1_rx_mode *rm)
397 int enabled = cmac->instance->enabled & MAC_DIRECTION_RX;
400 /* Disable MAC RX before reconfiguring it */
402 pm3393_disable(cmac, MAC_DIRECTION_RX);
404 pmread(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2, &rx_mode);
405 rx_mode &= ~(SUNI1x10GEXP_BITMSK_RXXG_PMODE |
406 SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN);
407 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2,
410 if (t1_rx_mode_promisc(rm)) {
411 /* Promiscuous mode. */
412 rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_PMODE;
414 if (t1_rx_mode_allmulti(rm)) {
415 /* Accept all multicast. */
416 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW, 0xffff);
417 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDLOW, 0xffff);
418 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDHIGH, 0xffff);
419 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_HIGH, 0xffff);
420 rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN;
421 } else if (t1_rx_mode_mc_cnt(rm)) {
422 /* Accept one or more multicast(s). */
425 u16 mc_filter[4] = { 0, };
427 while ((addr = t1_get_next_mcaddr(rm))) {
428 bit = (calc_crc(addr, ETH_ALEN) >> 23) & 0x3f; /* bit[23:28] */
429 mc_filter[bit >> 4] |= 1 << (bit & 0xf);
431 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW, mc_filter[0]);
432 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDLOW, mc_filter[1]);
433 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDHIGH, mc_filter[2]);
434 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_HIGH, mc_filter[3]);
435 rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN;
438 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2, (u16)rx_mode);
441 pm3393_enable(cmac, MAC_DIRECTION_RX);
446 static int pm3393_get_speed_duplex_fc(struct cmac *cmac, int *speed,
447 int *duplex, int *fc)
450 *speed = SPEED_10000;
452 *duplex = DUPLEX_FULL;
454 *fc = cmac->instance->fc;
458 static int pm3393_set_speed_duplex_fc(struct cmac *cmac, int speed, int duplex,
461 if (speed >= 0 && speed != SPEED_10000)
463 if (duplex >= 0 && duplex != DUPLEX_FULL)
465 if (fc & ~(PAUSE_TX | PAUSE_RX))
468 if (fc != cmac->instance->fc) {
469 cmac->instance->fc = (u8) fc;
470 if (cmac->instance->enabled & MAC_DIRECTION_TX)
471 pm3393_enable(cmac, MAC_DIRECTION_TX);
476 #define RMON_UPDATE(mac, name, stat_name) \
478 t1_tpi_read((mac)->adapter, OFFSET(name), &val0); \
479 t1_tpi_read((mac)->adapter, OFFSET(((name)+1)), &val1); \
480 t1_tpi_read((mac)->adapter, OFFSET(((name)+2)), &val2); \
481 (mac)->stats.stat_name = ((u64)val0 & 0xffff) | \
482 (((u64)val1 & 0xffff) << 16) | \
483 (((u64)val2 & 0xff) << 32) | \
484 ((mac)->stats.stat_name & \
487 ((name - SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW) >> 2)) \
488 (mac)->stats.stat_name += ((u64)1 << 40); \
491 static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac,
495 u32 val0, val1, val2, val3;
497 /* Snap the counters */
498 pmwrite(mac, SUNI1x10GEXP_REG_MSTAT_CONTROL,
499 SUNI1x10GEXP_BITMSK_MSTAT_SNAP);
501 /* Counter rollover, clear on read */
502 pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_0, &val0);
503 pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_1, &val1);
504 pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_2, &val2);
505 pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_3, &val3);
506 ro = ((u64)val0 & 0xffff) | (((u64)val1 & 0xffff) << 16) |
507 (((u64)val2 & 0xffff) << 32) | (((u64)val3 & 0xffff) << 48);
510 RMON_UPDATE(mac, RxOctetsReceivedOK, RxOctetsOK);
511 RMON_UPDATE(mac, RxUnicastFramesReceivedOK, RxUnicastFramesOK);
512 RMON_UPDATE(mac, RxMulticastFramesReceivedOK, RxMulticastFramesOK);
513 RMON_UPDATE(mac, RxBroadcastFramesReceivedOK, RxBroadcastFramesOK);
514 RMON_UPDATE(mac, RxPAUSEMACCtrlFramesReceived, RxPauseFrames);
515 RMON_UPDATE(mac, RxFrameCheckSequenceErrors, RxFCSErrors);
516 RMON_UPDATE(mac, RxFramesLostDueToInternalMACErrors,
517 RxInternalMACRcvError);
518 RMON_UPDATE(mac, RxSymbolErrors, RxSymbolErrors);
519 RMON_UPDATE(mac, RxInRangeLengthErrors, RxInRangeLengthErrors);
520 RMON_UPDATE(mac, RxFramesTooLongErrors , RxFrameTooLongErrors);
521 RMON_UPDATE(mac, RxJabbers, RxJabberErrors);
522 RMON_UPDATE(mac, RxFragments, RxRuntErrors);
523 RMON_UPDATE(mac, RxUndersizedFrames, RxRuntErrors);
524 RMON_UPDATE(mac, RxJumboFramesReceivedOK, RxJumboFramesOK);
525 RMON_UPDATE(mac, RxJumboOctetsReceivedOK, RxJumboOctetsOK);
528 RMON_UPDATE(mac, TxOctetsTransmittedOK, TxOctetsOK);
529 RMON_UPDATE(mac, TxFramesLostDueToInternalMACTransmissionError,
530 TxInternalMACXmitError);
531 RMON_UPDATE(mac, TxTransmitSystemError, TxFCSErrors);
532 RMON_UPDATE(mac, TxUnicastFramesTransmittedOK, TxUnicastFramesOK);
533 RMON_UPDATE(mac, TxMulticastFramesTransmittedOK, TxMulticastFramesOK);
534 RMON_UPDATE(mac, TxBroadcastFramesTransmittedOK, TxBroadcastFramesOK);
535 RMON_UPDATE(mac, TxPAUSEMACCtrlFramesTransmitted, TxPauseFrames);
536 RMON_UPDATE(mac, TxJumboFramesReceivedOK, TxJumboFramesOK);
537 RMON_UPDATE(mac, TxJumboOctetsReceivedOK, TxJumboOctetsOK);
542 static int pm3393_macaddress_get(struct cmac *cmac, u8 mac_addr[6])
544 memcpy(mac_addr, cmac->instance->mac_addr, 6);
548 static int pm3393_macaddress_set(struct cmac *cmac, u8 ma[6])
550 u32 val, lo, mid, hi, enabled = cmac->instance->enabled;
553 * MAC addr: 00:07:43:00:13:09
562 * The PM3393 requires byte swapping and reverse order entry
563 * when programming MAC addresses:
565 * low_bits[15:0] = ma[1]:ma[0]
566 * mid_bits[31:16] = ma[3]:ma[2]
567 * high_bits[47:32] = ma[5]:ma[4]
570 /* Store local copy */
571 memcpy(cmac->instance->mac_addr, ma, 6);
573 lo = ((u32) ma[1] << 8) | (u32) ma[0];
574 mid = ((u32) ma[3] << 8) | (u32) ma[2];
575 hi = ((u32) ma[5] << 8) | (u32) ma[4];
577 /* Disable Rx/Tx MAC before configuring it. */
579 pm3393_disable(cmac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
581 /* Set RXXG Station Address */
582 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_15_0, lo);
583 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_31_16, mid);
584 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_47_32, hi);
586 /* Set TXXG Station Address */
587 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_15_0, lo);
588 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_31_16, mid);
589 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_47_32, hi);
591 /* Setup Exact Match Filter 1 with our MAC address
593 * Must disable exact match filter before configuring it.
595 pmread(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, &val);
597 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, val);
599 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_LOW, lo);
600 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_MID, mid);
601 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_HIGH, hi);
604 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, val);
607 pm3393_enable(cmac, enabled);
611 static void pm3393_destroy(struct cmac *cmac)
616 static struct cmac_ops pm3393_ops = {
617 .destroy = pm3393_destroy,
618 .reset = pm3393_reset,
619 .interrupt_enable = pm3393_interrupt_enable,
620 .interrupt_disable = pm3393_interrupt_disable,
621 .interrupt_clear = pm3393_interrupt_clear,
622 .interrupt_handler = pm3393_interrupt_handler,
623 .enable = pm3393_enable_port,
624 .disable = pm3393_disable,
625 .loopback_enable = pm3393_loopback_enable,
626 .loopback_disable = pm3393_loopback_disable,
627 .set_mtu = pm3393_set_mtu,
628 .set_rx_mode = pm3393_set_rx_mode,
629 .get_speed_duplex_fc = pm3393_get_speed_duplex_fc,
630 .set_speed_duplex_fc = pm3393_set_speed_duplex_fc,
631 .statistics_update = pm3393_update_statistics,
632 .macaddress_get = pm3393_macaddress_get,
633 .macaddress_set = pm3393_macaddress_set
636 static struct cmac *pm3393_mac_create(adapter_t *adapter, int index)
640 cmac = kzalloc(sizeof(*cmac) + sizeof(cmac_instance), GFP_KERNEL);
644 cmac->ops = &pm3393_ops;
645 cmac->instance = (cmac_instance *) (cmac + 1);
646 cmac->adapter = adapter;
647 cmac->instance->fc = PAUSE_TX | PAUSE_RX;
649 t1_tpi_write(adapter, OFFSET(0x0001), 0x00008000);
650 t1_tpi_write(adapter, OFFSET(0x0001), 0x00000000);
651 t1_tpi_write(adapter, OFFSET(0x2308), 0x00009800);
652 t1_tpi_write(adapter, OFFSET(0x2305), 0x00001001); /* PL4IO Enable */
653 t1_tpi_write(adapter, OFFSET(0x2320), 0x00008800);
654 t1_tpi_write(adapter, OFFSET(0x2321), 0x00008800);
655 t1_tpi_write(adapter, OFFSET(0x2322), 0x00008800);
656 t1_tpi_write(adapter, OFFSET(0x2323), 0x00008800);
657 t1_tpi_write(adapter, OFFSET(0x2324), 0x00008800);
658 t1_tpi_write(adapter, OFFSET(0x2325), 0x00008800);
659 t1_tpi_write(adapter, OFFSET(0x2326), 0x00008800);
660 t1_tpi_write(adapter, OFFSET(0x2327), 0x00008800);
661 t1_tpi_write(adapter, OFFSET(0x2328), 0x00008800);
662 t1_tpi_write(adapter, OFFSET(0x2329), 0x00008800);
663 t1_tpi_write(adapter, OFFSET(0x232a), 0x00008800);
664 t1_tpi_write(adapter, OFFSET(0x232b), 0x00008800);
665 t1_tpi_write(adapter, OFFSET(0x232c), 0x00008800);
666 t1_tpi_write(adapter, OFFSET(0x232d), 0x00008800);
667 t1_tpi_write(adapter, OFFSET(0x232e), 0x00008800);
668 t1_tpi_write(adapter, OFFSET(0x232f), 0x00008800);
669 t1_tpi_write(adapter, OFFSET(0x230d), 0x00009c00);
670 t1_tpi_write(adapter, OFFSET(0x2304), 0x00000202); /* PL4IO Calendar Repetitions */
672 t1_tpi_write(adapter, OFFSET(0x3200), 0x00008080); /* EFLX Enable */
673 t1_tpi_write(adapter, OFFSET(0x3210), 0x00000000); /* EFLX Channel Deprovision */
674 t1_tpi_write(adapter, OFFSET(0x3203), 0x00000000); /* EFLX Low Limit */
675 t1_tpi_write(adapter, OFFSET(0x3204), 0x00000040); /* EFLX High Limit */
676 t1_tpi_write(adapter, OFFSET(0x3205), 0x000002cc); /* EFLX Almost Full */
677 t1_tpi_write(adapter, OFFSET(0x3206), 0x00000199); /* EFLX Almost Empty */
678 t1_tpi_write(adapter, OFFSET(0x3207), 0x00000240); /* EFLX Cut Through Threshold */
679 t1_tpi_write(adapter, OFFSET(0x3202), 0x00000000); /* EFLX Indirect Register Update */
680 t1_tpi_write(adapter, OFFSET(0x3210), 0x00000001); /* EFLX Channel Provision */
681 t1_tpi_write(adapter, OFFSET(0x3208), 0x0000ffff); /* EFLX Undocumented */
682 t1_tpi_write(adapter, OFFSET(0x320a), 0x0000ffff); /* EFLX Undocumented */
683 t1_tpi_write(adapter, OFFSET(0x320c), 0x0000ffff); /* EFLX enable overflow interrupt The other bit are undocumented */
684 t1_tpi_write(adapter, OFFSET(0x320e), 0x0000ffff); /* EFLX Undocumented */
686 t1_tpi_write(adapter, OFFSET(0x2200), 0x0000c000); /* IFLX Configuration - enable */
687 t1_tpi_write(adapter, OFFSET(0x2201), 0x00000000); /* IFLX Channel Deprovision */
688 t1_tpi_write(adapter, OFFSET(0x220e), 0x00000000); /* IFLX Low Limit */
689 t1_tpi_write(adapter, OFFSET(0x220f), 0x00000100); /* IFLX High Limit */
690 t1_tpi_write(adapter, OFFSET(0x2210), 0x00000c00); /* IFLX Almost Full Limit */
691 t1_tpi_write(adapter, OFFSET(0x2211), 0x00000599); /* IFLX Almost Empty Limit */
692 t1_tpi_write(adapter, OFFSET(0x220d), 0x00000000); /* IFLX Indirect Register Update */
693 t1_tpi_write(adapter, OFFSET(0x2201), 0x00000001); /* IFLX Channel Provision */
694 t1_tpi_write(adapter, OFFSET(0x2203), 0x0000ffff); /* IFLX Undocumented */
695 t1_tpi_write(adapter, OFFSET(0x2205), 0x0000ffff); /* IFLX Undocumented */
696 t1_tpi_write(adapter, OFFSET(0x2209), 0x0000ffff); /* IFLX Enable overflow interrupt. The other bit are undocumented */
698 t1_tpi_write(adapter, OFFSET(0x2241), 0xfffffffe); /* PL4MOS Undocumented */
699 t1_tpi_write(adapter, OFFSET(0x2242), 0x0000ffff); /* PL4MOS Undocumented */
700 t1_tpi_write(adapter, OFFSET(0x2243), 0x00000008); /* PL4MOS Starving Burst Size */
701 t1_tpi_write(adapter, OFFSET(0x2244), 0x00000008); /* PL4MOS Hungry Burst Size */
702 t1_tpi_write(adapter, OFFSET(0x2245), 0x00000008); /* PL4MOS Transfer Size */
703 t1_tpi_write(adapter, OFFSET(0x2240), 0x00000005); /* PL4MOS Disable */
705 t1_tpi_write(adapter, OFFSET(0x2280), 0x00002103); /* PL4ODP Training Repeat and SOP rule */
706 t1_tpi_write(adapter, OFFSET(0x2284), 0x00000000); /* PL4ODP MAX_T setting */
708 t1_tpi_write(adapter, OFFSET(0x3280), 0x00000087); /* PL4IDU Enable data forward, port state machine. Set ALLOW_NON_ZERO_OLB */
709 t1_tpi_write(adapter, OFFSET(0x3282), 0x0000001f); /* PL4IDU Enable Dip4 check error interrupts */
711 t1_tpi_write(adapter, OFFSET(0x3040), 0x0c32); /* # TXXG Config */
712 /* For T1 use timer based Mac flow control. */
713 t1_tpi_write(adapter, OFFSET(0x304d), 0x8000);
714 t1_tpi_write(adapter, OFFSET(0x2040), 0x059c); /* # RXXG Config */
715 t1_tpi_write(adapter, OFFSET(0x2049), 0x0001); /* # RXXG Cut Through */
716 t1_tpi_write(adapter, OFFSET(0x2070), 0x0000); /* # Disable promiscuous mode */
718 /* Setup Exact Match Filter 0 to allow broadcast packets.
720 t1_tpi_write(adapter, OFFSET(0x206e), 0x0000); /* # Disable Match Enable bit */
721 t1_tpi_write(adapter, OFFSET(0x204a), 0xffff); /* # low addr */
722 t1_tpi_write(adapter, OFFSET(0x204b), 0xffff); /* # mid addr */
723 t1_tpi_write(adapter, OFFSET(0x204c), 0xffff); /* # high addr */
724 t1_tpi_write(adapter, OFFSET(0x206e), 0x0009); /* # Enable Match Enable bit */
726 t1_tpi_write(adapter, OFFSET(0x0003), 0x0000); /* # NO SOP/ PAD_EN setup */
727 t1_tpi_write(adapter, OFFSET(0x0100), 0x0ff0); /* # RXEQB disabled */
728 t1_tpi_write(adapter, OFFSET(0x0101), 0x0f0f); /* # No Preemphasis */
733 static int pm3393_mac_reset(adapter_t * adapter)
737 u32 is_pl4_reset_finished;
738 u32 is_pl4_outof_lock;
739 u32 is_xaui_mabc_pll_locked;
740 u32 successful_reset;
743 /* The following steps are required to properly reset
744 * the PM3393. This information is provided in the
745 * PM3393 datasheet (Issue 2: November 2002)
746 * section 13.1 -- Device Reset.
748 * The PM3393 has three types of components that are
749 * individually reset:
751 * DRESETB - Digital circuitry
752 * PL4_ARESETB - PL4 analog circuitry
753 * XAUI_ARESETB - XAUI bus analog circuitry
755 * Steps to reset PM3393 using RSTB pin:
757 * 1. Assert RSTB pin low ( write 0 )
758 * 2. Wait at least 1ms to initiate a complete initialization of device.
759 * 3. Wait until all external clocks and REFSEL are stable.
760 * 4. Wait minimum of 1ms. (after external clocks and REFEL are stable)
761 * 5. De-assert RSTB ( write 1 )
762 * 6. Wait until internal timers to expires after ~14ms.
763 * - Allows analog clock synthesizer(PL4CSU) to stabilize to
764 * selected reference frequency before allowing the digital
765 * portion of the device to operate.
766 * 7. Wait at least 200us for XAUI interface to stabilize.
767 * 8. Verify the PM3393 came out of reset successfully.
768 * Set successful reset flag if everything worked else try again
772 successful_reset = 0;
773 for (i = 0; i < 3 && !successful_reset; i++) {
775 t1_tpi_read(adapter, A_ELMER0_GPO, &val);
777 t1_tpi_write(adapter, A_ELMER0_GPO, val);
786 msleep(2 /*1 extra ms for safety */ );
790 t1_tpi_write(adapter, A_ELMER0_GPO, val);
793 msleep(15 /*1 extra ms for safety */ );
800 /* Has PL4 analog block come out of reset correctly? */
801 t1_tpi_read(adapter, OFFSET(SUNI1x10GEXP_REG_DEVICE_STATUS), &val);
802 is_pl4_reset_finished = (val & SUNI1x10GEXP_BITMSK_TOP_EXPIRED);
804 /* TBD XXX SUNI1x10GEXP_BITMSK_TOP_PL4_IS_DOOL gets locked later in the init sequence
807 /* Have all PL4 block clocks locked? */
808 x = (SUNI1x10GEXP_BITMSK_TOP_PL4_ID_DOOL
809 /*| SUNI1x10GEXP_BITMSK_TOP_PL4_IS_DOOL */ |
810 SUNI1x10GEXP_BITMSK_TOP_PL4_ID_ROOL |
811 SUNI1x10GEXP_BITMSK_TOP_PL4_IS_ROOL |
812 SUNI1x10GEXP_BITMSK_TOP_PL4_OUT_ROOL);
813 is_pl4_outof_lock = (val & x);
815 /* ??? If this fails, might be able to software reset the XAUI part
816 * and try to recover... thus saving us from doing another HW reset */
817 /* Has the XAUI MABC PLL circuitry stablized? */
818 is_xaui_mabc_pll_locked =
819 (val & SUNI1x10GEXP_BITMSK_TOP_SXRA_EXPIRED);
821 successful_reset = (is_pl4_reset_finished && !is_pl4_outof_lock
822 && is_xaui_mabc_pll_locked);
825 "PM3393 HW reset %d: pl4_reset 0x%x, val 0x%x, "
826 "is_pl4_outof_lock 0x%x, xaui_locked 0x%x\n",
827 i, is_pl4_reset_finished, val, is_pl4_outof_lock,
828 is_xaui_mabc_pll_locked);
830 return successful_reset ? 0 : 1;
833 struct gmac t1_pm3393_ops = {