/*
 * tsec.c
 * Motorola Three Speed Ethernet Controller driver
 *
 * This software may be used and distributed according to the
 * terms of the GNU Public License, Version 2, incorporated
 * herein by reference.
 *
 * (C) Copyright 2003, Motorola, Inc.
 * maintained by Xianghua Xiao (x.xiao@motorola.com)
 * author Andy Fleming
 *
 */

#include <config.h>
#include <mpc85xx.h>
#include <common.h>
#include <malloc.h>
#include <net.h>
#include <command.h>

#if defined(CONFIG_TSEC_ENET)
#include "tsec.h"

#define TX_BUF_CNT 2

#undef TSEC_DEBUG
#ifdef TSEC_DEBUG
#define DBGPRINT(x) printf(x)
#else
#define DBGPRINT(x)
#endif

static uint rxIdx;	/* index of the current RX buffer */
static uint txIdx;	/* index of the current TX buffer */

typedef volatile struct rtxbd {
	txbd8_t txbd[TX_BUF_CNT];
	rxbd8_t rxbd[PKTBUFSRX];
}  RTXBD;

#ifdef __GNUC__
static RTXBD rtx __attribute__ ((aligned(8)));
#else
#error "rtx must be 64-bit aligned"
#endif

static int tsec_send(struct eth_device* dev, volatile void *packet, int length);
static int tsec_recv(struct eth_device* dev);
static int tsec_init(struct eth_device* dev, bd_t * bd);
static void tsec_halt(struct eth_device* dev);
static void init_registers(volatile tsec_t *regs);
static void startup_tsec(volatile tsec_t *regs);
static void init_phy(volatile tsec_t *regs);

/* Initialize device structure.  returns 0 on failure, 1 on
 * success */
int tsec_initialize(bd_t *bis)
{
	struct eth_device* dev;
	int i;

	dev = (struct eth_device*) malloc(sizeof *dev);

	if(dev == NULL)
		return 0;

	memset(dev, 0, sizeof *dev);

	sprintf(dev->name, "MOTOROLA ETHERNET");
	dev->iobase = 0;
	dev->priv   = 0;
	dev->init   = tsec_init;
	dev->halt   = tsec_halt;
	dev->send   = tsec_send;
	dev->recv   = tsec_recv;

	/* Tell u-boot to get the addr from the env */
	for(i=0;i<6;i++)
		dev->enetaddr[i] = 0;

	eth_register(dev);

	return 1;
}


/* Initializes data structures and registers for the controller,
 * and brings the interface up */
int tsec_init(struct eth_device* dev, bd_t * bd)
{
	volatile tsec_t *regs;
	uint tempval;
	char tmpbuf[MAC_ADDR_LEN];
	int i;

	regs = (volatile tsec_t *)(TSEC_BASE_ADDR);

	/* Make sure the controller is stopped */
	tsec_halt(dev);

	/* Reset the MAC */
	regs->maccfg1 |= MACCFG1_SOFT_RESET;

	/* Clear MACCFG1[Soft_Reset] */
	regs->maccfg1 &= ~(MACCFG1_SOFT_RESET);

	/* Init MACCFG2.  Defaults to GMII/MII */
	regs->maccfg2 = MACCFG2_INIT_SETTINGS;

	/* Init ECNTRL */
	regs->ecntrl = ECNTRL_INIT_SETTINGS;

	/* Copy the station address into the address registers.
	 * Backwards, because little endian MACS are dumb */
	for(i=0;i<MAC_ADDR_LEN;i++) {
		tmpbuf[MAC_ADDR_LEN - 1 - i] = bd->bi_enetaddr[i];
	}
	(uint)(regs->macstnaddr1) = *((uint *)(tmpbuf));

	tempval = *((uint *)(tmpbuf +4));

	(uint)(regs->macstnaddr2) = tempval;

	/* Initialize the PHY */
	init_phy(regs);

	/* reset the indices to zero */
	rxIdx = 0;
	txIdx = 0;

	/* Clear out (for the most part) the other registers */
	init_registers(regs);

	/* Ready the device for tx/rx */
	startup_tsec(regs);

	return 1;

}


/* Reads from the register at offset in the PHY at phyid, */
/* using the register set defined in regbase.  It waits until the */
/* bits in the miimstat are valid (miimind notvalid bit cleared), */
/* and then passes those bits on to the variable specified in */
/* value */
/* Before it does the read, it needs to clear the command field */
uint read_phy_reg(volatile tsec_t *regbase, uint phyid, uint offset)
{
	uint value;

	/* Put the address of the phy, and the register number into
	 * MIIMADD
	 */
	regbase->miimadd = (phyid << 8) | offset;

	/* Clear the command register, and wait */
	regbase->miimcom = 0;
	asm("msync");

	/* Initiate a read command, and wait */
	regbase->miimcom = MIIM_READ_COMMAND;
	asm("msync");

	/* Wait for the the indication that the read is done */
	while((regbase->miimind & (MIIMIND_NOTVALID | MIIMIND_BUSY)));

	/* Grab the value read from the PHY */
	value = regbase->miimstat;

	return value;
}

/* Setup the PHY */
static void init_phy(volatile tsec_t *regs)
{
	uint testval;
	unsigned int timeout = TSEC_TIMEOUT;

	/* Assign a Physical address to the TBI */
	regs->tbipa=TBIPA_VALUE;

	/* reset the management interface */
	regs->miimcfg=MIIMCFG_RESET;

	regs->miimcfg=MIIMCFG_INIT_VALUE;

	/* Wait until the bus is free */
	while(regs->miimind & MIIMIND_BUSY);

#ifdef CONFIG_PHY_CIS8201
	/* override PHY config settings */
	write_phy_reg(regs, 0, MIIM_AUX_CONSTAT, MIIM_AUXCONSTAT_INIT);

	/* Set up interface mode */
	write_phy_reg(regs, 0, MIIM_EXT_CON1, MIIM_EXTCON1_INIT);
#endif

	/* Set the PHY to gigabit, full duplex, Auto-negotiate */
	write_phy_reg(regs, 0, MIIM_CONTROL, MIIM_CONTROL_INIT);

	/* Wait until TBI_STATUS indicates AN is done */
	DBGPRINT("Waiting for Auto-negotiation to complete\n");
	testval=read_phy_reg(regs, 0, MIIM_TBI_STATUS);

	while((!(testval & MIIM_TBI_STATUS_AN_DONE))&& timeout--) {
		testval=read_phy_reg(regs, 0, MIIM_TBI_STATUS);
	}

	if(testval & MIIM_TBI_STATUS_AN_DONE)
		DBGPRINT("Auto-negotiation done\n");
	else
		DBGPRINT("Auto-negotiation timed-out.\n");

#ifdef CONFIG_PHY_CIS8201
	/* Find out what duplexity (duplicity?) we have */
	/* Read it twice to make sure */
	testval=read_phy_reg(regs, 0, MIIM_AUX_CONSTAT);

	if(testval & MIIM_AUXCONSTAT_DUPLEX) {
		DBGPRINT("Enet starting in full duplex\n");
		regs->maccfg2 |= MACCFG2_FULL_DUPLEX;
	} else {
		DBGPRINT("Enet starting in half duplex\n");
		regs->maccfg2 &= ~MACCFG2_FULL_DUPLEX;
	}

	/* Also, we look to see what speed we are at
	 * if Gigabit, MACCFG2 goes in GMII, otherwise,
	 * MII mode.
	 */
	if((testval & MIIM_AUXCONSTAT_SPEED) != MIIM_AUXCONSTAT_GBIT) {
		if((testval & MIIM_AUXCONSTAT_SPEED) == MIIM_AUXCONSTAT_100)
			DBGPRINT("Enet starting in 100BT\n");
		else
			DBGPRINT("Enet starting in 10BT\n");

		/* mark the mode in MACCFG2 */
		regs->maccfg2 = ((regs->maccfg2&~(MACCFG2_IF)) | MACCFG2_MII);
	} else {
		DBGPRINT("Enet starting in 1000BT\n");
	}

#endif

#ifdef CONFIG_PHY_M88E1011
	/* Read the PHY to see what speed and duplex we are */
	testval=read_phy_reg(regs, 0, MIIM_PHY_STATUS);

	timeout = TSEC_TIMEOUT;
	while((!(testval & MIIM_PHYSTAT_SPDDONE)) && timeout--) {
		testval = read_phy_reg(regs,0,MIIM_PHY_STATUS);
	}

	if(!(testval & MIIM_PHYSTAT_SPDDONE))
		DBGPRINT("Enet: Speed not resolved\n");

	testval=read_phy_reg(regs, 0, MIIM_PHY_STATUS);
	if(testval & MIIM_PHYSTAT_DUPLEX) {
		DBGPRINT("Enet starting in Full Duplex\n");
		regs->maccfg2 |= MACCFG2_FULL_DUPLEX;
	} else {
		DBGPRINT("Enet starting in Half Duplex\n");
		regs->maccfg2 &= ~MACCFG2_FULL_DUPLEX;
	}

	if(!((testval&MIIM_PHYSTAT_SPEED) == MIIM_PHYSTAT_GBIT)) {
		if((testval & MIIM_PHYSTAT_SPEED) == MIIM_PHYSTAT_100)
			DBGPRINT("Enet starting in 100BT\n");
		else
			DBGPRINT("Enet starting in 10BT\n");

		regs->maccfg2 = ((regs->maccfg2&~(MACCFG2_IF)) | MACCFG2_MII);
	} else {
		DBGPRINT("Enet starting in 1000BT\n");
	}
#endif

}


static void init_registers(volatile tsec_t *regs)
{
	/* Clear IEVENT */
	regs->ievent = IEVENT_INIT_CLEAR;

	regs->imask = IMASK_INIT_CLEAR;

	regs->hash.iaddr0 = 0;
	regs->hash.iaddr1 = 0;
	regs->hash.iaddr2 = 0;
	regs->hash.iaddr3 = 0;
	regs->hash.iaddr4 = 0;
	regs->hash.iaddr5 = 0;
	regs->hash.iaddr6 = 0;
	regs->hash.iaddr7 = 0;

	regs->hash.gaddr0 = 0;
	regs->hash.gaddr1 = 0;
	regs->hash.gaddr2 = 0;
	regs->hash.gaddr3 = 0;
	regs->hash.gaddr4 = 0;
	regs->hash.gaddr5 = 0;
	regs->hash.gaddr6 = 0;
	regs->hash.gaddr7 = 0;

	regs->rctrl = 0x00000000;

	/* Init RMON mib registers */
	memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t));

	regs->rmon.cam1 = 0xffffffff;
	regs->rmon.cam2 = 0xffffffff;

	regs->mrblr = MRBLR_INIT_SETTINGS;

	regs->minflr = MINFLR_INIT_SETTINGS;

	regs->attr = ATTR_INIT_SETTINGS;
	regs->attreli = ATTRELI_INIT_SETTINGS;

}

static void startup_tsec(volatile tsec_t *regs)
{
	int i;

	/* Point to the buffer descriptors */
	regs->tbase = (unsigned int)(&rtx.txbd[txIdx]);
	regs->rbase = (unsigned int)(&rtx.rxbd[rxIdx]);

	/* Initialize the Rx Buffer descriptors */
	for (i = 0; i < PKTBUFSRX; i++) {
		rtx.rxbd[i].status = RXBD_EMPTY;
		rtx.rxbd[i].length = 0;
		rtx.rxbd[i].bufPtr = (uint)NetRxPackets[i];
	}
	rtx.rxbd[PKTBUFSRX -1].status |= RXBD_WRAP;

	/* Initialize the TX Buffer Descriptors */
	for(i=0; i<TX_BUF_CNT; i++) {
		rtx.txbd[i].status = 0;
		rtx.txbd[i].length = 0;
		rtx.txbd[i].bufPtr = 0;
	}
	rtx.txbd[TX_BUF_CNT -1].status |= TXBD_WRAP;

	/* Enable Transmit and Receive */
	regs->maccfg1 |= (MACCFG1_RX_EN | MACCFG1_TX_EN);

	/* Tell the DMA it is clear to go */
	regs->dmactrl |= DMACTRL_INIT_SETTINGS;
	regs->tstat = TSTAT_CLEAR_THALT;
	regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
}

/* This returns the status bits of the device.  The return value
 * is never checked, and this is what the 8260 driver did, so we
 * do the same.  Presumably, this would be zero if there were no
 * errors */
static int tsec_send(struct eth_device* dev, volatile void *packet, int length)
{
	int i;
	int result = 0;
	volatile tsec_t * regs = (volatile tsec_t *)(TSEC_BASE_ADDR);

	/* Find an empty buffer descriptor */
	for(i=0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
		if (i >= TOUT_LOOP) {
			DBGPRINT("tsec: tx buffers full\n");
			return result;
		}
	}

	rtx.txbd[txIdx].bufPtr = (uint)packet;
	rtx.txbd[txIdx].length = length;
	rtx.txbd[txIdx].status |= (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT);

	/* Tell the DMA to go */
	regs->tstat = TSTAT_CLEAR_THALT;

	/* Wait for buffer to be transmitted */
	for(i=0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
		if (i >= TOUT_LOOP) {
			DBGPRINT("tsec: tx error\n");
			return result;
		}
	}

	txIdx = (txIdx + 1) % TX_BUF_CNT;
	result = rtx.txbd[txIdx].status & TXBD_STATS;

	return result;
}

static int tsec_recv(struct eth_device* dev)
{
	int length;
	volatile tsec_t *regs = (volatile tsec_t *)(TSEC_BASE_ADDR);

	while(!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) {

		length = rtx.rxbd[rxIdx].length;

		/* Send the packet up if there were no errors */
		if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) {
			NetReceive(NetRxPackets[rxIdx], length - 4);
		}

		rtx.rxbd[rxIdx].length = 0;

		/* Set the wrap bit if this is the last element in the list */
		rtx.rxbd[rxIdx].status = RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0);

		rxIdx = (rxIdx + 1) % PKTBUFSRX;
	}

	if(regs->ievent&IEVENT_BSY) {
		regs->ievent = IEVENT_BSY;
		regs->rstat = RSTAT_CLEAR_RHALT;
	}

	return -1;

}


static void tsec_halt(struct eth_device* dev)
{
	volatile tsec_t *regs = (volatile tsec_t *)(TSEC_BASE_ADDR);

	regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
	regs->dmactrl |= (DMACTRL_GRS | DMACTRL_GTS);

	while(!(regs->ievent & (IEVENT_GRSC | IEVENT_GTSC)));

	regs->maccfg1 &= ~(MACCFG1_TX_EN | MACCFG1_RX_EN);

}
#endif /* CONFIG_TSEC_ENET */
