dtsec.c 3.9 KB
Newer Older
Tony Feng committed
1 2 3 4 5 6 7 8 9
/*
 * Copyright 2009-2011 Freescale Semiconductor, Inc.
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <asm/types.h>
#include <asm/io.h>
10
#include <fsl_dtsec.h>
Tony Feng committed
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
#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(&regs->maccfg1, MACCFG1_SOFT_RST);
	udelay(1000);

	/* clear soft reset, Rx/Tx MAC disable */
	out_be32(&regs->maccfg1, 0);

	/* graceful stop rx */
	out_be32(&regs->rctrl, RCTRL_INIT);
	udelay(1000);

	/* graceful stop tx */
	out_be32(&regs->tctrl, TCTRL_INIT);
	udelay(1000);

	/* disable all interrupts */
	out_be32(&regs->imask, IMASK_MASK_ALL);

	/* clear all events */
	out_be32(&regs->ievent, IEVENT_CLEAR_ALL);

	/* set the max Rx length */
	out_be32(&regs->maxfrm, mac->max_rx_len & MAXFRM_MASK);

	/* set the ecntrl to reset value */
	out_be32(&regs->ecntrl, ECNTRL_DEFAULT);

	/*
	 * Rx length check, no strip CRC for Rx, pad and append CRC for Tx,
	 * full duplex
	 */
	out_be32(&regs->maccfg2, MACCFG2_INIT);
}

static void dtsec_enable_mac(struct fsl_enet_mac *mac)
{
	struct dtsec *regs = mac->base;

	/* enable Rx/Tx MAC */
	setbits_be32(&regs->maccfg1, MACCFG1_RXTX_EN);

	/* clear the graceful Rx stop */
	clrbits_be32(&regs->rctrl, RCTRL_GRS);

	/* clear the graceful Tx stop */
	clrbits_be32(&regs->tctrl, TCTRL_GTS);
}

static void dtsec_disable_mac(struct fsl_enet_mac *mac)
{
	struct dtsec *regs = mac->base;

	/* graceful Rx stop */
	setbits_be32(&regs->rctrl, RCTRL_GRS);

	/* graceful Tx stop */
	setbits_be32(&regs->tctrl, TCTRL_GTS);

	/* disable Rx/Tx MAC */
	clrbits_be32(&regs->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(&regs->macstnaddr1, mac_addr1);

	mac_addr2 = ((mac_addr[1] << 24) | (mac_addr[0] << 16)) & 0xffff0000;
	out_be32(&regs->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(&regs->ecntrl);
	ecntrl &= ~(ECNTRL_TBIM | ECNTRL_GMIIM | ECNTRL_RPM |
				  ECNTRL_R100M | ECNTRL_SGMIIM);

	maccfg2 = in_be32(&regs->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(&regs->ecntrl, ecntrl);
	out_be32(&regs->maccfg2, maccfg2);
}

void init_dtsec(struct fsl_enet_mac *mac, void *base,
		void *phyregs, int max_rx_len)
{
	mac->base = base;
	mac->phyregs = phyregs;
	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;
}