diff options
Diffstat (limited to 'drivers/net/fm/dtsec.c')
-rw-r--r-- | drivers/net/fm/dtsec.c | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/drivers/net/fm/dtsec.c b/drivers/net/fm/dtsec.c new file mode 100644 index 0000000..a77ee20 --- /dev/null +++ b/drivers/net/fm/dtsec.c @@ -0,0 +1,181 @@ +/* + * Copyright 2009-2011 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/types.h> +#include <asm/io.h> +#include <asm/fsl_enet.h> +#include <asm/fsl_dtsec.h> +#include <fsl_mdio.h> +#include <phy.h> + +#include "fm.h" + +#define RCTRL_INIT (RCTRL_GRS | RCTRL_UPROM) +#define TCTRL_INIT TCTRL_GTS +#define MACCFG1_INIT MACCFG1_SOFT_RST + +#define MACCFG2_INIT (MACCFG2_PRE_LEN(0x7) | MACCFG2_LEN_CHECK | \ + MACCFG2_PAD_CRC | MACCFG2_FULL_DUPLEX | \ + MACCFG2_IF_MODE_NIBBLE) + +/* MAXFRM - maximum frame length register */ +#define MAXFRM_MASK 0x00003fff + +static void dtsec_init_mac(struct fsl_enet_mac *mac) +{ + struct dtsec *regs = mac->base; + + /* soft reset */ + out_be32(®s->maccfg1, MACCFG1_SOFT_RST); + udelay(1000); + + /* clear soft reset, Rx/Tx MAC disable */ + out_be32(®s->maccfg1, 0); + + /* graceful stop rx */ + out_be32(®s->rctrl, RCTRL_INIT); + udelay(1000); + + /* graceful stop tx */ + out_be32(®s->tctrl, TCTRL_INIT); + udelay(1000); + + /* disable all interrupts */ + out_be32(®s->imask, IMASK_MASK_ALL); + + /* clear all events */ + out_be32(®s->ievent, IEVENT_CLEAR_ALL); + + /* set the max Rx length */ + out_be32(®s->maxfrm, mac->max_rx_len & MAXFRM_MASK); + + /* set the ecntrl to reset value */ + out_be32(®s->ecntrl, ECNTRL_DEFAULT); + + /* + * Rx length check, no strip CRC for Rx, pad and append CRC for Tx, + * full duplex + */ + out_be32(®s->maccfg2, MACCFG2_INIT); +} + +static void dtsec_enable_mac(struct fsl_enet_mac *mac) +{ + struct dtsec *regs = mac->base; + + /* enable Rx/Tx MAC */ + setbits_be32(®s->maccfg1, MACCFG1_RXTX_EN); + + /* clear the graceful Rx stop */ + clrbits_be32(®s->rctrl, RCTRL_GRS); + + /* clear the graceful Tx stop */ + clrbits_be32(®s->tctrl, TCTRL_GTS); +} + +static void dtsec_disable_mac(struct fsl_enet_mac *mac) +{ + struct dtsec *regs = mac->base; + + /* graceful Rx stop */ + setbits_be32(®s->rctrl, RCTRL_GRS); + + /* graceful Tx stop */ + setbits_be32(®s->tctrl, TCTRL_GTS); + + /* disable Rx/Tx MAC */ + clrbits_be32(®s->maccfg1, MACCFG1_RXTX_EN); +} + +static void dtsec_set_mac_addr(struct fsl_enet_mac *mac, u8 *mac_addr) +{ + struct dtsec *regs = mac->base; + u32 mac_addr1, mac_addr2; + + /* + * if a station address of 0x12345678ABCD, perform a write to + * MACSTNADDR1 of 0xCDAB7856, MACSTNADDR2 of 0x34120000 + */ + mac_addr1 = (mac_addr[5] << 24) | (mac_addr[4] << 16) | \ + (mac_addr[3] << 8) | (mac_addr[2]); + out_be32(®s->macstnaddr1, mac_addr1); + + mac_addr2 = ((mac_addr[1] << 24) | (mac_addr[0] << 16)) & 0xffff0000; + out_be32(®s->macstnaddr2, mac_addr2); +} + +static void dtsec_set_interface_mode(struct fsl_enet_mac *mac, + phy_interface_t type, int speed) +{ + struct dtsec *regs = mac->base; + u32 ecntrl, maccfg2; + + /* clear all bits relative with interface mode */ + ecntrl = in_be32(®s->ecntrl); + ecntrl &= ~(ECNTRL_TBIM | ECNTRL_GMIIM | ECNTRL_RPM | + ECNTRL_R100M | ECNTRL_SGMIIM); + + maccfg2 = in_be32(®s->maccfg2); + maccfg2 &= ~MACCFG2_IF_MODE_MASK; + + if (speed == SPEED_1000) + maccfg2 |= MACCFG2_IF_MODE_BYTE; + else + maccfg2 |= MACCFG2_IF_MODE_NIBBLE; + + /* set interface mode */ + switch (type) { + case PHY_INTERFACE_MODE_GMII: + ecntrl |= ECNTRL_GMIIM; + break; + case PHY_INTERFACE_MODE_RGMII: + ecntrl |= (ECNTRL_GMIIM | ECNTRL_RPM); + if (speed == SPEED_100) + ecntrl |= ECNTRL_R100M; + break; + case PHY_INTERFACE_MODE_RMII: + if (speed == SPEED_100) + ecntrl |= ECNTRL_R100M; + break; + case PHY_INTERFACE_MODE_SGMII: + ecntrl |= (ECNTRL_SGMIIM | ECNTRL_TBIM); + if (speed == SPEED_100) + ecntrl |= ECNTRL_R100M; + break; + default: + break; + } + + out_be32(®s->ecntrl, ecntrl); + out_be32(®s->maccfg2, maccfg2); +} + +void init_dtsec(struct fsl_enet_mac *mac, void *base, + void *phyregs, int max_rx_len) +{ + mac->base = base; + mac->phyregs = NULL; + mac->max_rx_len = max_rx_len; + mac->init_mac = dtsec_init_mac; + mac->enable_mac = dtsec_enable_mac; + mac->disable_mac = dtsec_disable_mac; + mac->set_mac_addr = dtsec_set_mac_addr; + mac->set_if_mode = dtsec_set_interface_mode; +} |