1 /*****************************************************************************
5 * $Date: 2005/03/23 07:41:27 $ *
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)
48 #define MMD_RESERVED 0
52 #define MMD_PHY_XGXS 4 /* XGMII Extender Sublayer */
53 #define MMD_DTE_XGXS 5
55 #define PHY_XGXS_CTRL_1 0
56 #define PHY_XGXS_STATUS_1 1
58 #define OFFSET(REG_ADDR) (REG_ADDR << 2)
60 /* Max frame size PM3393 can handle. Includes Ethernet header and CRC. */
61 #define MAX_FRAME_SIZE 9600
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)
70 /* Update statistics every 15 minutes */
71 #define STATS_TICK_SECS (15 * 60)
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,
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
97 struct _cmac_instance {
103 static int pmread(struct cmac *cmac, u32 reg, u32 * data32)
105 t1_tpi_read(cmac->adapter, OFFSET(reg), data32);
109 static int pmwrite(struct cmac *cmac, u32 reg, u32 data32)
111 t1_tpi_write(cmac->adapter, OFFSET(reg), data32);
116 static int pm3393_reset(struct cmac *cmac)
122 * Enable interrupts for the PM3393
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.
129 static int pm3393_interrupt_enable(struct cmac *cmac)
133 /* PM3393 - Enabling all hardware block interrupts.
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);
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);
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);
156 /* PM3393 - Global interrupt enable
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 */ );
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);
169 static int pm3393_interrupt_disable(struct cmac *cmac)
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);
192 /* PM3393 - Global interrupt enable */
193 pmwrite(cmac, SUNI1x10GEXP_REG_GLOBAL_INTERRUPT_ENABLE, 0);
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);
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.
208 static int pm3393_interrupt_clear(struct cmac *cmac)
214 /* PM3393 - Clearing HW interrupt blocks. Note, this assumes
215 * bit WCIMODE=0 for a clear-on-read.
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,
230 pmread(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_STATUS, &val32);
231 pmread(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_CHANGE, &val32);
233 /* PM3393 - Global interrupt status
235 pmread(cmac, SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS, &val32);
237 /* ELMER - External chip interrupts.
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);
243 /* TERMINATOR - PL_INTERUPTS_EXT
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);
252 /* Interrupt handler */
253 static int pm3393_interrupt_handler(struct cmac *cmac)
255 u32 master_intr_status;
257 1. Read master interrupt register.
258 2. Read BLOCK's interrupt status registers.
259 3. Handle BLOCK interrupts.
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",
267 /* TBD XXX Lets just clear everything for now */
268 pm3393_interrupt_clear(cmac);
273 static int pm3393_enable(struct cmac *cmac, int which)
275 if (which & MAC_DIRECTION_RX)
276 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_1,
277 (RXXG_CONF1_VAL | SUNI1x10GEXP_BITMSK_RXXG_RXEN));
279 if (which & MAC_DIRECTION_TX) {
280 u32 val = TXXG_CONF1_VAL | SUNI1x10GEXP_BITMSK_TXXG_TXEN0;
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);
289 cmac->instance->enabled |= which;
293 static int pm3393_enable_port(struct cmac *cmac, int which)
295 /* Clear port statistics */
296 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_CONTROL,
297 SUNI1x10GEXP_BITMSK_MSTAT_CLEAR);
299 memset(&cmac->stats, 0, sizeof(struct cmac_statistics));
301 pm3393_enable(cmac, which);
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.
309 extern void link_changed(adapter_t *adapter, int port_id);
311 link_changed(cmac->adapter, 0);
316 static int pm3393_disable(struct cmac *cmac, int which)
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);
324 * The disable is graceful. Give the PM3393 time. Can't wait very
325 * long here, we may be holding locks.
329 cmac->instance->enabled &= ~which;
333 static int pm3393_loopback_enable(struct cmac *cmac)
338 static int pm3393_loopback_disable(struct cmac *cmac)
343 static int pm3393_set_mtu(struct cmac *cmac, int mtu)
345 int enabled = cmac->instance->enabled;
347 /* MAX_FRAME_SIZE includes header + FCS, mtu doesn't */
349 if (mtu > MAX_FRAME_SIZE)
352 /* Disable Rx/Tx MAC before configuring it. */
354 pm3393_disable(cmac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
356 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MAX_FRAME_LENGTH, mtu);
357 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_MAX_FRAME_SIZE, mtu);
360 pm3393_enable(cmac, enabled);
364 static u32 calc_crc(u8 *b, int len)
369 /* calculate crc one bit at a time */
372 for (i = 0; i < 8; i++) {
374 crc = (crc >> 1) ^ 0xedb88320;
381 crc = ((crc >> 4) & 0x0f0f0f0f) | ((crc << 4) & 0xf0f0f0f0);
382 crc = ((crc >> 2) & 0x33333333) | ((crc << 2) & 0xcccccccc);
383 crc = ((crc >> 1) & 0x55555555) | ((crc << 1) & 0xaaaaaaaa);
385 crc = (crc >> 16) | (crc << 16);
386 crc = (crc >> 8 & 0x00ff00ff) | (crc << 8 & 0xff00ff00);
391 static int pm3393_set_rx_mode(struct cmac *cmac, struct t1_rx_mode *rm)
393 int enabled = cmac->instance->enabled & MAC_DIRECTION_RX;
396 /* Disable MAC RX before reconfiguring it */
398 pm3393_disable(cmac, MAC_DIRECTION_RX);
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,
406 if (t1_rx_mode_promisc(rm)) {
407 /* Promiscuous mode. */
408 rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_PMODE;
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). */
421 u16 mc_filter[4] = { 0, };
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);
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;
434 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2, (u16)rx_mode);
437 pm3393_enable(cmac, MAC_DIRECTION_RX);
442 static int pm3393_get_speed_duplex_fc(struct cmac *cmac, int *speed,
443 int *duplex, int *fc)
446 *speed = SPEED_10000;
448 *duplex = DUPLEX_FULL;
450 *fc = cmac->instance->fc;
454 static int pm3393_set_speed_duplex_fc(struct cmac *cmac, int speed, int duplex,
457 if (speed >= 0 && speed != SPEED_10000)
459 if (duplex >= 0 && duplex != DUPLEX_FULL)
461 if (fc & ~(PAUSE_TX | PAUSE_RX))
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);
472 #define RMON_UPDATE(mac, name, stat_name) \
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 & \
483 ((name - SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW) >> 2)) \
484 (mac)->stats.stat_name += ((u64)1 << 40); \
487 static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac,
491 u32 val0, val1, val2, val3;
493 /* Snap the counters */
494 pmwrite(mac, SUNI1x10GEXP_REG_MSTAT_CONTROL,
495 SUNI1x10GEXP_BITMSK_MSTAT_SNAP);
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);
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);
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);
534 static int pm3393_macaddress_get(struct cmac *cmac, u8 mac_addr[6])
536 memcpy(mac_addr, cmac->instance->mac_addr, 6);
540 static int pm3393_macaddress_set(struct cmac *cmac, u8 ma[6])
542 u32 val, lo, mid, hi, enabled = cmac->instance->enabled;
545 * MAC addr: 00:07:43:00:13:09
554 * The PM3393 requires byte swapping and reverse order entry
555 * when programming MAC addresses:
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]
562 /* Store local copy */
563 memcpy(cmac->instance->mac_addr, ma, 6);
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];
569 /* Disable Rx/Tx MAC before configuring it. */
571 pm3393_disable(cmac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
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);
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);
583 /* Setup Exact Match Filter 1 with our MAC address
585 * Must disable exact match filter before configuring it.
587 pmread(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, &val);
589 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, val);
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);
596 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, val);
599 pm3393_enable(cmac, enabled);
603 static void pm3393_destroy(struct cmac *cmac)
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
628 static struct cmac *pm3393_mac_create(adapter_t *adapter, int index)
632 cmac = kmalloc(sizeof(*cmac) + sizeof(cmac_instance), GFP_KERNEL);
635 memset(cmac, 0, sizeof(*cmac));
637 cmac->ops = &pm3393_ops;
638 cmac->instance = (cmac_instance *) (cmac + 1);
639 cmac->adapter = adapter;
640 cmac->instance->fc = PAUSE_TX | PAUSE_RX;
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 */
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 */
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 */
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 */
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 */
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 */
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 */
712 /* Setup Exact Match Filter 0 to allow broadcast packets.
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 */
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 */
727 static int pm3393_mac_reset(adapter_t * adapter)
731 u32 is_pl4_reset_finished;
732 u32 is_pl4_outof_lock;
733 u32 is_xaui_mabc_pll_locked;
734 u32 successful_reset;
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.
742 * The PM3393 has three types of components that are
743 * individually reset:
745 * DRESETB - Digital circuitry
746 * PL4_ARESETB - PL4 analog circuitry
747 * XAUI_ARESETB - XAUI bus analog circuitry
749 * Steps to reset PM3393 using RSTB pin:
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
766 successful_reset = 0;
767 for (i = 0; i < 3 && !successful_reset; i++) {
769 t1_tpi_read(adapter, A_ELMER0_GPO, &val);
771 t1_tpi_write(adapter, A_ELMER0_GPO, val);
780 msleep(2 /*1 extra ms for safety */ );
784 t1_tpi_write(adapter, A_ELMER0_GPO, val);
787 msleep(15 /*1 extra ms for safety */ );
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);
798 /* TBD XXX SUNI1x10GEXP_BITMSK_TOP_PL4_IS_DOOL gets locked later in the init sequence
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);
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);
815 successful_reset = (is_pl4_reset_finished && !is_pl4_outof_lock
816 && is_xaui_mabc_pll_locked);
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);
824 return successful_reset ? 0 : 1;
827 struct gmac t1_pm3393_ops = {