/*
 * PLB2800 internal switch ethernet driver.
 *
 * (C) Copyright 2003
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <malloc.h>
#include <net.h>
#include <netdev.h>
#include <asm/addrspace.h>


#define NUM_RX_DESC	PKTBUFSRX
#define TOUT_LOOP	1000000

#define LONG_REF(addr) (*((volatile unsigned long*)addr))

#define CMAC_CRX_CTRL	LONG_REF(0xb800c870)
#define CMAC_CTX_CTRL	LONG_REF(0xb800c874)
#define SYS_MAC_ADDR_0	LONG_REF(0xb800c878)
#define SYS_MAC_ADDR_1	LONG_REF(0xb800c87c)
#define MIPS_H_MASK	LONG_REF(0xB800C810)

#define MA_LEARN	LONG_REF(0xb8008004)
#define DA_LOOKUP	LONG_REF(0xb8008008)

#define CMAC_CRX_CTRL_PD	0x00000001
#define CMAC_CRX_CTRL_CG	0x00000002
#define CMAC_CRX_CTRL_PL_SHIFT	2
#define CMAC_CRIT		0x0
#define CMAC_NON_CRIT		0x1
#define MBOX_STAT_ID_SHF	28
#define MBOX_STAT_CP		0x80000000
#define MBOX_STAT_MB		0x00000001
#define EN_MA_LEARN		0x02000000
#define EN_DA_LKUP		0x01000000
#define MA_DEST_SHF		11
#define DA_DEST_SHF		11
#define DA_STATE_SHF		19
#define TSTAMP_MS		0x00000000
#define SW_H_MBOX4_MASK		0x08000000
#define SW_H_MBOX3_MASK		0x04000000
#define SW_H_MBOX2_MASK		0x02000000
#define SW_H_MBOX1_MASK		0x01000000

typedef volatile struct {
  unsigned int stat;
  unsigned int cmd;
  unsigned int cnt;
  unsigned int adr;
} mailbox_t;

#define MBOX_REG(mb) ((mailbox_t*)(0xb800c830+(mb<<4)))

typedef volatile struct {
  unsigned int word0;
  unsigned int word1;
  unsigned int word2;
} mbhdr_t;

#define MBOX_MEM(mb) ((void*)(0xb800a000+((3-mb)<<11)))


static int plb2800_eth_init(struct eth_device *dev, bd_t * bis);
static int plb2800_eth_send(struct eth_device *dev, void *packet, int length);
static int plb2800_eth_recv(struct eth_device *dev);
static void plb2800_eth_halt(struct eth_device *dev);

static void plb2800_set_mac_addr(struct eth_device *dev, unsigned char * addr);
static unsigned char * plb2800_get_mac_addr(void);

static int rx_new;
static int mac_addr_set = 0;


int plb2800_eth_initialize(bd_t * bis)
{
	struct eth_device *dev;
	ulong temp;

#ifdef DEBUG
	printf("Entered plb2800_eth_initialize()\n");
#endif

	if (!(dev = (struct eth_device *) malloc (sizeof *dev)))
	{
		printf("Failed to allocate memory\n");
		return -1;
	}
	memset(dev, 0, sizeof(*dev));

	sprintf(dev->name, "PLB2800 Switch");
	dev->init = plb2800_eth_init;
	dev->halt = plb2800_eth_halt;
	dev->send = plb2800_eth_send;
	dev->recv = plb2800_eth_recv;

	eth_register(dev);

	/* bug fix */
	*(ulong *)0xb800e800 = 0x838;

	/* Set MBOX ownership */
	temp = CMAC_CRIT << MBOX_STAT_ID_SHF;
	MBOX_REG(0)->stat = temp;
	MBOX_REG(1)->stat = temp;

	temp = CMAC_NON_CRIT << MBOX_STAT_ID_SHF;
	MBOX_REG(2)->stat = temp;
	MBOX_REG(3)->stat = temp;

	plb2800_set_mac_addr(dev, plb2800_get_mac_addr());

	/* Disable all Mbox interrupt */
	temp = MIPS_H_MASK;
	temp &= ~ (SW_H_MBOX1_MASK | SW_H_MBOX2_MASK | SW_H_MBOX3_MASK | SW_H_MBOX4_MASK) ;
	MIPS_H_MASK = temp;

#ifdef DEBUG
	printf("Leaving plb2800_eth_initialize()\n");
#endif

	return 0;
}

static int plb2800_eth_init(struct eth_device *dev, bd_t * bis)
{
#ifdef DEBUG
	printf("Entering plb2800_eth_init()\n");
#endif

	plb2800_set_mac_addr(dev, dev->enetaddr);

	rx_new = 0;

#ifdef DEBUG
	printf("Leaving plb2800_eth_init()\n");
#endif

	return 0;
}


static int plb2800_eth_send(struct eth_device *dev, void *packet, int length)
{
	int                    i;
	int                    res         = -1;
	u32                    temp;
	mailbox_t *            mb          = MBOX_REG(0);
	char      *            mem         = MBOX_MEM(0);

#ifdef DEBUG
	printf("Entered plb2800_eth_send()\n");
#endif

	if (length <= 0)
	{
		printf ("%s: bad packet size: %d\n", dev->name, length);
		goto Done;
	}

	if (length < 64)
	{
		length = 64;
	}

	temp = CMAC_CRX_CTRL_CG | ((length + 4) << CMAC_CRX_CTRL_PL_SHIFT);

#ifdef DEBUG
	printf("0 mb->stat = 0x%x\n",  mb->stat);
#endif

	for(i = 0; mb->stat & (MBOX_STAT_CP | MBOX_STAT_MB); i++)
	{
		if (i >= TOUT_LOOP)
		{
			printf("%s: tx buffer not ready\n", dev->name);
			printf("1 mb->stat = 0x%x\n",  mb->stat);
			goto Done;
		}
	}

		/* For some strange reason, memcpy doesn't work, here!
		 */
	do
	{
		int words = (length >> 2) + 1;
		unsigned int* dst = (unsigned int*)(mem);
		unsigned int* src = (unsigned int*)(packet);
		for (i = 0; i < words; i++)
		{
			*dst = *src;
			dst++;
			src++;
		};
	} while(0);

	CMAC_CRX_CTRL = temp;
	mb->cmd = MBOX_STAT_CP;

#ifdef DEBUG
	printf("2 mb->stat = 0x%x\n",  mb->stat);
#endif

	res = length;
Done:

#ifdef DEBUG
	printf("Leaving plb2800_eth_send()\n");
#endif

	return res;
}


static int plb2800_eth_recv(struct eth_device *dev)
{
	int                    length  = 0;
	mailbox_t            * mbox    = MBOX_REG(3);
	unsigned char        * hdr     = MBOX_MEM(3);
	unsigned int           stat;

#ifdef DEBUG
	printf("Entered plb2800_eth_recv()\n");
#endif

	for (;;)
	{
		stat = mbox->stat;

		if (!(stat & MBOX_STAT_CP))
		{
			break;
		}

		length = ((*(hdr + 6) & 0x3f) << 8) + *(hdr + 7);
		memcpy((void *)NetRxPackets[rx_new], hdr + 12, length);

		stat &= ~MBOX_STAT_CP;
		mbox->stat = stat;
#ifdef DEBUG
		{
			int i;
			for (i=0;i<length - 4;i++)
			{
				if (i % 16 == 0) printf("\n%04x: ", i);
				printf("%02X ", NetRxPackets[rx_new][i]);
			}
			printf("\n");
		}
#endif

		if (length)
		{
#ifdef DEBUG
			printf("Received %d bytes\n", length);
#endif
			NetReceive((void*)(NetRxPackets[rx_new]),
				    length - 4);
		}
		else
		{
#if 1
			printf("Zero length!!!\n");
#endif
		}

		rx_new = (rx_new + 1) % NUM_RX_DESC;
	}

#ifdef DEBUG
	printf("Leaving plb2800_eth_recv()\n");
#endif

	return length;
}


static void plb2800_eth_halt(struct eth_device *dev)
{
#ifdef DEBUG
	printf("Entered plb2800_eth_halt()\n");
#endif

#ifdef DEBUG
	printf("Leaving plb2800_eth_halt()\n");
#endif
}

static void plb2800_set_mac_addr(struct eth_device *dev, unsigned char * addr)
{
	char packet[60];
	ulong temp;
	int ix;

	if (mac_addr_set ||
	    NULL == addr || memcmp(addr, "\0\0\0\0\0\0", 6) == 0)
	{
		return;
	}

	/* send one packet through CPU port
	 * in order to learn system MAC address
	 */

	/* Set DA_LOOKUP register */
	temp = EN_MA_LEARN | (0 << DA_STATE_SHF) | (63 << DA_DEST_SHF);
	DA_LOOKUP = temp;

	/* Set MA_LEARN register */
	temp = 50 << MA_DEST_SHF;	/* static entry */
	MA_LEARN = temp;

	/* set destination address */
	for (ix=0;ix<6;ix++)
		packet[ix] = 0xff;

	/* set source address = system MAC address */
	for (ix=0;ix<6;ix++)
		packet[6+ix] = addr[ix];

	/* set type field */
	packet[12]=0xaa;
	packet[13]=0x55;

	/* set data field */
	for(ix=14;ix<60;ix++)
		packet[ix] = 0x00;

#ifdef DEBUG
	for (ix=0;ix<6;ix++)
		printf("mac_addr[%d]=%02X\n", ix, (unsigned char)packet[6+ix]);
#endif

	/* set one packet */
	plb2800_eth_send(dev, packet, sizeof(packet));

	/* delay for a while */
	for(ix=0;ix<65535;ix++)
		temp = ~temp;

	/* Set CMAC_CTX_CTRL register */
	temp = TSTAMP_MS;	/* no autocast */
	CMAC_CTX_CTRL = temp;

	/* Set DA_LOOKUP register */
	temp = EN_DA_LKUP;
	DA_LOOKUP = temp;

	mac_addr_set = 1;
}

static unsigned char * plb2800_get_mac_addr(void)
{
	static unsigned char addr[6];
	char *tmp, *end;
	int i;

	tmp = getenv ("ethaddr");
	if (NULL == tmp) return NULL;

	for (i=0; i<6; i++) {
		addr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0;
		if (tmp)
			tmp = (*end) ? end+1 : end;
	}

	return addr;
}
