mirror of https://github.com/F-Stack/f-stack.git
846 lines
22 KiB
C
846 lines
22 KiB
C
/*
|
|
* Copyright 2008-2012 Freescale Semiconductor Inc.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* * Neither the name of Freescale Semiconductor nor the
|
|
* names of its contributors may be used to endorse or promote products
|
|
* derived from this software without specific prior written permission.
|
|
*
|
|
*
|
|
* ALTERNATIVELY, this software may be distributed under the terms of the
|
|
* GNU General Public License ("GPL") as published by the Free Software
|
|
* Foundation, either version 2 of that License or (at your option) any
|
|
* later version.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
|
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
|
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
|
|
#include "fsl_fman_dtsec.h"
|
|
|
|
|
|
void fman_dtsec_stop_rx(struct dtsec_regs *regs)
|
|
{
|
|
/* Assert the graceful stop bit */
|
|
iowrite32be(ioread32be(®s->rctrl) | RCTRL_GRS, ®s->rctrl);
|
|
}
|
|
|
|
void fman_dtsec_stop_tx(struct dtsec_regs *regs)
|
|
{
|
|
/* Assert the graceful stop bit */
|
|
iowrite32be(ioread32be(®s->tctrl) | DTSEC_TCTRL_GTS, ®s->tctrl);
|
|
}
|
|
|
|
void fman_dtsec_start_tx(struct dtsec_regs *regs)
|
|
{
|
|
/* clear the graceful stop bit */
|
|
iowrite32be(ioread32be(®s->tctrl) & ~DTSEC_TCTRL_GTS, ®s->tctrl);
|
|
}
|
|
|
|
void fman_dtsec_start_rx(struct dtsec_regs *regs)
|
|
{
|
|
/* clear the graceful stop bit */
|
|
iowrite32be(ioread32be(®s->rctrl) & ~RCTRL_GRS, ®s->rctrl);
|
|
}
|
|
|
|
void fman_dtsec_defconfig(struct dtsec_cfg *cfg)
|
|
{
|
|
cfg->halfdup_on = DEFAULT_HALFDUP_ON;
|
|
cfg->halfdup_retransmit = DEFAULT_HALFDUP_RETRANSMIT;
|
|
cfg->halfdup_coll_window = DEFAULT_HALFDUP_COLL_WINDOW;
|
|
cfg->halfdup_excess_defer = DEFAULT_HALFDUP_EXCESS_DEFER;
|
|
cfg->halfdup_no_backoff = DEFAULT_HALFDUP_NO_BACKOFF;
|
|
cfg->halfdup_bp_no_backoff = DEFAULT_HALFDUP_BP_NO_BACKOFF;
|
|
cfg->halfdup_alt_backoff_val = DEFAULT_HALFDUP_ALT_BACKOFF_VAL;
|
|
cfg->halfdup_alt_backoff_en = DEFAULT_HALFDUP_ALT_BACKOFF_EN;
|
|
cfg->rx_drop_bcast = DEFAULT_RX_DROP_BCAST;
|
|
cfg->rx_short_frm = DEFAULT_RX_SHORT_FRM;
|
|
cfg->rx_len_check = DEFAULT_RX_LEN_CHECK;
|
|
cfg->tx_pad_crc = DEFAULT_TX_PAD_CRC;
|
|
cfg->tx_crc = DEFAULT_TX_CRC;
|
|
cfg->rx_ctrl_acc = DEFAULT_RX_CTRL_ACC;
|
|
cfg->tx_pause_time = DEFAULT_TX_PAUSE_TIME;
|
|
cfg->tbipa = DEFAULT_TBIPA; /* PHY address 0 is reserved (DPAA RM)*/
|
|
cfg->rx_prepend = DEFAULT_RX_PREPEND;
|
|
cfg->ptp_tsu_en = DEFAULT_PTP_TSU_EN;
|
|
cfg->ptp_exception_en = DEFAULT_PTP_EXCEPTION_EN;
|
|
cfg->preamble_len = DEFAULT_PREAMBLE_LEN;
|
|
cfg->rx_preamble = DEFAULT_RX_PREAMBLE;
|
|
cfg->tx_preamble = DEFAULT_TX_PREAMBLE;
|
|
cfg->loopback = DEFAULT_LOOPBACK;
|
|
cfg->rx_time_stamp_en = DEFAULT_RX_TIME_STAMP_EN;
|
|
cfg->tx_time_stamp_en = DEFAULT_TX_TIME_STAMP_EN;
|
|
cfg->rx_flow = DEFAULT_RX_FLOW;
|
|
cfg->tx_flow = DEFAULT_TX_FLOW;
|
|
cfg->rx_group_hash_exd = DEFAULT_RX_GROUP_HASH_EXD;
|
|
cfg->tx_pause_time_extd = DEFAULT_TX_PAUSE_TIME_EXTD;
|
|
cfg->rx_promisc = DEFAULT_RX_PROMISC;
|
|
cfg->non_back_to_back_ipg1 = DEFAULT_NON_BACK_TO_BACK_IPG1;
|
|
cfg->non_back_to_back_ipg2 = DEFAULT_NON_BACK_TO_BACK_IPG2;
|
|
cfg->min_ifg_enforcement = DEFAULT_MIN_IFG_ENFORCEMENT;
|
|
cfg->back_to_back_ipg = DEFAULT_BACK_TO_BACK_IPG;
|
|
cfg->maximum_frame = DEFAULT_MAXIMUM_FRAME;
|
|
cfg->tbi_phy_addr = DEFAULT_TBI_PHY_ADDR;
|
|
cfg->wake_on_lan = DEFAULT_WAKE_ON_LAN;
|
|
}
|
|
|
|
int fman_dtsec_init(struct dtsec_regs *regs, struct dtsec_cfg *cfg,
|
|
enum enet_interface iface_mode,
|
|
enum enet_speed iface_speed,
|
|
uint8_t *macaddr,
|
|
uint8_t fm_rev_maj,
|
|
uint8_t fm_rev_min,
|
|
uint32_t exception_mask)
|
|
{
|
|
bool is_rgmii = FALSE;
|
|
bool is_sgmii = FALSE;
|
|
bool is_qsgmii = FALSE;
|
|
int i;
|
|
uint32_t tmp;
|
|
|
|
UNUSED(fm_rev_maj);UNUSED(fm_rev_min);
|
|
|
|
/* let's start with a soft reset */
|
|
iowrite32be(MACCFG1_SOFT_RESET, ®s->maccfg1);
|
|
iowrite32be(0, ®s->maccfg1);
|
|
|
|
/*************dtsec_id2******************/
|
|
tmp = ioread32be(®s->tsec_id2);
|
|
|
|
/* check RGMII support */
|
|
if (iface_mode == E_ENET_IF_RGMII ||
|
|
iface_mode == E_ENET_IF_RMII)
|
|
if (tmp & DTSEC_ID2_INT_REDUCED_OFF)
|
|
return -EINVAL;
|
|
|
|
if (iface_mode == E_ENET_IF_SGMII ||
|
|
iface_mode == E_ENET_IF_MII)
|
|
if (tmp & DTSEC_ID2_INT_REDUCED_OFF)
|
|
return -EINVAL;
|
|
|
|
/***************ECNTRL************************/
|
|
|
|
is_rgmii = (bool)((iface_mode == E_ENET_IF_RGMII) ? TRUE : FALSE);
|
|
is_sgmii = (bool)((iface_mode == E_ENET_IF_SGMII) ? TRUE : FALSE);
|
|
is_qsgmii = (bool)((iface_mode == E_ENET_IF_QSGMII) ? TRUE : FALSE);
|
|
|
|
tmp = 0;
|
|
if (is_rgmii || iface_mode == E_ENET_IF_GMII)
|
|
tmp |= DTSEC_ECNTRL_GMIIM;
|
|
if (is_sgmii)
|
|
tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM);
|
|
if (is_qsgmii)
|
|
tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM |
|
|
DTSEC_ECNTRL_QSGMIIM);
|
|
if (is_rgmii)
|
|
tmp |= DTSEC_ECNTRL_RPM;
|
|
if (iface_speed == E_ENET_SPEED_100)
|
|
tmp |= DTSEC_ECNTRL_R100M;
|
|
|
|
iowrite32be(tmp, ®s->ecntrl);
|
|
/***************ECNTRL************************/
|
|
|
|
/***************TCTRL************************/
|
|
tmp = 0;
|
|
if (cfg->halfdup_on)
|
|
tmp |= DTSEC_TCTRL_THDF;
|
|
if (cfg->tx_time_stamp_en)
|
|
tmp |= DTSEC_TCTRL_TTSE;
|
|
|
|
iowrite32be(tmp, ®s->tctrl);
|
|
|
|
/***************TCTRL************************/
|
|
|
|
/***************PTV************************/
|
|
tmp = 0;
|
|
|
|
#ifdef FM_SHORT_PAUSE_TIME_ERRATA_DTSEC1
|
|
if ((fm_rev_maj == 1) && (fm_rev_min == 0))
|
|
cfg->tx_pause_time += 2;
|
|
#endif /* FM_SHORT_PAUSE_TIME_ERRATA_DTSEC1 */
|
|
|
|
if (cfg->tx_pause_time)
|
|
tmp |= cfg->tx_pause_time;
|
|
if (cfg->tx_pause_time_extd)
|
|
tmp |= cfg->tx_pause_time_extd << PTV_PTE_OFST;
|
|
iowrite32be(tmp, ®s->ptv);
|
|
|
|
/***************RCTRL************************/
|
|
tmp = 0;
|
|
tmp |= ((uint32_t)(cfg->rx_prepend & 0x0000001f)) << 16;
|
|
if (cfg->rx_ctrl_acc)
|
|
tmp |= RCTRL_CFA;
|
|
if (cfg->rx_group_hash_exd)
|
|
tmp |= RCTRL_GHTX;
|
|
if (cfg->rx_time_stamp_en)
|
|
tmp |= RCTRL_RTSE;
|
|
if (cfg->rx_drop_bcast)
|
|
tmp |= RCTRL_BC_REJ;
|
|
if (cfg->rx_short_frm)
|
|
tmp |= RCTRL_RSF;
|
|
if (cfg->rx_promisc)
|
|
tmp |= RCTRL_PROM;
|
|
|
|
iowrite32be(tmp, ®s->rctrl);
|
|
/***************RCTRL************************/
|
|
|
|
/*
|
|
* Assign a Phy Address to the TBI (TBIPA).
|
|
* Done also in cases where TBI is not selected to avoid conflict with
|
|
* the external PHY's Physical address
|
|
*/
|
|
iowrite32be(cfg->tbipa, ®s->tbipa);
|
|
|
|
/***************TMR_CTL************************/
|
|
iowrite32be(0, ®s->tmr_ctrl);
|
|
|
|
if (cfg->ptp_tsu_en) {
|
|
tmp = 0;
|
|
tmp |= TMR_PEVENT_TSRE;
|
|
iowrite32be(tmp, ®s->tmr_pevent);
|
|
|
|
if (cfg->ptp_exception_en) {
|
|
tmp = 0;
|
|
tmp |= TMR_PEMASK_TSREEN;
|
|
iowrite32be(tmp, ®s->tmr_pemask);
|
|
}
|
|
}
|
|
|
|
/***************MACCFG1***********************/
|
|
tmp = 0;
|
|
if (cfg->loopback)
|
|
tmp |= MACCFG1_LOOPBACK;
|
|
if (cfg->rx_flow)
|
|
tmp |= MACCFG1_RX_FLOW;
|
|
if (cfg->tx_flow)
|
|
tmp |= MACCFG1_TX_FLOW;
|
|
iowrite32be(tmp, ®s->maccfg1);
|
|
|
|
/***************MACCFG1***********************/
|
|
|
|
/***************MACCFG2***********************/
|
|
tmp = 0;
|
|
|
|
if (iface_speed < E_ENET_SPEED_1000)
|
|
tmp |= MACCFG2_NIBBLE_MODE;
|
|
else if (iface_speed == E_ENET_SPEED_1000)
|
|
tmp |= MACCFG2_BYTE_MODE;
|
|
|
|
tmp |= ((uint32_t) cfg->preamble_len & 0x0000000f)
|
|
<< PREAMBLE_LENGTH_SHIFT;
|
|
|
|
if (cfg->rx_preamble)
|
|
tmp |= MACCFG2_PRE_AM_Rx_EN;
|
|
if (cfg->tx_preamble)
|
|
tmp |= MACCFG2_PRE_AM_Tx_EN;
|
|
if (cfg->rx_len_check)
|
|
tmp |= MACCFG2_LENGTH_CHECK;
|
|
if (cfg->tx_pad_crc)
|
|
tmp |= MACCFG2_PAD_CRC_EN;
|
|
if (cfg->tx_crc)
|
|
tmp |= MACCFG2_CRC_EN;
|
|
if (!cfg->halfdup_on)
|
|
tmp |= MACCFG2_FULL_DUPLEX;
|
|
iowrite32be(tmp, ®s->maccfg2);
|
|
|
|
/***************MACCFG2***********************/
|
|
|
|
/***************IPGIFG************************/
|
|
tmp = (((cfg->non_back_to_back_ipg1 <<
|
|
IPGIFG_NON_BACK_TO_BACK_IPG_1_SHIFT)
|
|
& IPGIFG_NON_BACK_TO_BACK_IPG_1)
|
|
| ((cfg->non_back_to_back_ipg2 <<
|
|
IPGIFG_NON_BACK_TO_BACK_IPG_2_SHIFT)
|
|
& IPGIFG_NON_BACK_TO_BACK_IPG_2)
|
|
| ((cfg->min_ifg_enforcement <<
|
|
IPGIFG_MIN_IFG_ENFORCEMENT_SHIFT)
|
|
& IPGIFG_MIN_IFG_ENFORCEMENT)
|
|
| (cfg->back_to_back_ipg & IPGIFG_BACK_TO_BACK_IPG));
|
|
iowrite32be(tmp, ®s->ipgifg);
|
|
|
|
/***************IPGIFG************************/
|
|
|
|
/***************HAFDUP************************/
|
|
tmp = 0;
|
|
|
|
if (cfg->halfdup_alt_backoff_en)
|
|
tmp = (uint32_t)(HAFDUP_ALT_BEB |
|
|
((cfg->halfdup_alt_backoff_val & 0x0000000f)
|
|
<< HAFDUP_ALTERNATE_BEB_TRUNCATION_SHIFT));
|
|
if (cfg->halfdup_bp_no_backoff)
|
|
tmp |= HAFDUP_BP_NO_BACKOFF;
|
|
if (cfg->halfdup_no_backoff)
|
|
tmp |= HAFDUP_NO_BACKOFF;
|
|
if (cfg->halfdup_excess_defer)
|
|
tmp |= HAFDUP_EXCESS_DEFER;
|
|
tmp |= ((cfg->halfdup_retransmit << HAFDUP_RETRANSMISSION_MAX_SHIFT)
|
|
& HAFDUP_RETRANSMISSION_MAX);
|
|
tmp |= (cfg->halfdup_coll_window & HAFDUP_COLLISION_WINDOW);
|
|
|
|
iowrite32be(tmp, ®s->hafdup);
|
|
/***************HAFDUP************************/
|
|
|
|
/***************MAXFRM************************/
|
|
/* Initialize MAXFRM */
|
|
iowrite32be(cfg->maximum_frame, ®s->maxfrm);
|
|
|
|
/***************MAXFRM************************/
|
|
|
|
/***************CAM1************************/
|
|
iowrite32be(0xffffffff, ®s->cam1);
|
|
iowrite32be(0xffffffff, ®s->cam2);
|
|
|
|
/***************IMASK************************/
|
|
iowrite32be(exception_mask, ®s->imask);
|
|
/***************IMASK************************/
|
|
|
|
/***************IEVENT************************/
|
|
iowrite32be(0xffffffff, ®s->ievent);
|
|
|
|
/***************MACSTNADDR1/2*****************/
|
|
|
|
tmp = (uint32_t)((macaddr[5] << 24) |
|
|
(macaddr[4] << 16) |
|
|
(macaddr[3] << 8) |
|
|
macaddr[2]);
|
|
iowrite32be(tmp, ®s->macstnaddr1);
|
|
|
|
tmp = (uint32_t)((macaddr[1] << 24) |
|
|
(macaddr[0] << 16));
|
|
iowrite32be(tmp, ®s->macstnaddr2);
|
|
|
|
/***************MACSTNADDR1/2*****************/
|
|
|
|
/*****************HASH************************/
|
|
for (i = 0; i < NUM_OF_HASH_REGS ; i++) {
|
|
/* Initialize IADDRx */
|
|
iowrite32be(0, ®s->igaddr[i]);
|
|
/* Initialize GADDRx */
|
|
iowrite32be(0, ®s->gaddr[i]);
|
|
}
|
|
|
|
fman_dtsec_reset_stat(regs);
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint16_t fman_dtsec_get_max_frame_len(struct dtsec_regs *regs)
|
|
{
|
|
return (uint16_t)ioread32be(®s->maxfrm);
|
|
}
|
|
|
|
void fman_dtsec_set_max_frame_len(struct dtsec_regs *regs, uint16_t length)
|
|
{
|
|
iowrite32be(length, ®s->maxfrm);
|
|
}
|
|
|
|
void fman_dtsec_set_mac_address(struct dtsec_regs *regs, uint8_t *adr)
|
|
{
|
|
uint32_t tmp;
|
|
|
|
tmp = (uint32_t)((adr[5] << 24) |
|
|
(adr[4] << 16) |
|
|
(adr[3] << 8) |
|
|
adr[2]);
|
|
iowrite32be(tmp, ®s->macstnaddr1);
|
|
|
|
tmp = (uint32_t)((adr[1] << 24) |
|
|
(adr[0] << 16));
|
|
iowrite32be(tmp, ®s->macstnaddr2);
|
|
}
|
|
|
|
void fman_dtsec_get_mac_address(struct dtsec_regs *regs, uint8_t *macaddr)
|
|
{
|
|
uint32_t tmp1, tmp2;
|
|
|
|
tmp1 = ioread32be(®s->macstnaddr1);
|
|
tmp2 = ioread32be(®s->macstnaddr2);
|
|
|
|
macaddr[0] = (uint8_t)((tmp2 & 0x00ff0000) >> 16);
|
|
macaddr[1] = (uint8_t)((tmp2 & 0xff000000) >> 24);
|
|
macaddr[2] = (uint8_t)(tmp1 & 0x000000ff);
|
|
macaddr[3] = (uint8_t)((tmp1 & 0x0000ff00) >> 8);
|
|
macaddr[4] = (uint8_t)((tmp1 & 0x00ff0000) >> 16);
|
|
macaddr[5] = (uint8_t)((tmp1 & 0xff000000) >> 24);
|
|
}
|
|
|
|
void fman_dtsec_set_hash_table(struct dtsec_regs *regs, uint32_t crc, bool mcast, bool ghtx)
|
|
{
|
|
int32_t bucket;
|
|
if (ghtx)
|
|
bucket = (int32_t)((crc >> 23) & 0x1ff);
|
|
else {
|
|
bucket = (int32_t)((crc >> 24) & 0xff);
|
|
/* if !ghtx and mcast the bit must be set in gaddr instead of igaddr. */
|
|
if (mcast)
|
|
bucket += 0x100;
|
|
}
|
|
fman_dtsec_set_bucket(regs, bucket, TRUE);
|
|
}
|
|
|
|
void fman_dtsec_set_bucket(struct dtsec_regs *regs, int bucket, bool enable)
|
|
{
|
|
int reg_idx = (bucket >> 5) & 0xf;
|
|
int bit_idx = bucket & 0x1f;
|
|
uint32_t bit_mask = 0x80000000 >> bit_idx;
|
|
uint32_t *reg;
|
|
|
|
if (reg_idx > 7)
|
|
reg = ®s->gaddr[reg_idx-8];
|
|
else
|
|
reg = ®s->igaddr[reg_idx];
|
|
|
|
if (enable)
|
|
iowrite32be(ioread32be(reg) | bit_mask, reg);
|
|
else
|
|
iowrite32be(ioread32be(reg) & (~bit_mask), reg);
|
|
}
|
|
|
|
void fman_dtsec_reset_filter_table(struct dtsec_regs *regs, bool mcast, bool ucast)
|
|
{
|
|
int i;
|
|
bool ghtx;
|
|
|
|
ghtx = (bool)((ioread32be(®s->rctrl) & RCTRL_GHTX) ? TRUE : FALSE);
|
|
|
|
if (ucast || (ghtx && mcast)) {
|
|
for (i = 0; i < NUM_OF_HASH_REGS; i++)
|
|
iowrite32be(0, ®s->igaddr[i]);
|
|
}
|
|
if (mcast) {
|
|
for (i = 0; i < NUM_OF_HASH_REGS; i++)
|
|
iowrite32be(0, ®s->gaddr[i]);
|
|
}
|
|
}
|
|
|
|
int fman_dtsec_set_tbi_phy_addr(struct dtsec_regs *regs,
|
|
uint8_t addr)
|
|
{
|
|
if (addr > 0 && addr < 32)
|
|
iowrite32be(addr, ®s->tbipa);
|
|
else
|
|
return -EINVAL;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void fman_dtsec_set_wol(struct dtsec_regs *regs, bool en)
|
|
{
|
|
uint32_t tmp;
|
|
|
|
tmp = ioread32be(®s->maccfg2);
|
|
if (en)
|
|
tmp |= MACCFG2_MAGIC_PACKET_EN;
|
|
else
|
|
tmp &= ~MACCFG2_MAGIC_PACKET_EN;
|
|
iowrite32be(tmp, ®s->maccfg2);
|
|
}
|
|
|
|
int fman_dtsec_adjust_link(struct dtsec_regs *regs,
|
|
enum enet_interface iface_mode,
|
|
enum enet_speed speed, bool full_dx)
|
|
{
|
|
uint32_t tmp;
|
|
|
|
UNUSED(iface_mode);
|
|
|
|
if ((speed == E_ENET_SPEED_1000) && !full_dx)
|
|
return -EINVAL;
|
|
|
|
tmp = ioread32be(®s->maccfg2);
|
|
if (!full_dx)
|
|
tmp &= ~MACCFG2_FULL_DUPLEX;
|
|
else
|
|
tmp |= MACCFG2_FULL_DUPLEX;
|
|
|
|
tmp &= ~(MACCFG2_NIBBLE_MODE | MACCFG2_BYTE_MODE);
|
|
if (speed < E_ENET_SPEED_1000)
|
|
tmp |= MACCFG2_NIBBLE_MODE;
|
|
else if (speed == E_ENET_SPEED_1000)
|
|
tmp |= MACCFG2_BYTE_MODE;
|
|
iowrite32be(tmp, ®s->maccfg2);
|
|
|
|
tmp = ioread32be(®s->ecntrl);
|
|
if (speed == E_ENET_SPEED_100)
|
|
tmp |= DTSEC_ECNTRL_R100M;
|
|
else
|
|
tmp &= ~DTSEC_ECNTRL_R100M;
|
|
iowrite32be(tmp, ®s->ecntrl);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void fman_dtsec_set_uc_promisc(struct dtsec_regs *regs, bool enable)
|
|
{
|
|
uint32_t tmp;
|
|
|
|
tmp = ioread32be(®s->rctrl);
|
|
|
|
if (enable)
|
|
tmp |= RCTRL_UPROM;
|
|
else
|
|
tmp &= ~RCTRL_UPROM;
|
|
|
|
iowrite32be(tmp, ®s->rctrl);
|
|
}
|
|
|
|
void fman_dtsec_set_mc_promisc(struct dtsec_regs *regs, bool enable)
|
|
{
|
|
uint32_t tmp;
|
|
|
|
tmp = ioread32be(®s->rctrl);
|
|
|
|
if (enable)
|
|
tmp |= RCTRL_MPROM;
|
|
else
|
|
tmp &= ~RCTRL_MPROM;
|
|
|
|
iowrite32be(tmp, ®s->rctrl);
|
|
}
|
|
|
|
bool fman_dtsec_get_clear_carry_regs(struct dtsec_regs *regs,
|
|
uint32_t *car1, uint32_t *car2)
|
|
{
|
|
/* read carry registers */
|
|
*car1 = ioread32be(®s->car1);
|
|
*car2 = ioread32be(®s->car2);
|
|
/* clear carry registers */
|
|
if (*car1)
|
|
iowrite32be(*car1, ®s->car1);
|
|
if (*car2)
|
|
iowrite32be(*car2, ®s->car2);
|
|
|
|
return (bool)((*car1 | *car2) ? TRUE : FALSE);
|
|
}
|
|
|
|
void fman_dtsec_reset_stat(struct dtsec_regs *regs)
|
|
{
|
|
/* clear HW counters */
|
|
iowrite32be(ioread32be(®s->ecntrl) |
|
|
DTSEC_ECNTRL_CLRCNT, ®s->ecntrl);
|
|
}
|
|
|
|
int fman_dtsec_set_stat_level(struct dtsec_regs *regs, enum dtsec_stat_level level)
|
|
{
|
|
switch (level) {
|
|
case E_MAC_STAT_NONE:
|
|
iowrite32be(0xffffffff, ®s->cam1);
|
|
iowrite32be(0xffffffff, ®s->cam2);
|
|
iowrite32be(ioread32be(®s->ecntrl) & ~DTSEC_ECNTRL_STEN,
|
|
®s->ecntrl);
|
|
iowrite32be(ioread32be(®s->imask) & ~DTSEC_IMASK_MSROEN,
|
|
®s->imask);
|
|
break;
|
|
case E_MAC_STAT_PARTIAL:
|
|
iowrite32be(CAM1_ERRORS_ONLY, ®s->cam1);
|
|
iowrite32be(CAM2_ERRORS_ONLY, ®s->cam2);
|
|
iowrite32be(ioread32be(®s->ecntrl) | DTSEC_ECNTRL_STEN,
|
|
®s->ecntrl);
|
|
iowrite32be(ioread32be(®s->imask) | DTSEC_IMASK_MSROEN,
|
|
®s->imask);
|
|
break;
|
|
case E_MAC_STAT_MIB_GRP1:
|
|
iowrite32be((uint32_t)~CAM1_MIB_GRP_1, ®s->cam1);
|
|
iowrite32be((uint32_t)~CAM2_MIB_GRP_1, ®s->cam2);
|
|
iowrite32be(ioread32be(®s->ecntrl) | DTSEC_ECNTRL_STEN,
|
|
®s->ecntrl);
|
|
iowrite32be(ioread32be(®s->imask) | DTSEC_IMASK_MSROEN,
|
|
®s->imask);
|
|
break;
|
|
case E_MAC_STAT_FULL:
|
|
iowrite32be(0, ®s->cam1);
|
|
iowrite32be(0, ®s->cam2);
|
|
iowrite32be(ioread32be(®s->ecntrl) | DTSEC_ECNTRL_STEN,
|
|
®s->ecntrl);
|
|
iowrite32be(ioread32be(®s->imask) | DTSEC_IMASK_MSROEN,
|
|
®s->imask);
|
|
break;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void fman_dtsec_set_ts(struct dtsec_regs *regs, bool en)
|
|
{
|
|
if (en) {
|
|
iowrite32be(ioread32be(®s->rctrl) | RCTRL_RTSE,
|
|
®s->rctrl);
|
|
iowrite32be(ioread32be(®s->tctrl) | DTSEC_TCTRL_TTSE,
|
|
®s->tctrl);
|
|
} else {
|
|
iowrite32be(ioread32be(®s->rctrl) & ~RCTRL_RTSE,
|
|
®s->rctrl);
|
|
iowrite32be(ioread32be(®s->tctrl) & ~DTSEC_TCTRL_TTSE,
|
|
®s->tctrl);
|
|
}
|
|
}
|
|
|
|
void fman_dtsec_enable(struct dtsec_regs *regs, bool apply_rx, bool apply_tx)
|
|
{
|
|
uint32_t tmp;
|
|
|
|
tmp = ioread32be(®s->maccfg1);
|
|
|
|
if (apply_rx)
|
|
tmp |= MACCFG1_RX_EN ;
|
|
|
|
if (apply_tx)
|
|
tmp |= MACCFG1_TX_EN ;
|
|
|
|
iowrite32be(tmp, ®s->maccfg1);
|
|
}
|
|
|
|
void fman_dtsec_clear_addr_in_paddr(struct dtsec_regs *regs, uint8_t paddr_num)
|
|
{
|
|
iowrite32be(0, ®s->macaddr[paddr_num].exact_match1);
|
|
iowrite32be(0, ®s->macaddr[paddr_num].exact_match2);
|
|
}
|
|
|
|
void fman_dtsec_add_addr_in_paddr(struct dtsec_regs *regs,
|
|
uint64_t addr,
|
|
uint8_t paddr_num)
|
|
{
|
|
uint32_t tmp;
|
|
|
|
tmp = (uint32_t)(addr);
|
|
/* swap */
|
|
tmp = (((tmp & 0x000000FF) << 24) |
|
|
((tmp & 0x0000FF00) << 8) |
|
|
((tmp & 0x00FF0000) >> 8) |
|
|
((tmp & 0xFF000000) >> 24));
|
|
iowrite32be(tmp, ®s->macaddr[paddr_num].exact_match1);
|
|
|
|
tmp = (uint32_t)(addr>>32);
|
|
/* swap */
|
|
tmp = (((tmp & 0x000000FF) << 24) |
|
|
((tmp & 0x0000FF00) << 8) |
|
|
((tmp & 0x00FF0000) >> 8) |
|
|
((tmp & 0xFF000000) >> 24));
|
|
iowrite32be(tmp, ®s->macaddr[paddr_num].exact_match2);
|
|
}
|
|
|
|
void fman_dtsec_disable(struct dtsec_regs *regs, bool apply_rx, bool apply_tx)
|
|
{
|
|
uint32_t tmp;
|
|
|
|
tmp = ioread32be(®s->maccfg1);
|
|
|
|
if (apply_rx)
|
|
tmp &= ~MACCFG1_RX_EN;
|
|
|
|
if (apply_tx)
|
|
tmp &= ~MACCFG1_TX_EN;
|
|
|
|
iowrite32be(tmp, ®s->maccfg1);
|
|
}
|
|
|
|
void fman_dtsec_set_tx_pause_frames(struct dtsec_regs *regs, uint16_t time)
|
|
{
|
|
uint32_t ptv = 0;
|
|
|
|
/* fixme: don't enable tx pause for half-duplex */
|
|
|
|
if (time) {
|
|
ptv = ioread32be(®s->ptv);
|
|
ptv &= 0xffff0000;
|
|
ptv |= time & 0x0000ffff;
|
|
iowrite32be(ptv, ®s->ptv);
|
|
|
|
/* trigger the transmission of a flow-control pause frame */
|
|
iowrite32be(ioread32be(®s->maccfg1) | MACCFG1_TX_FLOW,
|
|
®s->maccfg1);
|
|
} else
|
|
iowrite32be(ioread32be(®s->maccfg1) & ~MACCFG1_TX_FLOW,
|
|
®s->maccfg1);
|
|
}
|
|
|
|
void fman_dtsec_handle_rx_pause(struct dtsec_regs *regs, bool en)
|
|
{
|
|
uint32_t tmp;
|
|
|
|
/* todo: check if mac is set to full-duplex */
|
|
|
|
tmp = ioread32be(®s->maccfg1);
|
|
if (en)
|
|
tmp |= MACCFG1_RX_FLOW;
|
|
else
|
|
tmp &= ~MACCFG1_RX_FLOW;
|
|
iowrite32be(tmp, ®s->maccfg1);
|
|
}
|
|
|
|
uint32_t fman_dtsec_get_rctrl(struct dtsec_regs *regs)
|
|
{
|
|
return ioread32be(®s->rctrl);
|
|
}
|
|
|
|
uint32_t fman_dtsec_get_revision(struct dtsec_regs *regs)
|
|
{
|
|
return ioread32be(®s->tsec_id);
|
|
}
|
|
|
|
uint32_t fman_dtsec_get_event(struct dtsec_regs *regs, uint32_t ev_mask)
|
|
{
|
|
return ioread32be(®s->ievent) & ev_mask;
|
|
}
|
|
|
|
void fman_dtsec_ack_event(struct dtsec_regs *regs, uint32_t ev_mask)
|
|
{
|
|
iowrite32be(ev_mask, ®s->ievent);
|
|
}
|
|
|
|
uint32_t fman_dtsec_get_interrupt_mask(struct dtsec_regs *regs)
|
|
{
|
|
return ioread32be(®s->imask);
|
|
}
|
|
|
|
uint32_t fman_dtsec_check_and_clear_tmr_event(struct dtsec_regs *regs)
|
|
{
|
|
uint32_t event;
|
|
|
|
event = ioread32be(®s->tmr_pevent);
|
|
event &= ioread32be(®s->tmr_pemask);
|
|
|
|
if (event)
|
|
iowrite32be(event, ®s->tmr_pevent);
|
|
return event;
|
|
}
|
|
|
|
void fman_dtsec_enable_tmr_interrupt(struct dtsec_regs *regs)
|
|
{
|
|
iowrite32be(ioread32be(®s->tmr_pemask) | TMR_PEMASK_TSREEN,
|
|
®s->tmr_pemask);
|
|
}
|
|
|
|
void fman_dtsec_disable_tmr_interrupt(struct dtsec_regs *regs)
|
|
{
|
|
iowrite32be(ioread32be(®s->tmr_pemask) & ~TMR_PEMASK_TSREEN,
|
|
®s->tmr_pemask);
|
|
}
|
|
|
|
void fman_dtsec_enable_interrupt(struct dtsec_regs *regs, uint32_t ev_mask)
|
|
{
|
|
iowrite32be(ioread32be(®s->imask) | ev_mask, ®s->imask);
|
|
}
|
|
|
|
void fman_dtsec_disable_interrupt(struct dtsec_regs *regs, uint32_t ev_mask)
|
|
{
|
|
iowrite32be(ioread32be(®s->imask) & ~ev_mask, ®s->imask);
|
|
}
|
|
|
|
uint32_t fman_dtsec_get_stat_counter(struct dtsec_regs *regs,
|
|
enum dtsec_stat_counters reg_name)
|
|
{
|
|
uint32_t ret_val;
|
|
|
|
switch (reg_name) {
|
|
case E_DTSEC_STAT_TR64:
|
|
ret_val = ioread32be(®s->tr64);
|
|
break;
|
|
case E_DTSEC_STAT_TR127:
|
|
ret_val = ioread32be(®s->tr127);
|
|
break;
|
|
case E_DTSEC_STAT_TR255:
|
|
ret_val = ioread32be(®s->tr255);
|
|
break;
|
|
case E_DTSEC_STAT_TR511:
|
|
ret_val = ioread32be(®s->tr511);
|
|
break;
|
|
case E_DTSEC_STAT_TR1K:
|
|
ret_val = ioread32be(®s->tr1k);
|
|
break;
|
|
case E_DTSEC_STAT_TRMAX:
|
|
ret_val = ioread32be(®s->trmax);
|
|
break;
|
|
case E_DTSEC_STAT_TRMGV:
|
|
ret_val = ioread32be(®s->trmgv);
|
|
break;
|
|
case E_DTSEC_STAT_RBYT:
|
|
ret_val = ioread32be(®s->rbyt);
|
|
break;
|
|
case E_DTSEC_STAT_RPKT:
|
|
ret_val = ioread32be(®s->rpkt);
|
|
break;
|
|
case E_DTSEC_STAT_RMCA:
|
|
ret_val = ioread32be(®s->rmca);
|
|
break;
|
|
case E_DTSEC_STAT_RBCA:
|
|
ret_val = ioread32be(®s->rbca);
|
|
break;
|
|
case E_DTSEC_STAT_RXPF:
|
|
ret_val = ioread32be(®s->rxpf);
|
|
break;
|
|
case E_DTSEC_STAT_RALN:
|
|
ret_val = ioread32be(®s->raln);
|
|
break;
|
|
case E_DTSEC_STAT_RFLR:
|
|
ret_val = ioread32be(®s->rflr);
|
|
break;
|
|
case E_DTSEC_STAT_RCDE:
|
|
ret_val = ioread32be(®s->rcde);
|
|
break;
|
|
case E_DTSEC_STAT_RCSE:
|
|
ret_val = ioread32be(®s->rcse);
|
|
break;
|
|
case E_DTSEC_STAT_RUND:
|
|
ret_val = ioread32be(®s->rund);
|
|
break;
|
|
case E_DTSEC_STAT_ROVR:
|
|
ret_val = ioread32be(®s->rovr);
|
|
break;
|
|
case E_DTSEC_STAT_RFRG:
|
|
ret_val = ioread32be(®s->rfrg);
|
|
break;
|
|
case E_DTSEC_STAT_RJBR:
|
|
ret_val = ioread32be(®s->rjbr);
|
|
break;
|
|
case E_DTSEC_STAT_RDRP:
|
|
ret_val = ioread32be(®s->rdrp);
|
|
break;
|
|
case E_DTSEC_STAT_TFCS:
|
|
ret_val = ioread32be(®s->tfcs);
|
|
break;
|
|
case E_DTSEC_STAT_TBYT:
|
|
ret_val = ioread32be(®s->tbyt);
|
|
break;
|
|
case E_DTSEC_STAT_TPKT:
|
|
ret_val = ioread32be(®s->tpkt);
|
|
break;
|
|
case E_DTSEC_STAT_TMCA:
|
|
ret_val = ioread32be(®s->tmca);
|
|
break;
|
|
case E_DTSEC_STAT_TBCA:
|
|
ret_val = ioread32be(®s->tbca);
|
|
break;
|
|
case E_DTSEC_STAT_TXPF:
|
|
ret_val = ioread32be(®s->txpf);
|
|
break;
|
|
case E_DTSEC_STAT_TNCL:
|
|
ret_val = ioread32be(®s->tncl);
|
|
break;
|
|
case E_DTSEC_STAT_TDRP:
|
|
ret_val = ioread32be(®s->tdrp);
|
|
break;
|
|
default:
|
|
ret_val = 0;
|
|
}
|
|
|
|
return ret_val;
|
|
}
|