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