blob: 6e6231c60a27b8fac3d65a47d9619fa9fef3e870 [file] [log] [blame]
/*------------------------------------------------------------------------------
*
* Copyright (c) 2003
* CADENCE CADENCE DESIGN FOUNDRY
* All rights reserved.
*
*------------------------------------------------------------------------------
*
* Filename : gem_AL.c
*
* Author : Steven Ho, DICS, LDC
*
* Date : 9th Oct 2001
*
* Limitations : Due to the use of bit-fields, only little endian
* architectures is currently supported. The header file
* will need to be updated for other architectures.
*
*------------------------------------------------------------------------------
* Description : A Hardware Abstraction Layer for the Cadence Gigabit
* Ethernet MAC (gem).
* This comprises of a set of functions and macros to
* provide a simple abstracted view to operating the MAC
* enabling the MAC software development in the minimal
* amount of time.
*
*------------------------------------------------------------------------------
* Revision Control
*
*------------------------------------------------------------------------------
*/
#include <common.h>
#include <config.h>
#include <asm/arch/hardware.h>
#include <asm/byteorder.h>
#include <malloc.h>
#include <net.h>
#include <command.h>
#if defined(CONFIG_COMCERTO_GEMAC)
#include "comcerto_gem.h"
/******************************************************************************/
/* Some functions to set/reset and get specific bits in the MAC registers
* Note that all functions operate on a read-modify-write basis
*/
/******************************************************************************/
/*
* Function to start transmission on the specified device. The parameter to
* this function is simply a pointer to the struct gemac_dev structure.
* This function should be called after the relevant queues and data has been
* set up, however it will check if the number of queue elements is zero first.
* Note that this function will also enable tx even if it was previously not set
*
* Return value:
* 0 : OK
* -1 : Transmit queue not valid.
*/
/******************************************************************************/
int gem_start_tx(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) |= __cpu_to_le32(GEM_TX_START | GEM_TX_EN);
return 0;
}
/******************************************************************************/
/******************************************************************************/
/*
* Halt transmission after current frame has completed. This is accomplished
* simply by writing to the GEM_TX_HALT bit in the network control register,
* which should cause the MAC to complete its current frame then stop.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_stop_tx(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) |= __cpu_to_le32(GEM_TX_HALT);
}
/******************************************************************************/
/******************************************************************************/
/*
* Abort transmission immediately WITHOUT waiting for completion of any current
* frame.
* Note that after this operation, the transmit buffer descriptor will be reset
* to point to the first buffer in the descriptor list!
*
* There is no return value.
*/
/******************************************************************************/
void gem_abort_tx(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) &= __cpu_to_le32(~(GEM_TX_START | GEM_TX_EN));
}
/******************************************************************************/
/******************************************************************************/
/*
* Obtains status of transmission circuitry, whether it is transmitting or idle.
*
* Return value:
* 0 : Transmitter is idle.
* 1 : Transmitter active.
*/
/******************************************************************************/
int gem_transmitting(struct gemac_dev *gemac)
{
return (__le32_to_cpu(*(volatile u32 *)(gemac->registers + GEM_TX_STATUS) & __cpu_to_le32(GEM_TX_GO)) == GEM_TX_GO);
}
/******************************************************************************/
/******************************************************************************/
/*
* Enable the receive circuitry. This should be performed only after the
* buffers and the descriptor queues have been set up, otherwise unpredictable
* results may occur.
*
* Return value:
* 0 : OK
* -1 : Receive queue not valid.
*/
/******************************************************************************/
int gem_enable_rx(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) |= __cpu_to_le32(GEM_RX_EN);
return 0;
}
/******************************************************************************/
/******************************************************************************/
/*
* Disable the receive circuitry. This will stop reception of any frame
* immediately, note that the descriptor pointer is not changed.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_disable_rx(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) &= __cpu_to_le32(~GEM_RX_EN);
}
/******************************************************************************/
/******************************************************************************/
/*
* Obtain the status of the receive circuitry, whether it is enabled.
*
* Return value:
* 0 : Receive circuitry disabled.
* -1 : Receive circuits enabled.
*/
/******************************************************************************/
int gem_receive_on(struct gemac_dev *gemac)
{
return (__le32_to_cpu(*(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) & __cpu_to_le32(GEM_RX_EN)) == GEM_RX_EN);
}
/******************************************************************************/
/******************************************************************************/
/*
* Set the loopback mode of the MAC. This can be either no loopback for normal
* operation, local loopback through MAC internal loopback module or PHY
* loopback for external loopback through a PHY. This asserts the external loop
* pin.
* The function parameters are a pointer to the device and an enumerated type
* specifying the type of loopback required.
*
* Note: if an invalid loopback mode is specified, loop back will be disabled.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_set_loop(struct gemac_dev *gemac, /* Pointer to the device structure. */
MAC_LOOP gem_loop /* Loopback mode. */
) {
switch (gem_loop) {
case LB_LOCAL:
*(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) &= __cpu_to_le32(~GEM_LB_PHY);
*(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) |= __cpu_to_le32(GEM_LB_MAC);
break;
case LB_EXT:
*(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) &= __cpu_to_le32(~GEM_LB_MAC);
*(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) |= __cpu_to_le32(GEM_LB_PHY);
break;
default:
*(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) &= __cpu_to_le32(~(GEM_LB_MAC | GEM_LB_PHY));
}
}
/******************************************************************************/
/******************************************************************************/
/*
* Get the loopback mode of the MAC. This can be either no loopback for normal
* operation, local loopback through MAC internal loopback module or PHY
* loopback for external loopback through a PHY. This asserts the external loop
* pin.
* The function parameters are a pointer to the device.
*
* Return value:
* LB_LOCAL : Local loop back active.
* LB_EXT : External loop back active.
* LB_NONE : Loop back disabled.
* -1 : Unknown mode.
*/
/******************************************************************************/
MAC_LOOP gem_get_loop(struct gemac_dev *gemac)
{
u32 lb_mode;
lb_mode = *(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) & (GEM_LB_PHY | GEM_LB_MAC);
switch (lb_mode) {
case GEM_LB_MAC:
return LB_LOCAL;
break;
case GEM_LB_PHY:
return LB_EXT;
break;
case 0:
return LB_NONE;
break;
default:
return -1;
}
}
/******************************************************************************/
/******************************************************************************/
/*
* Activate the Management interface. This is required to program the PHY
* registers through the MDIO port.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_enable_MDIO(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) |= __cpu_to_le32(GEM_MDIO_EN);
}
/******************************************************************************/
/******************************************************************************/
/*
* Disable the Management interface. In this state, the MDIO is placed in a
* high impedance state and the MDC clock is driven low.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_disable_MDIO(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) &= __cpu_to_le32(~GEM_MDIO_EN);
}
/******************************************************************************/
/******************************************************************************/
/*
* Enable writing to the statistic registers. This is for debug purposes only
* and should not be active during normal operation.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_stats_wr_en(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) |= __cpu_to_le32(GEM_STATS_WR_EN);
}
/******************************************************************************/
/******************************************************************************/
/*
* Disable writing to the statistic registers. Under normal operation this is
* not necessary as the writing to statistics registers should be off by default
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_stats_wr_off(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) &= __cpu_to_le32(~GEM_STATS_WR_EN);
}
/******************************************************************************/
/******************************************************************************/
/*
* Increment all the statistic registers by 1. This is for debug purposes only.
* Note that the statistic registers are automatically cleared on read!
*
* No return value.
*/
/******************************************************************************/
void gem_stats_inc(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) |= __cpu_to_le32(GEM_STATS_INC);
}
/******************************************************************************/
/******************************************************************************/
/*
* Clear all the statistic registers.
*
* No return value.
*/
/******************************************************************************/
void gem_stats_clr(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) |= __cpu_to_le32(GEM_STATS_CLR);
}
/******************************************************************************/
/******************************************************************************/
/*
* Enable pause frame reception. With this enabled, if a valid pause frame is
* received, transmission will halt for the specified time after the current
* frame has completed transmission.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_enable_pause_rx(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) |= __cpu_to_le32(GEM_RX_PAUSE_EN);
}
/******************************************************************************/
/******************************************************************************/
/*
* Disable pause frame reception. Incoming pause frames are ignored.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_disable_pause_rx(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32(~GEM_RX_PAUSE_EN);
}
/******************************************************************************/
/******************************************************************************/
/*
* Enable copy of received pause frame.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_enable_pause_cpy(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32(~GEM_RX_NO_PAUSE);
}
/******************************************************************************/
/******************************************************************************/
/*
* Disable copy of received pause frame.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_disable_pause_cpy(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) |= __cpu_to_le32(GEM_RX_NO_PAUSE);
}
/******************************************************************************/
/******************************************************************************/
/*
* Send a pause frame with zero quantum.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_send_0q_pause(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) |= __cpu_to_le32(GEM_TX_0Q_PAUSE);
}
/******************************************************************************/
/******************************************************************************/
/*
* Send a normal pause frame.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_send_pause(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) |= __cpu_to_le32(GEM_TX_PAUSE);
}
/******************************************************************************/
/******************************************************************************/
/*
* Set transmit pause quantum.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_set_tx_pause_q(struct gemac_dev *gemac, u32 gem_pause)
{
*(volatile u32 *)(gemac->registers + GEM_TX_PAUSE_QUANT) = __cpu_to_le32(gem_pause);
}
/******************************************************************************/
/******************************************************************************/
/*
* Read transmit pause quantum.
*
* Return values:
* 0-65535: transmit pause quantum.
*/
/******************************************************************************/
u32 gem_get_tx_pause_q(struct gemac_dev *gemac)
{
return (__le32_to_cpu(*(volatile u32 *)(gemac->registers + GEM_TX_PAUSE_QUANT)));
}
/******************************************************************************/
/******************************************************************************/
/*
* Set retry test bit, this is used for debug purposes only to speed up testing.
* This should not be enabled for normal operation.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_en_retry_test(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) |= __cpu_to_le32(GEM_RETRY_TEST);
}
/******************************************************************************/
/******************************************************************************/
/*
* Disable retry test bit. For normal operation this bit should not be set.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_dis_retry_test(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32(~GEM_RETRY_TEST);
}
/******************************************************************************/
/******************************************************************************/
/*
* Enable external address match via the eam pin, which when active will copy
* the current frame to memory.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_enable_eam(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) |= __cpu_to_le32(GEM_EAM_EN);
}
/******************************************************************************/
/******************************************************************************/
/*
* Disable external address match capability. The MAC will ignore the status of
* the eam pin.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_disable_eam(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32(~GEM_EAM_EN);
}
/******************************************************************************/
/******************************************************************************/
/*
* Enable storing of the receive frame check sequence into memory.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_enable_fcs_rx(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32(~GEM_RX_NO_FCS);
}
/******************************************************************************/
/******************************************************************************/
/*
* Disable storing of the receive frame check sequence into memory. The last 4
* bytes from the incoming frame will be checked for valid CRC, however this
* will not be stored into memory. The frame length will be updated
* accordingly.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_disable_fcs_rx(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) |= __cpu_to_le32(GEM_RX_NO_FCS);
}
/******************************************************************************/
/******************************************************************************/
/*
* Enable reception of long frames up to 1536 bytes in length.
* These are not standard IEEE 802.3 frames.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_enable_1536_rx(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) |= __cpu_to_le32(GEM_FRAME_1536);
}
/******************************************************************************/
/******************************************************************************/
/*
* Disable reception of frames greater than 1518 bytes in length.
* This is normal operation mode for the MAC for compatibility with IEEE 802.3
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_disable_1536_rx(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32(~GEM_FRAME_1536);
}
/******************************************************************************/
/******************************************************************************/
/*
* Enable reception of unicast hashed frames. The frame will be received when
* the 6 bit hash function of the frame's destination address points a bit that
* is set in the 64-bit hash register and is signalled as a unicast frame.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_enable_unicast(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) |= __cpu_to_le32(GEM_UNICAST_EN);
}
/******************************************************************************/
/******************************************************************************/
/*
* Disable reception of unicast hashed frames.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_disable_unicast(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32(~GEM_UNICAST_EN);
}
/******************************************************************************/
/******************************************************************************/
/*
* Enable reception of multicast hashed frames. The frame will be received when
* the 6 bit hash function of the frame's destination address points a bit that
* is set in the 64-bit hash register and is signalled as a multicast frame.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_enable_multicast(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) |= __cpu_to_le32(GEM_MULTICAST_EN);
}
/******************************************************************************/
/******************************************************************************/
/*
* Disable reception of multicast hashed frames.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_disable_multicast(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32(~GEM_MULTICAST_EN);
}
/******************************************************************************/
/******************************************************************************/
/*
* Allow reception of broadcast frames (frames with address set to all 1's)
* This is normal operating mode for the MAC.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_allow_broadcast(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32(~GEM_NO_BROADCAST);
}
/******************************************************************************/
/******************************************************************************/
/*
* Do not allow reception of broadcast frames, such frames will be ignored.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_no_broadcast(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) |= __cpu_to_le32(GEM_NO_BROADCAST);
}
/******************************************************************************/
/******************************************************************************/
/*
* Enable copy all frames. In this mode, the MAC will copy all valid received
* frames to memory regardless of the destination address.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_enable_copy_all(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) |= __cpu_to_le32(GEM_COPY_ALL);
}
/******************************************************************************/
/******************************************************************************/
/*
* Do not copy all frames. Normal operating mode for the MAC, frames will only
* be copied to memory if it matches one of the specific or hash addresses.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_disable_copy_all(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32(~GEM_COPY_ALL);
}
/******************************************************************************/
/******************************************************************************/
/*
* Set MAC into full duplex mode. The crs and col signals will be ignored in
* this mode.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_full_duplex(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->baseaddr + GEM_CFG) |= __cpu_to_le32(GEM_CONF_DUPLEX_GEM_FULL);
}
/******************************************************************************/
/******************************************************************************/
/*
* Set MAC into half duplex mode. The crs and col signals are used to detect
* collisions and perform deference where necessary.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_half_duplex(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->baseaddr + GEM_CFG) &= __cpu_to_le32(~GEM_CONF_DUPLEX_GEM_FULL);
}
/******************************************************************************/
/******************************************************************************/
/*
* Set the operating speed of the MAC, for 10 and 100Mb modes, this has no
* effect on the MAC functionality, but simply asserts an external speed pin
* accordingly.
* For 1G modes, this will set the MAC into the appropriate operating mode by
* switching to either the GMII or TBI interface depending on required mode.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_set_speed(struct gemac_dev *gemac, MAC_SPEED gem_speed)
{
switch (gem_speed) {
case SPEED_10M:
*(volatile u32 *)(gemac->baseaddr + GEM_CFG) = (*(volatile u32 *)(gemac->baseaddr + GEM_CFG) & __cpu_to_le32(~GEM_CONF_SPEED_MASK)) | __cpu_to_le32(GEM_CONF_SPEED_SEL_GEM | GEM_CONF_SPEED_GEM_10M);
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32(~GEM_PCS_SEL);
break;
case SPEED_100M:
*(volatile u32 *)(gemac->baseaddr + GEM_CFG) = (*(volatile u32 *)(gemac->baseaddr + GEM_CFG) & __cpu_to_le32(~GEM_CONF_SPEED_MASK)) | __cpu_to_le32(GEM_CONF_SPEED_SEL_GEM | GEM_CONF_SPEED_GEM_100M);
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32(~GEM_PCS_SEL);
break;
case SPEED_1000M:
*(volatile u32 *)(gemac->baseaddr + GEM_CFG) = (*(volatile u32 *)(gemac->baseaddr + GEM_CFG) & __cpu_to_le32(~GEM_CONF_SPEED_MASK)) | __cpu_to_le32(GEM_CONF_SPEED_SEL_GEM | GEM_CONF_SPEED_GEM_1G);
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32(~GEM_PCS_SEL);
break;
case SPEED_1000M_PCS:
*(volatile u32 *)(gemac->baseaddr + GEM_CFG) = (*(volatile u32 *)(gemac->baseaddr + GEM_CFG) & __cpu_to_le32(~GEM_CONF_SPEED_MASK)) | __cpu_to_le32(GEM_CONF_SPEED_SEL_GEM | GEM_CONF_SPEED_GEM_1G);
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) |= __cpu_to_le32(GEM_PCS_SEL);
break;
default:
*(volatile u32 *)(gemac->baseaddr + GEM_CFG) = (*(volatile u32 *)(gemac->baseaddr + GEM_CFG) & __cpu_to_le32(~GEM_CONF_SPEED_MASK)) | __cpu_to_le32(GEM_CONF_SPEED_SEL_GEM | GEM_CONF_SPEED_GEM_100M);
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32(~GEM_PCS_SEL);
}
}
/******************************************************************************/
/******************************************************************************/
/*
* Get the operating speed of the MAC, currently this has no functional effect
* on the MAC.
*
* This function returns an enumerated value cast into an int. This is for
* backward compatibility with the macb driver.
*
* Return value:
* SPEED_10M : MAC in 10Mb/s mode.
* SPEED_100M : MAC in 100Mb/s mode.
* SPEED_1000M : MAC in 1G mode with GMII interface.
* SPEED_1000M_PCS : MAC in 1G mode with PCS interface.
*/
/******************************************************************************/
MAC_SPEED gem_get_speed(struct gemac_dev *gemac)
{
if (*(volatile u32 *)(gemac->baseaddr + GEM_CFG) & __cpu_to_le32(GEM_CONF_SPEED_SEL_GEM)) {
if (*(volatile u32 *)(gemac->baseaddr + GEM_CFG) & __cpu_to_le32(GEM_CONF_SPEED_GEM_1G)) {
if (*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) & __cpu_to_le32(GEM_PCS_SEL))
return (SPEED_1000M_PCS);
else
return (SPEED_1000M);
} else {
if (*(volatile u32 *)(gemac->baseaddr + GEM_CFG) & __cpu_to_le32(GEM_CONF_SPEED_GEM_100M))
return (SPEED_100M);
else
return (SPEED_10M);
}
} else {
if (*(volatile u32 *)(gemac->baseaddr + GEM_CFG) & __cpu_to_le32(GEM_CONF_SPEED_PHY_1G)) {
if (*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) & __cpu_to_le32(GEM_PCS_SEL))
return (SPEED_1000M_PCS);
else
return (SPEED_1000M);
} else {
if (*(volatile u32 *)(gemac->baseaddr + GEM_CFG) & __cpu_to_le32(GEM_CONF_SPEED_PHY_100M))
return (SPEED_100M);
else
return (SPEED_10M);
}
}
}
/******************************************************************************/
#if defined(CONFIG_COMCERTO_100)
/******************************************************************************/
/*
* Set AMBA AHB bus width.
* AMBA_AHB_32:
* AMBA_AHB_64:
* AMBA_AHB_128:
* There is no return value for this function.
*/
/******************************************************************************/
void gem_set_ahb_width(struct gemac_dev *gemac, MAC_AHB_WIDTH gem_buswidth)
{
switch (gem_buswidth) {
case AMBA_AHB_128:
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) |= __cpu_to_le32(GEM_AHB_WIDTH1);
break;
case AMBA_AHB_64:
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32(~GEM_AHB_WIDTH1);
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) |= __cpu_to_le32(GEM_AHB_WIDTH0);
break;
case AMBA_AHB_32:
default:
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32((~GEM_AHB_WIDTH1) & (~GEM_AHB_WIDTH0));
}
}
/******************************************************************************/
/******************************************************************************/
/*
* Get AMBA AHB bus width.
* It returns one of the following values:
* AMBA_AHB_32, AMBA_AHB_64, AMBA_AHB_128,
*/
/******************************************************************************/
MAC_AHB_WIDTH gem_get_ahb_width(struct gemac_dev *gemac)
{
if (*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) & __cpu_to_le32(GEM_AHB_WIDTH1)) {
return AMBA_AHB_128;
} else {
if (*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) & __cpu_to_le32(GEM_AHB_WIDTH0)) {
return AMBA_AHB_64;
} else {
return AMBA_AHB_32;
}
}
}
/******************************************************************************/
#endif
/******************************************************************************/
/*
* Set MDC clock division.
* MDC_DIV_8:
* MDC_DIV_16:
* MDC_DIV_32:
* MDC_DIV_48:
* MDC_DIV_64:
* MDC_DIV_96:
* MDC_DIV_128:
* MDC_DIV_224:
* There is no return value for this function.
*/
/******************************************************************************/
void gem_set_mdc_div(struct gemac_dev *gemac, MAC_MDC_DIV gem_mdcdiv)
{
switch (gem_mdcdiv) {
case MDC_DIV_8:
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32((~GEM_MDC_DIV2) & (~GEM_MDC_DIV1) & (~GEM_MDC_DIV0));
break;
case MDC_DIV_16:
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32((~GEM_MDC_DIV2) & (~GEM_MDC_DIV1));
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) |= __cpu_to_le32(GEM_MDC_DIV0);
break;
case MDC_DIV_32:
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32((~GEM_MDC_DIV2) & (~GEM_MDC_DIV0));
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) |= __cpu_to_le32(GEM_MDC_DIV1);
break;
case MDC_DIV_48:
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) |= __cpu_to_le32(GEM_MDC_DIV1 | GEM_MDC_DIV0);
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32(~GEM_MDC_DIV2);
break;
case MDC_DIV_64:
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32((~GEM_MDC_DIV1) & (~GEM_MDC_DIV0));
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) |= __cpu_to_le32(GEM_MDC_DIV2);
break;
case MDC_DIV_96:
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) |= __cpu_to_le32(GEM_MDC_DIV2 | GEM_MDC_DIV0);
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32(~GEM_MDC_DIV1);
break;
case MDC_DIV_128:
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) |= __cpu_to_le32(GEM_MDC_DIV2 | GEM_MDC_DIV1);
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32(~GEM_MDC_DIV0);
break;
case MDC_DIV_224:
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) |= __cpu_to_le32(GEM_MDC_DIV2 | GEM_MDC_DIV1 | GEM_MDC_DIV0);
break;
}
}
/******************************************************************************/
/******************************************************************************/
/*
* Get MDC clock division.
* It returns one of this values:
* MDC_DIV_8, MDC_DIV_16, MDC_DIV_32, MDC_DIV_48, MDC_DIV_64, MDC_DIV_96,
* MDC_DIV_128, MDC_DIV_224.
*/
/******************************************************************************/
MAC_MDC_DIV gem_get_mdc_div(struct gemac_dev *gemac)
{
if (*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) & __cpu_to_le32(GEM_MDC_DIV2)) {
if (*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) & __cpu_to_le32(GEM_MDC_DIV1)) {
if (*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) & __cpu_to_le32(GEM_MDC_DIV0)) {
return MDC_DIV_224;
} else {
return MDC_DIV_128;
}
} else {
if (*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) & __cpu_to_le32(GEM_MDC_DIV0)) {
return MDC_DIV_96;
} else {
return MDC_DIV_64;
}
}
} else {
if (*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) & __cpu_to_le32(GEM_MDC_DIV1)) {
if (*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) & __cpu_to_le32(GEM_MDC_DIV0)) {
return MDC_DIV_48;
} else {
return MDC_DIV_32;
}
} else {
if (*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) & __cpu_to_le32(GEM_MDC_DIV0)) {
return MDC_DIV_16;
} else {
return MDC_DIV_8;
}
}
}
}
/******************************************************************************/
/******************************************************************************/
/*
* Enable to read snapshot values of statistic registers.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_enable_rd_snap(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) |= __cpu_to_le32(GEM_READ_SNAP);
}
/******************************************************************************/
/*
* Disable to read snapshot values of statistic registers.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_disable_rd_snap(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) &= __cpu_to_le32(~GEM_READ_SNAP);
}
/******************************************************************************/
/*
* Take snapshot of statistic registers. Writing a one will record the current
* value of all statistics registers in the snapshot registers and clear the
* statistics registers.
*
* There is no return value for this function.
*/
/******************************************************************************/
void gem_take_snap(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) |= __cpu_to_le32(GEM_TAKE_SNAP);
}
/******************************************************************************/
/*
* Get the current link status as returned by the PHY
*
* Return value:
* 0 : Link is down.
* 1 : Link active.
*/
/******************************************************************************/
int gem_link_status(struct gemac_dev *gemac)
{
return (__le32_to_cpu(*(volatile u32 *)(gemac->registers + GEM_NET_STATUS) & __cpu_to_le32(GEM_LINK_STATUS)) == GEM_LINK_STATUS);
}
/******************************************************************************/
/******************************************************************************/
/*
* Check if the PHY management logic is idle, i.e. completed management
* operation.
*
* Return value:
* 0 : PHY management not-idle.
* 1 : PHY management completed.
*/
/******************************************************************************/
int gem_phy_man_idle(struct gemac_dev *gemac)
{
return (__le32_to_cpu(*(volatile u32 *)(gemac->phyregisters + GEM_NET_STATUS) & __cpu_to_le32(GEM_PHY_IDLE)) == GEM_PHY_IDLE);
}
/******************************************************************************/
/******************************************************************************/
/*
* Get the value of the transmit status register.
* The return value is an unsigned 32-bit integer containing the contents of the
* register. This should be masked appropriately to obtain the relevant status.
*
* Return value:
* Returns current value of transmit status register.
*/
/******************************************************************************/
u32 gem_get_tx_stat(struct gemac_dev *gemac)
{
return (__le32_to_cpu(*(volatile u32 *)(gemac->registers + GEM_TX_STATUS)));
}
/******************************************************************************/
/******************************************************************************/
/*
* Reset the specified bits of the transmit status register.
*
* There is no return value.
*/
/******************************************************************************/
void gem_reset_tx_stat(struct gemac_dev *gemac, /* Pointer to device structure. */
u32 rst_status /* Status to reset. */
) {
*(volatile u32 *)(gemac->registers + GEM_TX_STATUS) |= __cpu_to_le32(rst_status);
}
/******************************************************************************/
/******************************************************************************/
/*
* Get the value of the receive status register.
* The return value is an unsigned 32-bit integer containing the contents of the
* register. This should be masked appropriately to obtain the relevant status.
*
* Returns current receive status.
*/
/******************************************************************************/
u32 gem_get_rx_stat(struct gemac_dev *gemac)
{
return (__le32_to_cpu(*(volatile u32 *)(gemac->registers + GEM_RX_STATUS)));
}
/******************************************************************************/
/******************************************************************************/
/*
* Reset the specified bits of the receive status register.
*
* There is no return value.
*/
/******************************************************************************/
void gem_reset_rx_stat(struct gemac_dev *gemac, /* Pointer to device structure. */
u32 rst_status /* Status to reset. */
) {
*(volatile u32 *)(gemac->registers + GEM_RX_STATUS) |= __cpu_to_le32(rst_status);
}
/******************************************************************************/
/******************************************************************************/
/*
* Enable jumbo frames to be accepted.
*
* There is no return value.
*/
/******************************************************************************/
void gem_enable_rx_jmb(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) |= __cpu_to_le32(GEM_RX_JUMBO);
}
/******************************************************************************/
/******************************************************************************/
/*
* Disable jumbo frames to be accepted.
*
* There is no return value.
*/
/******************************************************************************/
void gem_disable_rx_jmb(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32(~GEM_RX_JUMBO);
}
/******************************************************************************/
/******************************************************************************/
/*
* Enable only VLAN frames to be accepted, all other frames will be discarded.
*
* There is no return value.
*/
/******************************************************************************/
void gem_enable_vlan_only(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) |= __cpu_to_le32(GEM_VLAN_ONLY);
}
/******************************************************************************/
/******************************************************************************/
/*
* Disable VLAN frame only mode. All frames will be accepted.
*
* There is no return value.
*/
/******************************************************************************/
void gem_disable_vlan_only(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32(~GEM_VLAN_ONLY);
}
/******************************************************************************/
/******************************************************************************/
/*
* Read the interrupt status register.
* This returns an unsigned 32-bit integer with the current interrupt status,
* this should be masked appropriately to get the required status.
* Note that the interrupt status register is automatically reset on read, so
* the returned value should be stored if further processing required.
*
* Returns the current interrupt status.
*/
/******************************************************************************/
u32 gem_get_irq_stat(struct gemac_dev *gemac)
{
return (__le32_to_cpu(*(volatile u32 *)(gemac->registers + GEM_IRQ_STATUS)));
}
/******************************************************************************/
/******************************************************************************/
/*
* Set specified bits in the interrupt status register.
* This can be used for debug purposes to manually activate an interrupt.
*
* There is no return value.
*/
/******************************************************************************/
void gem_set_irq_stat(struct gemac_dev *gemac, u32 irq_status)
{
*(volatile u32 *)(gemac->registers + GEM_IRQ_STATUS) |= __cpu_to_le32(irq_status);
}
/******************************************************************************/
/******************************************************************************/
/*
* Enable specified interrupts.
* The specified interrupt bits are enabled by unmasking them.
* Note that this appends to the existing interrupt enable list.
*
* There is no return value.
*/
/******************************************************************************/
void gem_enable_irq(struct gemac_dev *gemac, u32 irq_en)
{
*(volatile u32 *)(gemac->registers + GEM_IRQ_ENABLE) |= __cpu_to_le32(irq_en);
}
/******************************************************************************/
/******************************************************************************/
/*
* Disable specified interrupts.
* The specified interrupts are masked out so that they do not generate an
* interrupt.
* Note that this appends to the existing interrupt mask list.
*
* There is no return value.
*/
/******************************************************************************/
void gem_mask_irq(struct gemac_dev *gemac, u32 irq_mask)
{
*(volatile u32 *)(gemac->registers + GEM_IRQ_DISABLE) |= __cpu_to_le32(irq_mask);
}
/******************************************************************************/
/******************************************************************************/
/*
* Obtain the current interrupt mask value.
* The return value indicates which interrupts are currently masked out i.e. do
* not generate an interrupt.
*
* Returns the interrupt mask status.
*/
/******************************************************************************/
u32 gem_get_irq_mask(struct gemac_dev *gemac)
{
return (__le32_to_cpu(*(volatile u32 *)(gemac->registers + GEM_IRQ_MASK)));
}
/******************************************************************************/
/******************************************************************************/
/*
* Write to the PHY management registers.
* This function simply sets off the PHY management operation, completion will
* be indicated by an interrupt.
* The input parameters are the PHY address, register address, and the 16-bit
* data to be written.
* Note that the MDIO enable register must be on.
*
* Return value:
* 0 : OK
* -1 : Invalid input range.
*/
/******************************************************************************/
int gem_phy_man_wr(struct gemac_dev *gemac, u8 phy_addr, u8 reg_addr, u32 data) {
u32 write_data;
if ((phy_addr > 0x1F) || (reg_addr > 0x1F) || (data > 0xFFFF)) {
return -1;
} else {
write_data = 0x50020000;
write_data |= ((phy_addr << 23) | (reg_addr << 18) | data);
*(volatile u32 *)(gemac->phyregisters + GEM_PHY_MAN) = __cpu_to_le32(write_data);
return 0;
}
}
/******************************************************************************/
/******************************************************************************/
/*
* Perform PHY management register read operation.
* This function simply sets off the PHY management operation, completion will
* be indicated by an interrupt.
* The input parameters are the PHY address and the register address to be read
*
* Return value:
* 0 : OK
* -1 : Invalid input range.
*/
/******************************************************************************/
int gem_phy_man_rd(struct gemac_dev *gemac, u8 phy_addr, u8 reg_addr) {
u32 write_data;
if ((phy_addr > 0x1F) || (reg_addr > 0x1F)) {
return -1;
} else {
write_data = 0x60020000;
write_data |= ((phy_addr << 23) | (reg_addr << 18));
*(volatile u32 *)(gemac->phyregisters + GEM_PHY_MAN) = __cpu_to_le32(write_data);
return 0;
}
}
/******************************************************************************/
/******************************************************************************/
/*
* Read the data section of the PHY management register. After a read operation
* the data from the PHY will be stored here.
*
* Return value is the lower 16-bits of the PHY management register.
*/
/******************************************************************************/
u32 gem_phy_man_data(struct gemac_dev *gemac)
{
return (__le32_to_cpu(*(volatile u32 *)(gemac->phyregisters + GEM_PHY_MAN) & __cpu_to_le32(0xFFFF)));
}
/******************************************************************************/
/******************************************************************************/
/*
* Read the pause time register.
*
* Returns the current value in the pause time register which will
* decrement when the MAC has gone into pause mode.
*/
/******************************************************************************/
u32 gem_pause_time(struct gemac_dev *gemac)
{
return (__le32_to_cpu(*(volatile u32 *)(gemac->registers + GEM_RX_PAUSE_TIME)));
}
/******************************************************************************/
/******************************************************************************/
/*
* Set the id-check registers of the MAC.
* These registers are used to check the type-id field of the incoming frames,
* if matched, the appropriate status bit will be set in word 1 of the receive
* descriptor for that frame.
* The input parameter is truncated to 16-bits.
*
* There is no return value.
*/
/******************************************************************************/
void gem_set_id_check1(struct gemac_dev *gemac, u32 id_check) {
*(volatile u32 *)(gemac->registers + GEM_ID_CHECK1) = __cpu_to_le32(id_check & 0xFFFF);
}
void gem_set_id_check2(struct gemac_dev *gemac, u32 id_check) {
*(volatile u32 *)(gemac->registers + GEM_ID_CHECK2) = __cpu_to_le32(id_check & 0xFFFF);
}
void gem_set_id_check3(struct gemac_dev *gemac, u32 id_check) {
*(volatile u32 *)(gemac->registers + GEM_ID_CHECK3) = __cpu_to_le32(id_check & 0xFFFF);
}
void gem_set_id_check4(struct gemac_dev *gemac, u32 id_check) {
*(volatile u32 *)(gemac->registers + GEM_ID_CHECK4) = __cpu_to_le32(id_check & 0xFFFF);
}
/******************************************************************************/
/******************************************************************************/
/*
* Get the value of the id-check registers in the MAC.
*
* Return value:
* Value of ID check register.
*/
/******************************************************************************/
u32 gem_get_id_check1(struct gemac_dev *gemac)
{
return (__le32_to_cpu(*(volatile u32 *)(gemac->registers + GEM_ID_CHECK1)));
}
u32 gem_get_id_check2(struct gemac_dev *gemac)
{
return (__le32_to_cpu(*(volatile u32 *)(gemac->registers + GEM_ID_CHECK2)));
}
u32 gem_get_id_check3(struct gemac_dev *gemac)
{
return (__le32_to_cpu(*(volatile u32 *)(gemac->registers + GEM_ID_CHECK3)));
}
u32 gem_get_id_check4(struct gemac_dev *gemac)
{
return (__le32_to_cpu(*(volatile u32 *)(gemac->registers + GEM_ID_CHECK4)));
}
/******************************************************************************/
/******************************************************************************/
/*
* Set the hash register of the MAC.
* This register is used for matching unicast and multicast frames.
* The parameter of this function should be a pointer to type MAC_ADDR as
* defined in the header file.
*
* There is no return value.
*/
/******************************************************************************/
void gem_set_hash(struct gemac_dev *gemac, MAC_ADDR *hash_addr) {
*(volatile u32 *)(gemac->registers + GEM_HASH_BOT) = hash_addr->bottom;
*(volatile u32 *)(gemac->registers + GEM_HASH_TOP) = hash_addr->top;
}
/******************************************************************************/
/******************************************************************************/
/*
* Get the current value of the hash registers of the MAC.
*
* This function returns a value of type MAC_ADDR
*/
/******************************************************************************/
MAC_ADDR gem_get_hash(struct gemac_dev *gemac)
{
MAC_ADDR addr;
addr.bottom = *(volatile u32 *)(gemac->registers + GEM_HASH_BOT);
addr.top = *(volatile u32 *)(gemac->registers + GEM_HASH_TOP);
return addr;
}
/******************************************************************************/
/******************************************************************************/
/*
* Setup all the specific address registers for the MAC.
* These registers are matched against incoming frames to determine whether the
* frame should be copied to memory.
* The input parameter to this function should be a pointer to type SPEC_ADDR
* as defined in the header file.
*
* There is no return value.
*/
/******************************************************************************/
void gem_set_address(struct gemac_dev *gemac, SPEC_ADDR *spec_addr)
{
*(volatile u32 *)(gemac->registers + GEM_LADDR1_BOT) = spec_addr->one.bottom;
*(volatile u32 *)(gemac->registers + GEM_LADDR1_TOP) = spec_addr->one.top;
*(volatile u32 *)(gemac->registers + GEM_LADDR2_BOT) = spec_addr->two.bottom;
*(volatile u32 *)(gemac->registers + GEM_LADDR2_TOP) = spec_addr->two.top;
*(volatile u32 *)(gemac->registers + GEM_LADDR3_BOT) = spec_addr->three.bottom;
*(volatile u32 *)(gemac->registers + GEM_LADDR3_TOP) = spec_addr->three.top;
*(volatile u32 *)(gemac->registers + GEM_LADDR4_BOT) = spec_addr->four.bottom;
*(volatile u32 *)(gemac->registers + GEM_LADDR4_TOP) = spec_addr->four.top;
}
/******************************************************************************/
/******************************************************************************/
/*
* Get the current set of specific match addresses for the MAC.
* Note that a pointer is not returned as this would give direct access to the
* MAC address space which may cause unpredictable behaviour if wrongly used.
*
* Return type is of type SPEC_ADDR as defined in the header file.
*/
/******************************************************************************/
SPEC_ADDR gem_get_address(struct gemac_dev *gemac)
{
SPEC_ADDR spec_addr;
spec_addr.one.bottom = *(volatile u32 *)(gemac->registers + GEM_LADDR1_BOT);
spec_addr.one.top = *(volatile u32 *)(gemac->registers + GEM_LADDR1_TOP);
spec_addr.two.bottom = *(volatile u32 *)(gemac->registers + GEM_LADDR2_BOT);
spec_addr.two.top = *(volatile u32 *)(gemac->registers + GEM_LADDR2_TOP);
spec_addr.three.bottom = *(volatile u32 *)(gemac->registers + GEM_LADDR3_BOT);
spec_addr.three.top = *(volatile u32 *)(gemac->registers + GEM_LADDR3_TOP);
spec_addr.four.bottom = *(volatile u32 *)(gemac->registers + GEM_LADDR4_BOT);
spec_addr.four.top = *(volatile u32 *)(gemac->registers + GEM_LADDR4_TOP);
return spec_addr;
}
/******************************************************************************/
/******************************************************************************/
/*
* Set specific local addresses of the MAC.
* Rather than setting up all four specific addresses, this function sets them
* up individually. The input parameter should be a pointer to type MAC_ADDR.
*
* There are no return values.
*/
/******************************************************************************/
void gem_set_laddr1(struct gemac_dev *gemac, MAC_ADDR *address)
{
*(volatile u32 *)(gemac->registers + GEM_LADDR1_BOT) = address->bottom;
*(volatile u32 *)(gemac->registers + GEM_LADDR1_TOP) = address->top;
}
void gem_set_laddr2(struct gemac_dev *gemac, MAC_ADDR *address)
{
*(volatile u32 *)(gemac->registers + GEM_LADDR2_BOT) = address->bottom;
*(volatile u32 *)(gemac->registers + GEM_LADDR2_TOP) = address->top;
}
void gem_set_laddr3(struct gemac_dev *gemac, MAC_ADDR *address)
{
*(volatile u32 *)(gemac->registers + GEM_LADDR3_BOT) = address->bottom;
*(volatile u32 *)(gemac->registers + GEM_LADDR3_TOP) = address->top;
}
void gem_set_laddr4(struct gemac_dev *gemac, MAC_ADDR *address)
{
*(volatile u32 *)(gemac->registers + GEM_LADDR4_BOT) = address->bottom;
*(volatile u32 *)(gemac->registers + GEM_LADDR4_TOP) = address->top;
}
/******************************************************************************/
/******************************************************************************/
/*
* Get specific local addresses of the MAC.
* This allows returning of a single specific address stored in the MAC.
*
* Return value if of type MAC_ADDR as defined in the header file.
*/
/******************************************************************************/
MAC_ADDR gem_get_laddr1(struct gemac_dev *gemac)
{
MAC_ADDR addr;
addr.bottom = *(volatile u32 *)(gemac->registers + GEM_LADDR1_BOT);
addr.top = *(volatile u32 *)(gemac->registers + GEM_LADDR1_TOP);
return addr;
}
MAC_ADDR gem_get_laddr2(struct gemac_dev *gemac)
{
MAC_ADDR addr;
addr.bottom = *(volatile u32 *)(gemac->registers + GEM_LADDR2_BOT);
addr.top = *(volatile u32 *)(gemac->registers + GEM_LADDR2_TOP);
return addr;
}
MAC_ADDR gem_get_laddr3(struct gemac_dev *gemac)
{
MAC_ADDR addr;
addr.bottom = *(volatile u32 *)(gemac->registers + GEM_LADDR3_BOT);
addr.top = *(volatile u32 *)(gemac->registers + GEM_LADDR3_TOP);
return addr;
}
MAC_ADDR gem_get_laddr4(struct gemac_dev *gemac)
{
MAC_ADDR addr;
addr.bottom = *(volatile u32 *)(gemac->registers + GEM_LADDR4_BOT);
addr.top = *(volatile u32 *)(gemac->registers + GEM_LADDR4_TOP);
return addr;
}
/******************************************************************************/
/******************************************************************************/
/*
* Obtain the statistics registers structure.
* type GEM_STATS as defined in the header file.
* Note that this operation is relatively slow as it is copying all the
* statistics register values rather than providing a pointer reference to them.
* Note also that the statistics registers will all be automatically cleared
* after this operation.
*
* Returns the entire statistics register block for the MAC in a structure of
* type GEM_STATS
*/
/******************************************************************************/
GEM_STATS gem_get_stats(struct gemac_dev *gemac)
{
return (*(GEM_STATS *)(gemac->registers + GEM_OCT_TX_BOT));
}
/******************************************************************************/
/******************************************************************************/
/*
* Set the values of the statistics registers.
* This is for debug only and allows reading and writing to the statistic
* registers to verify functionality.
*
* There is no return value.
*/
/******************************************************************************/
void gem_set_stats(struct gemac_dev *gemac, GEM_STATS *stats)
{
// gemac->registers->stats = *stats;
}
/******************************************************************************/
/******************************************************************************/
/*
* Write to a specific MAC memory address. The defines in the header file
* should be used for this.
* Note: care should be taken when using this function so as not to pass null
* pointers or write to read only registers etc.
*
* Return value:
* 0 : OK
* -1 : Invalid input range.
*/
/******************************************************************************/
int gem_register_wr(struct gemac_dev *gemac, u32 reg_addr, u32 data)
{
if (reg_addr > GEM_REG_TOP) {
return -1;
} else {
*(volatile u32 *)(gemac->registers + reg_addr) = __cpu_to_le32(data);
return 0;
}
}
/******************************************************************************/
/******************************************************************************/
/*
* Read from a specific MAC memory address. The defines in the header file
* should be used for this.
* Note that the range of the address requested is not checked.
*
* Returns register contents.
*/
/******************************************************************************/
u32 gem_register_rd(struct gemac_dev *gemac, u32 reg_addr)
{
return (__le32_to_cpu(*(volatile u32 *)(gemac->registers + reg_addr)));
}
/******************************************************************************/
/*
* Reset the MAC device to its default value and load up the MAC address stored
* in the header file into specific address 1. The MAC will be held in
* quiescent state.
* This function should be called to initialise and check the device prior to
* setting up the buffer queues and enabling the MAC. If it is called mid way
* through operation, the MAC is reset to default value and any pending frames
* will be lost.
* Note that the values in the struct gemac_dev software structure are not reset, only
* the MAC registers are reset. This is to allow, if necessary to recover the
* buffers and reload them into the MAC, however prior to doing this, they
* should be cleared first.
*
* Return value:
* 0 : OK
* -1 : Error in write/read check on initialisation.
*/
/******************************************************************************/
int gem_reset(struct gemac_dev *gemac)
{
MAC_ADDR zero_address = { 0x00000000, 0x00000000 };
MAC_ADDR enet_address = zero_address;
int stats_length;
int loop_i;
stats_length = sizeof(GEM_STATS) / 4;
/* Write to registers and set default values. */
*(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) = __cpu_to_le32(GEM_STATS_CLR | GEM_MDIO_ENABLED);
#if defined(CONFIG_COMCERTO_100)
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) = __cpu_to_le32(GEM_DEF_DUPLEX);
#else
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) = __cpu_to_le32(0);
#endif
gem_set_loop(gemac, GEM_DEF_LOOP);
gem_set_mdc_div(gemac, GEM_DEF_PCLK_DIV);
gem_set_speed(gemac, GEM_DEF_SPEED);
#if defined(CONFIG_COMCERTO_100)
gem_set_ahb_width(gemac, GEM_DEF_AHB_WIDTH);
#endif
*(volatile u32 *)(gemac->registers + GEM_TX_STATUS) = __cpu_to_le32(0xFFFFFFFF);
*(volatile u32 *)(gemac->registers + GEM_RX_QPTR) = __cpu_to_le32(0x00000000);
#if defined(CONFIG_COMCERTO_100)
*(volatile u32 *)(gemac->registers + GEM_TX_QPTR) = __cpu_to_le32(0x00000000);
#endif
*(volatile u32 *)(gemac->registers + GEM_RX_STATUS) = __cpu_to_le32(0xFFFFFFFF);
*(volatile u32 *)(gemac->registers + GEM_IRQ_DISABLE) = __cpu_to_le32(0xFFFFFFFF);
*(volatile u32 *)(gemac->registers + GEM_IRQ_STATUS) = __cpu_to_le32(0x00000000);
gem_set_hash(gemac, &zero_address);
gem_set_laddr1(gemac, &enet_address);
gem_set_laddr2(gemac, &zero_address);
gem_set_laddr3(gemac, &zero_address);
gem_set_laddr4(gemac, &zero_address);
*(volatile u32 *)(gemac->registers + GEM_ID_CHECK1) = __cpu_to_le32(0x00000000);
*(volatile u32 *)(gemac->registers + GEM_ID_CHECK2) = __cpu_to_le32(0x00000000);
*(volatile u32 *)(gemac->registers + GEM_ID_CHECK3) = __cpu_to_le32(0x00000000);
*(volatile u32 *)(gemac->registers + GEM_ID_CHECK4) = __cpu_to_le32(0x00000000);
/* Now read back values and return if not correct. */
if ((*(volatile u32 *)(gemac->registers + GEM_ID_CHECK1) != __cpu_to_le32(0x00000000)) ||
(*(volatile u32 *)(gemac->registers + GEM_ID_CHECK2) != __cpu_to_le32(0x00000000)) ||
(*(volatile u32 *)(gemac->registers + GEM_ID_CHECK3) != __cpu_to_le32(0x00000000)) ||
(*(volatile u32 *)(gemac->registers + GEM_ID_CHECK4) != __cpu_to_le32(0x00000000)) ||
(*(volatile u32 *)(gemac->registers + GEM_LADDR4_BOT) != zero_address.bottom) ||
(*(volatile u32 *)(gemac->registers + GEM_LADDR4_TOP) != zero_address.top) ||
(*(volatile u32 *)(gemac->registers + GEM_LADDR3_BOT) != zero_address.bottom) ||
(*(volatile u32 *)(gemac->registers + GEM_LADDR3_TOP) != zero_address.top) ||
(*(volatile u32 *)(gemac->registers + GEM_LADDR2_BOT) != zero_address.bottom) ||
(*(volatile u32 *)(gemac->registers + GEM_LADDR2_TOP) != zero_address.top) ||
(*(volatile u32 *)(gemac->registers + GEM_LADDR1_BOT) != enet_address.bottom) ||
(*(volatile u32 *)(gemac->registers + GEM_LADDR1_TOP) != enet_address.top) ||
(*(volatile u32 *)(gemac->registers + GEM_HASH_BOT) != zero_address.bottom) ||
(*(volatile u32 *)(gemac->registers + GEM_HASH_TOP) != zero_address.top) ||
(*(volatile u32 *)(gemac->registers + GEM_IRQ_STATUS) != __cpu_to_le32(0x00000000)) ||
(*(volatile u32 *)(gemac->registers + GEM_IRQ_MASK) != __cpu_to_le32(0x0003FFFF)) ||
(*(volatile u32 *)(gemac->registers + GEM_RX_STATUS) != __cpu_to_le32(0x00000000)) ||
#if defined(CONFIG_COMCERTO_100)
(*(volatile u32 *)(gemac->registers + GEM_TX_QPTR) != __cpu_to_le32(0x00000000)) ||
#endif
(*(volatile u32 *)(gemac->registers + GEM_RX_QPTR) != __cpu_to_le32(0x00000000)) ||
(*(volatile u32 *)(gemac->registers + GEM_TX_STATUS) != __cpu_to_le32(0x00000000))
) {
return -1;
} else if ((__le32_to_cpu((*(volatile u32 *)(gemac->registers + GEM_NET_CONTROL) & __cpu_to_le32(GEM_MDIO_EN))) != (0x00000000 | GEM_MDIO_ENABLED)) ||
(gem_get_loop(gemac) != GEM_DEF_LOOP) ||
// (gem_get_speed(gemac) != GEM_DEF_SPEED) ||
(gem_get_mdc_div(gemac) != GEM_DEF_PCLK_DIV)
) {
return -1;
} else {
for (loop_i = 0; loop_i < stats_length; loop_i++) {
if (__le32_to_cpu(*(volatile u32 *)(gemac->registers + GEM_OCT_TX_BOT + 4 * loop_i)) != 0x00000000) {
return -1;
}
}
return 0;
}
}
/******************************************************************************/
/******************************************************************************/
/*
* Enable length field checking feature.
* The length field check feature automatically discards frames that has a frame
* length smaller than that reported in the length field of the header.
*
* Note that in accordance with the IEEE spec, frames that are longer than that
* reported in length field is still accepted as a valid frame.
*
* This function has no return value.
*/
/******************************************************************************/
void gem_enable_len_check(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) |= __cpu_to_le32(GEM_RX_LEN_CHK);
}
/******************************************************************************/
/******************************************************************************/
/*
* Disable length field checking feature.
*
* This function has no return value.
*/
/******************************************************************************/
void gem_disable_len_check(struct gemac_dev *gemac)
{
*(volatile u32 *)(gemac->registers + GEM_NET_CONFIG) &= __cpu_to_le32(~GEM_RX_LEN_CHK);
}
/******************************************************************************/
/******************************************************************************/
/*
* Convert standard byte style ethernet address to format compatible with MAC.
*
* Input : Pointer to beginning of 6 byte address.
* Pointer to MAC_ADDR structure.
* Return values:
* 0 : OK
* -1 : Invalid inputs.
*/
/******************************************************************************/
int gem_enet_addr_byte_mac(u8 *enet_byte_addr, MAC_ADDR *enet_addr)
{
if ((enet_byte_addr == NULL) || (enet_addr == NULL)) {
return -1;
}
else
{
#if defined(BE8_MODE)
enet_addr->bottom = ((enet_byte_addr[0] << 24) |
(enet_byte_addr[1] << 16) |
(enet_byte_addr[2] << 8) |
enet_byte_addr[3]);
enet_addr->top = ((enet_byte_addr[4] << 24) |
(enet_byte_addr[5] << 16));
#else
enet_addr->bottom = enet_byte_addr[0] |
(enet_byte_addr[1] << 8) |
(enet_byte_addr[2] << 16) |
(enet_byte_addr[3] << 24);
enet_addr->top = enet_byte_addr[4] |
(enet_byte_addr[5] << 8);
#endif
return 0;
}
}
/******************************************************************************/
/******************************************************************************/
/*
* Convert MAC type ethernet address to standard byte style ethernet address.
*
* Input : Pointer to beginning of free space for 6 byte address.
* Pointer to MAC_ADDR structure.
* Return values:
* 0 : OK
* -1 : Invalid inputs.
*/
/******************************************************************************/
int gem_enet_addr_mac_byte(u8 *enet_byte_addr, MAC_ADDR *enet_addr)
{
if ((enet_byte_addr == NULL) || (enet_addr == NULL)) {
return -1;
}
else
{
#if defined(BE8_MODE)
enet_byte_addr[0] = (enet_addr->bottom >> 24) & 0xFF;
enet_byte_addr[1] = (enet_addr->bottom >> 16) & 0xFF;
enet_byte_addr[2] = (enet_addr->bottom >> 8) & 0xFF;
enet_byte_addr[3] = (enet_addr->bottom) & 0xFF;
enet_byte_addr[4] = (enet_addr->top >> 24) & 0xFF;
enet_byte_addr[5] = (enet_addr->top >> 16) & 0xFF;
#else
enet_byte_addr[0] = enet_addr->bottom & 0xFF;
enet_byte_addr[1] = (enet_addr->bottom >> 8) & 0xFF;
enet_byte_addr[2] = (enet_addr->bottom >> 16) & 0xFF;
enet_byte_addr[3] = (enet_addr->bottom >> 24) & 0xFF;
enet_byte_addr[4] = enet_addr->top & 0xFF;
enet_byte_addr[5] = (enet_addr->top >> 8) & 0xFF;
#endif
return 0;
}
}
/******************************************************************************/
#endif