/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (C) 2003-2005 Chelsio Communications. All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI" /* pm3393.c */
#include "common.h"
#include "regs.h"
#include "gmac.h"
#include "elmer0.h"
#include "suni1x10gexp_regs.h"
/* 802.3ae 10Gb/s MDIO Manageable Device(MMD)
*/
#define MMD_RESERVED 0
#define PHY_XGXS_CTRL_1 0
/* Max frame size PM3393 can handle. Includes Ethernet header and CRC. */
/* Update statistics every 15 minutes */
enum { /* RMON registers */
};
struct _cmac_instance {
};
{
return 0;
}
{
return 0;
}
/* Port reset. */
/* ARGSUSED */
{
return 0;
}
/*
* Enable interrupts for the PM3393
1. Enable PM3393 BLOCK interrupts.
2. Enable PM3393 Master Interrupt bit(INTE)
3. Enable ELMER's PM3393 bit.
4. Enable Terminator external interrupt.
*/
{
#if 0
#endif
/* PM3393 - Enabling all hardware block interrupts.
*/
/* Don't interrupt on statistics overflow, we are polling */
/* PM3393 - Global interrupt enable
*/
/* TBD XXX Disable for now until we figure out why error interrupts keep asserting. */
0 /*SUNI1x10GEXP_BITMSK_TOP_INTE */ );
#if 0
/* ELMER - External chip interrupts.
*/
elmer |= ELMER0_GP_BIT1;
#endif
/* TERMINATOR - PL_INTERUPTS_EXT */
pl_intr |= F_PL_INTR_EXT;
return 0;
}
{
/* PM3393 - Enabling HW interrupt blocks. */
/* PM3393 - Global interrupt enable */
/* ELMER - External chip interrupts. */
elmer &= ~ELMER0_GP_BIT1;
/* TERMINATOR - PL_INTERUPTS_EXT */
/* DO NOT DISABLE TERMINATOR's EXTERNAL INTERRUPTS. ANOTHER CHIP
* COULD WANT THEM ENABLED. We disable PM3393 at the ELMER level.
*/
return 0;
}
{
/* PM3393 - Clearing HW interrupt blocks. Note, this assumes
* bit WCIMODE=0 for a clear-on-read.
*/
&val32);
/* PM3393 - Global interrupt status
*/
/* ELMER - External chip interrupts.
*/
elmer |= ELMER0_GP_BIT1;
/* TERMINATOR - PL_INTERUPTS_EXT
*/
pl_intr |= F_PL_INTR_EXT;
return 0;
}
/* Interrupt handler */
{
/*
1. Read master interrupt register.
2. Read BLOCK's interrupt status registers.
3. Handle BLOCK interrupts.
*/
/* Read the master interrupt status register. */
/* Handle BLOCK's interrupts. */
/* EMPTY */
}
/* EMPTY */
}
/* EMPTY */
}
/* SERDES */
/* EMPTY */
}
/* MSTAT */
/* EMPTY */
}
/* RXXG */
/* EMPTY */
}
/* TXXG */
/* EMPTY */
}
/* XRF */
/* EMPTY */
}
/* XTEF */
/* EMPTY */
}
/* MDIO */
/* Not used. 8000 uses MDIO through Elmer. */
/* EMPTY */
}
/* RXOAM */
/* EMPTY */
}
/* TXOAM */
/* EMPTY */
}
/* IFLX */
/* EMPTY */
}
/* EFLX */
/* EMPTY */
}
/* PL4ODP */
/* EMPTY */
}
/* PL4IDU */
/* EMPTY */
}
/* TBD XXX Lets just clear everything for now */
(void) pm3393_interrupt_clear(cmac);
return 0;
}
{
if (which & MAC_DIRECTION_RX)
if (which & MAC_DIRECTION_TX) {
}
return 0;
}
/* ARGSUSED */
{
/* Clear port statistics */
DELAY_US(2);
/*
* XXX This should be done by the PHY and preferrably not at all.
* The PHY doesn't give us link status indication on its own so have
* the link management code query it instead.
*/
{
}
return 0;
}
{
if (which & MAC_DIRECTION_RX)
if (which & MAC_DIRECTION_TX)
/*
* The disable is graceful. Give the PM3393 time. Can't wait very
* long here, we may be holding locks.
*/
DELAY_US(20);
return 0;
}
/* ARGSUSED */
{
return 0;
}
/* ARGSUSED */
{
return 0;
}
{
/* MAX_FRAME_SIZE includes header + FCS, mtu doesn't */
if (mtu > MAX_FRAME_SIZE)
return -EINVAL;
if (enabled)
if (enabled)
return 0;
}
{
int i;
/* calculate crc one bit at a time */
while (len--) {
crc ^= *b++;
for (i = 0; i < 8; i++) {
if (crc & 0x1)
else
}
}
/* reverse bits */
/* swap bytes */
return crc;
}
{
/* Disable MAC RX before reconfiguring it */
if (enabled)
if (t1_rx_mode_promisc(rm)) {
/* Promiscuous mode. */
}
if (t1_rx_mode_allmulti(rm)) {
/* Accept all multicast. */
} else if (t1_rx_mode_mc_cnt(rm)) {
/* Accept one or more multicast(s). */
int bit;
}
}
if (enabled)
return 0;
}
{
if (speed)
*speed = SPEED_10000;
if (duplex)
*duplex = DUPLEX_FULL;
if (fc)
return 0;
}
int fc)
{
return -1;
return -1;
return -1;
}
return 0;
}
{ \
}
/* ARGSUSED */
int flag)
{
/* Snap the counters */
/* Counter rollover, clear on read */
/* Rx stats */
/* Tx stats */
}
{
return 0;
}
{
/*
* MAC addr: 00:07:43:00:13:09
*
* ma[5] = 0x09
* ma[4] = 0x13
* ma[3] = 0x00
* ma[2] = 0x43
* ma[1] = 0x07
* ma[0] = 0x00
*
* The PM3393 requires byte swapping and reverse order entry
* when programming MAC addresses:
*
* low_bits[15:0] = ma[1]:ma[0]
* mid_bits[31:16] = ma[3]:ma[2]
* high_bits[47:32] = ma[5]:ma[4]
*/
/* Store local copy */
if (enabled)
/* Set RXXG Station Address */
/* Set TXXG Station Address */
/* Setup Exact Match Filter 1 with our MAC address
*
* Must disable exact match filter before configuring it.
*/
val &= 0xff0f;
val |= 0x0090;
if (enabled)
return 0;
}
{
}
#ifdef C99_NOT_SUPPORTED
};
#else
.reset = pm3393_reset,
};
#endif
/* ARGSUSED */
{
if (!cmac)
return NULL;
(void) t1_tpi_write(adapter, OFFSET(0x320c), 0x0000ffff); /* EFLX enable overflow interrupt The other bit are undocumented */
(void) t1_tpi_write(adapter, OFFSET(0x2209), 0x0000ffff); /* IFLX Enable overflow interrupt. The other bit are undocumented */
(void) t1_tpi_write(adapter, OFFSET(0x3280), 0x00000087); /* PL4IDU Enable data forward, port state machine. Set ALLOW_NON_ZERO_OLB */
(void) t1_tpi_write(adapter, OFFSET(0x3282), 0x0000001f); /* PL4IDU Enable Dip4 check error interrupts */
/* For T1 use timer based Mac flow control. */
/* Setup Exact Match Filter 0 to allow broadcast packets.
*/
return cmac;
}
{
u32 x;
int i;
/* The following steps are required to properly reset
* the PM3393. This information is provided in the
* PM3393 datasheet (Issue 2: November 2002)
* section 13.1 -- Device Reset.
*
* The PM3393 has three types of components that are
* individually reset:
*
* DRESETB - Digital circuitry
* PL4_ARESETB - PL4 analog circuitry
* XAUI_ARESETB - XAUI bus analog circuitry
*
* Steps to reset PM3393 using RSTB pin:
*
* 1. Assert RSTB pin low ( write 0 )
* 2. Wait at least 1ms to initiate a complete initialization of device.
* 3. Wait until all external clocks and REFSEL are stable.
* 4. Wait minimum of 1ms. (after external clocks and REFEL are stable)
* 5. De-assert RSTB ( write 1 )
* 6. Wait until internal timers to expires after ~14ms.
* - Allows analog clock synthesizer(PL4CSU) to stabilize to
* selected reference frequency before allowing the digital
* portion of the device to operate.
* 7. Wait at least 200us for XAUI interface to stabilize.
* 8. Verify the PM3393 came out of reset successfully.
* Set successful reset flag if everything worked else try again
* a few more times.
*/
successful_reset = 0;
for (i = 0; i < 3 && !successful_reset; i++) {
/* 1 */
val &= ~1;
/* 2 */
DELAY_MS(1);
/* 3 */
DELAY_MS(1);
/* 4 */
/* 5 */
val |= 1;
/* 6 */
/* 7 */
DELAY_MS(1);
/* 8 */
/* Has PL4 analog block come out of reset correctly? */
/* TBD XXX SUNI1x10GEXP_BITMSK_TOP_PL4_IS_DOOL gets locked later in the init sequence
* figure out why? */
/* Have all PL4 block clocks locked? */
/*| SUNI1x10GEXP_BITMSK_TOP_PL4_IS_DOOL */ |
is_pl4_outof_lock = (val & x);
/* ??? If this fails, might be able to software reset the XAUI part
* and try to recover... thus saving us from doing another HW reset */
/* Has the XAUI MABC PLL circuitry stablized? */
"PM3393 HW reset %d: pl4_reset 0x%x, val 0x%x, "
"is_pl4_outof_lock 0x%x, xaui_locked 0x%x\n",
}
return successful_reset ? 0 : 1;
}
};