/*
 * SMSC LAN9[12]1[567] Network driver
 *
 * (c) 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * 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 <command.h>
#include <net.h>
#include <miiphy.h>

#include "smc911x.h"

u32 pkt_data_pull(u32 addr) \
	__attribute__ ((weak, alias ("smc911x_reg_read")));
void pkt_data_push(u32 addr, u32 val) \
	__attribute__ ((weak, alias ("smc911x_reg_write")));

#define mdelay(n)       udelay((n)*1000)

static int smx911x_handle_mac_address(bd_t *bd)
{
	unsigned long addrh, addrl;
	unsigned char *m = bd->bi_enetaddr;

	/* if the environment has a valid mac address then use it */
	if ((m[0] | m[1] | m[2] | m[3] | m[4] | m[5])) {
		addrl = m[0] | m[1] << 8 | m[2] << 16 | m[3] << 24;
		addrh = m[4] | m[5] << 8;
		smc911x_set_mac_csr(ADDRH, addrh);
		smc911x_set_mac_csr(ADDRL, addrl);
	} else {
		/* if not, try to get one from the eeprom */
		addrh = smc911x_get_mac_csr(ADDRH);
		addrl = smc911x_get_mac_csr(ADDRL);

		m[0] = (addrl       ) & 0xff;
		m[1] = (addrl >>  8 ) & 0xff;
		m[2] = (addrl >> 16 ) & 0xff;
		m[3] = (addrl >> 24 ) & 0xff;
		m[4] = (addrh       ) & 0xff;
		m[5] = (addrh >>  8 ) & 0xff;

		/* we get 0xff when there is no eeprom connected */
		if ((m[0] & m[1] & m[2] & m[3] & m[4] & m[5]) == 0xff) {
			printf(DRIVERNAME ": no valid mac address in environment "
				"and no eeprom found\n");
			return -1;
		}
	}

	printf(DRIVERNAME ": MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
		m[0], m[1], m[2], m[3], m[4], m[5]);

	return 0;
}

static int smc911x_miiphy_read(u8 phy, u8 reg, u16 *val)
{
	while (smc911x_get_mac_csr(MII_ACC) & MII_ACC_MII_BUSY)
		;

	smc911x_set_mac_csr(MII_ACC, phy << 11 | reg << 6 | MII_ACC_MII_BUSY);

	while (smc911x_get_mac_csr(MII_ACC) & MII_ACC_MII_BUSY)
		;

	*val = smc911x_get_mac_csr(MII_DATA);

	return 0;
}

static int smc911x_miiphy_write(u8 phy, u8 reg, u16  val)
{
	while (smc911x_get_mac_csr(MII_ACC) & MII_ACC_MII_BUSY)
		;

	smc911x_set_mac_csr(MII_DATA, val);
	smc911x_set_mac_csr(MII_ACC,
		phy << 11 | reg << 6 | MII_ACC_MII_BUSY | MII_ACC_MII_WRITE);

	while (smc911x_get_mac_csr(MII_ACC) & MII_ACC_MII_BUSY)
		;
	return 0;
}

static int smc911x_phy_reset(void)
{
	u32 reg;

	reg = smc911x_reg_read(PMT_CTRL);
	reg &= ~0xfffff030;
	reg |= PMT_CTRL_PHY_RST;
	smc911x_reg_write(PMT_CTRL, reg);

	mdelay(100);

	return 0;
}

static void smc911x_phy_configure(void)
{
	int timeout;
	u16 status;

	smc911x_phy_reset();

	smc911x_miiphy_write(1, PHY_BMCR, PHY_BMCR_RESET);
	mdelay(1);
	smc911x_miiphy_write(1, PHY_ANAR, 0x01e1);
	smc911x_miiphy_write(1, PHY_BMCR, PHY_BMCR_AUTON | PHY_BMCR_RST_NEG);

	timeout = 5000;
	do {
		mdelay(1);
		if ((timeout--) == 0)
			goto err_out;

		if (smc911x_miiphy_read(1, PHY_BMSR, &status) != 0)
			goto err_out;
	} while (!(status & PHY_BMSR_LS));

	printf(DRIVERNAME ": phy initialized\n");

	return;

err_out:
	printf(DRIVERNAME ": autonegotiation timed out\n");
}

static void smc911x_enable(void)
{
	/* Enable TX */
	smc911x_reg_write(HW_CFG, 8 << 16 | HW_CFG_SF);

	smc911x_reg_write(GPT_CFG, GPT_CFG_TIMER_EN | 10000);

	smc911x_reg_write(TX_CFG, TX_CFG_TX_ON);

	/* no padding to start of packets */
	smc911x_reg_write(RX_CFG, 0);

	smc911x_set_mac_csr(MAC_CR, MAC_CR_TXEN | MAC_CR_RXEN | MAC_CR_HBDIS);

}

int eth_init(bd_t *bd)
{
	printf(DRIVERNAME ": initializing\n");

	if (smc911x_detect_chip())
		goto err_out;

	smc911x_reset();

	/* Configure the PHY, initialize the link state */
	smc911x_phy_configure();

	if (smx911x_handle_mac_address(bd))
		goto err_out;

	/* Turn on Tx + Rx */
	smc911x_enable();

	return 0;

err_out:
	return -1;
}

int eth_send(volatile void *packet, int length)
{
	u32 *data = (u32*)packet;
	u32 tmplen;
	u32 status;

	smc911x_reg_write(TX_DATA_FIFO, TX_CMD_A_INT_FIRST_SEG | TX_CMD_A_INT_LAST_SEG | length);
	smc911x_reg_write(TX_DATA_FIFO, length);

	tmplen = (length + 3) / 4;

	while (tmplen--)
		pkt_data_push(TX_DATA_FIFO, *data++);

	/* wait for transmission */
	while (!((smc911x_reg_read(TX_FIFO_INF) & TX_FIFO_INF_TSUSED) >> 16));

	/* get status. Ignore 'no carrier' error, it has no meaning for
	 * full duplex operation
	 */
	status = smc911x_reg_read(TX_STATUS_FIFO) & (TX_STS_LOC | TX_STS_LATE_COLL |
		TX_STS_MANY_COLL | TX_STS_MANY_DEFER | TX_STS_UNDERRUN);

	if (!status)
		return 0;

	printf(DRIVERNAME ": failed to send packet: %s%s%s%s%s\n",
		status & TX_STS_LOC ? "TX_STS_LOC " : "",
		status & TX_STS_LATE_COLL ? "TX_STS_LATE_COLL " : "",
		status & TX_STS_MANY_COLL ? "TX_STS_MANY_COLL " : "",
		status & TX_STS_MANY_DEFER ? "TX_STS_MANY_DEFER " : "",
		status & TX_STS_UNDERRUN ? "TX_STS_UNDERRUN" : "");

	return -1;
}

void eth_halt(void)
{
	smc911x_reset();
}

int eth_rx(void)
{
	u32 *data = (u32 *)NetRxPackets[0];
	u32 pktlen, tmplen;
	u32 status;

	if ((smc911x_reg_read(RX_FIFO_INF) & RX_FIFO_INF_RXSUSED) >> 16) {
		status = smc911x_reg_read(RX_STATUS_FIFO);
		pktlen = (status & RX_STS_PKT_LEN) >> 16;

		smc911x_reg_write(RX_CFG, 0);

		tmplen = (pktlen + 2+ 3) / 4;
		while (tmplen--)
			*data++ = pkt_data_pull(RX_DATA_FIFO);

		if (status & RX_STS_ES)
			printf(DRIVERNAME
				": dropped bad packet. Status: 0x%08x\n",
				status);
		else
			NetReceive(NetRxPackets[0], pktlen);
	}

	return 0;
}
