/*
 * (C) Copyright 2007
 * Stefan Roese, DENX Software Engineering, sr@denx.de.
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <config.h>
#include <common.h>
#include <command.h>
#include <i2c.h>
#include <miiphy.h>

#ifdef CONFIG_TAISHAN

#define LCD_DELAY_NORMAL_US	100
#define LCD_DELAY_NORMAL_MS	2
#define LCD_CMD_ADDR		((volatile char *)(CONFIG_SYS_EBC2_LCM_BASE))
#define LCD_DATA_ADDR		((volatile char *)(CONFIG_SYS_EBC2_LCM_BASE+1))
#define LCD_BLK_CTRL		((volatile char *)(CONFIG_SYS_EBC1_FPGA_BASE+0x2))

static int g_lcd_init_b = 0;
static char *amcc_logo = "  AMCC TAISHAN  440GX EvalBoard";
static char addr_flag = 0x80;

static void lcd_bl_ctrl(char val)
{
	char cpld_val;

	cpld_val = *LCD_BLK_CTRL;
	*LCD_BLK_CTRL = val | cpld_val;
}

static void lcd_putc(char val)
{
	int i = 100;
	char addr;

	while (i--) {
		if ((*LCD_CMD_ADDR & 0x80) != 0x80) {	/*BF = 1 ? */
			udelay(LCD_DELAY_NORMAL_US);
			break;
		}
		udelay(LCD_DELAY_NORMAL_US);
	}

	if (*LCD_CMD_ADDR & 0x80) {
		printf("LCD is busy\n");
		return;
	}

	addr = *LCD_CMD_ADDR;
	udelay(LCD_DELAY_NORMAL_US);
	if ((addr != 0) && (addr % 0x10 == 0)) {
		addr_flag ^= 0x40;
		*LCD_CMD_ADDR = addr_flag;
	}

	udelay(LCD_DELAY_NORMAL_US);
	*LCD_DATA_ADDR = val;
	udelay(LCD_DELAY_NORMAL_US);
}

static void lcd_puts(char *s)
{
	char *p = s;
	int i = 100;

	while (i--) {
		if ((*LCD_CMD_ADDR & 0x80) != 0x80) {	/*BF = 1 ? */
			udelay(LCD_DELAY_NORMAL_US);
			break;
		}
		udelay(LCD_DELAY_NORMAL_US);
	}

	if (*LCD_CMD_ADDR & 0x80) {
		printf("LCD is busy\n");
		return;
	}

	while (*p)
		lcd_putc(*p++);
}

static void lcd_put_logo(void)
{
	int i = 100;
	char *p = amcc_logo;

	while (i--) {
		if ((*LCD_CMD_ADDR & 0x80) != 0x80) {	/*BF = 1 ? */
			udelay(LCD_DELAY_NORMAL_US);
			break;
		}
		udelay(LCD_DELAY_NORMAL_US);
	}

	if (*LCD_CMD_ADDR & 0x80) {
		printf("LCD is busy\n");
		return;
	}

	*LCD_CMD_ADDR = 0x80;
	while (*p)
		lcd_putc(*p++);
}

int lcd_init(void)
{
	if (g_lcd_init_b == 0) {
		puts("LCD: ");
		mdelay(100);	/* Waiting for the LCD initialize */

		*LCD_CMD_ADDR = 0x38;	/*set function:8-bit,2-line,5x7 font type */
		udelay(LCD_DELAY_NORMAL_US);

		*LCD_CMD_ADDR = 0x0f;	/*set display on,cursor on,blink on */
		udelay(LCD_DELAY_NORMAL_US);

		*LCD_CMD_ADDR = 0x01;	/*display clear */
		mdelay(LCD_DELAY_NORMAL_MS);

		*LCD_CMD_ADDR = 0x06;	/*set entry */
		udelay(LCD_DELAY_NORMAL_US);

		lcd_bl_ctrl(0x02);
		lcd_put_logo();

		puts("  ready\n");
		g_lcd_init_b = 1;
	}

	return 0;
}

static int do_lcd_test(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
	lcd_init();
	return 0;
}

static int do_lcd_clear(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
	*LCD_CMD_ADDR = 0x01;
	mdelay(LCD_DELAY_NORMAL_MS);
	return 0;
}
static int do_lcd_puts(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
	if (argc < 2)
		return cmd_usage(cmdtp);

	lcd_puts(argv[1]);
	return 0;
}
static int do_lcd_putc(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
	if (argc < 2)
		return cmd_usage(cmdtp);

	lcd_putc((char)argv[1][0]);
	return 0;
}
static int do_lcd_cur(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
	ulong count;
	ulong dir;
	char cur_addr;

	if (argc < 3)
		return cmd_usage(cmdtp);

	count = simple_strtoul(argv[1], NULL, 16);
	if (count > 31) {
		printf("unable to shift > 0x20\n");
		count = 0;
	}

	dir = simple_strtoul(argv[2], NULL, 16);
	cur_addr = *LCD_CMD_ADDR;
	udelay(LCD_DELAY_NORMAL_US);
	if (dir == 0x0) {
		if (addr_flag == 0x80) {
			if (count >= (cur_addr & 0xf)) {
				*LCD_CMD_ADDR = 0x80;
				udelay(LCD_DELAY_NORMAL_US);
				count = 0;
			}
		} else {
			if (count >= ((cur_addr & 0x0f) + 0x0f)) {
				*LCD_CMD_ADDR = 0x80;
				addr_flag = 0x80;
				udelay(LCD_DELAY_NORMAL_US);
				count = 0x0;
			} else if (count >= (cur_addr & 0xf)) {
				count -= cur_addr & 0xf;
				*LCD_CMD_ADDR = 0x80 | 0xf;
				addr_flag = 0x80;
				udelay(LCD_DELAY_NORMAL_US);
			}
		}
	} else {
		if (addr_flag == 0x80) {
			if (count >= (0x1f - (cur_addr & 0xf))) {
				count = 0x0;
				addr_flag = 0xc0;
				*LCD_CMD_ADDR = 0xc0 | 0xf;
				udelay(LCD_DELAY_NORMAL_US);
			} else if ((count + (cur_addr & 0xf)) >= 0x0f) {
				count = count + (cur_addr & 0xf) - 0x0f;
				addr_flag = 0xc0;
				*LCD_CMD_ADDR = 0xc0;
				udelay(LCD_DELAY_NORMAL_US);
			}
		} else if ((count + (cur_addr & 0xf)) >= 0x0f) {
			count = 0x0;
			*LCD_CMD_ADDR = 0xc0 | 0xf;
			udelay(LCD_DELAY_NORMAL_US);
		}
	}

	while (count--) {
		if (dir == 0) {
			*LCD_CMD_ADDR = 0x10;
		} else {
			*LCD_CMD_ADDR = 0x14;
		}
		udelay(LCD_DELAY_NORMAL_US);
	}

	return 0;
}

U_BOOT_CMD(lcd_test, 1, 1, do_lcd_test, "lcd test display", "");
U_BOOT_CMD(lcd_cls, 1, 1, do_lcd_clear, "lcd clear display", "");
U_BOOT_CMD(lcd_puts, 2, 1, do_lcd_puts,
	   "display string on lcd",
	   "<string> - <string> to be displayed");
U_BOOT_CMD(lcd_putc, 2, 1, do_lcd_putc,
	   "display char on lcd",
	   "<char> - <char> to be displayed");
U_BOOT_CMD(lcd_cur, 3, 1, do_lcd_cur,
	   "shift cursor on lcd",
	   "<count> <dir>- shift cursor on lcd <count> times, direction is <dir> \n"
	   " <count> - 0~31\n" " <dir> - 0,backward; 1, forward");

#if 0 /* test-only */
void set_phy_loopback_mode(void)
{
	char devemac2[32];
	char devemac3[32];

	sprintf(devemac2, "%s2", CONFIG_EMAC_DEV_NAME);
	sprintf(devemac3, "%s3", CONFIG_EMAC_DEV_NAME);

#if 0
	unsigned short reg_short;

	miiphy_read(devemac2, 0x1, 1, &reg_short);
	if (reg_short & 0x04) {
		/*
		 * printf("EMAC2 link up,do nothing\n");
		 */
	} else {
		udelay(1000);
		miiphy_write(devemac2, 0x1, 0, 0x6000);
		udelay(1000);
		miiphy_read(devemac2, 0x1, 0, &reg_short);
		if (reg_short != 0x6000) {
			printf
			    ("\nEMAC2 error set LOOPBACK mode error,reg2[0]=%x\n",
			     reg_short);
		}
	}

	miiphy_read(devemac3, 0x3, 1, &reg_short);
	if (reg_short & 0x04) {
		/*
		 * printf("EMAC3 link up,do nothing\n");
		 */
	} else {
		udelay(1000);
		miiphy_write(devemac3, 0x3, 0, 0x6000);
		udelay(1000);
		miiphy_read(devemac3, 0x3, 0, &reg_short);
		if (reg_short != 0x6000) {
			printf
			    ("\nEMAC3 error set LOOPBACK mode error,reg2[0]=%x\n",
			     reg_short);
		}
	}
#else
	/* Set PHY as LOOPBACK MODE, for Linux emac initializing */
	miiphy_write(devemac2, CONFIG_PHY2_ADDR, 0, 0x6000);
	udelay(1000);
	miiphy_write(devemac3, CONFIG_PHY3_ADDR, 0, 0x6000);
	udelay(1000);
#endif	/* 0 */
}

void set_phy_normal_mode(void)
{
	char devemac2[32];
	char devemac3[32];
	unsigned short reg_short;

	sprintf(devemac2, "%s2", CONFIG_EMAC_DEV_NAME);
	sprintf(devemac3, "%s3", CONFIG_EMAC_DEV_NAME);

	/* Set phy of EMAC2 */
	miiphy_read(devemac2, CONFIG_PHY2_ADDR, 0x16, &reg_short);
	reg_short &= ~(0x7);
	reg_short |= 0x6;	/* RGMII DLL Delay */
	miiphy_write(devemac2, CONFIG_PHY2_ADDR, 0x16, reg_short);

	miiphy_read(devemac2, CONFIG_PHY2_ADDR, 0x17, &reg_short);
	reg_short &= ~(0x40);
	miiphy_write(devemac2, CONFIG_PHY2_ADDR, 0x17, reg_short);

	miiphy_write(devemac2, CONFIG_PHY2_ADDR, 0x1c, 0x74f0);

	/* Set phy of EMAC3 */
	miiphy_read(devemac3, CONFIG_PHY3_ADDR, 0x16, &reg_short);
	reg_short &= ~(0x7);
	reg_short |= 0x6;	/* RGMII DLL Delay */
	miiphy_write(devemac3, CONFIG_PHY3_ADDR, 0x16, reg_short);

	miiphy_read(devemac3, CONFIG_PHY3_ADDR, 0x17, &reg_short);
	reg_short &= ~(0x40);
	miiphy_write(devemac3, CONFIG_PHY3_ADDR, 0x17, reg_short);

	miiphy_write(devemac3, CONFIG_PHY3_ADDR, 0x1c, 0x74f0);
}
#endif	/* 0 - test only */

static int do_led_test_off(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
	volatile unsigned int *GpioOr =
		(volatile unsigned int *)(CONFIG_SYS_PERIPHERAL_BASE + 0x700);
	*GpioOr |= 0x00300000;
	return 0;
}

static int do_led_test_on(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
	volatile unsigned int *GpioOr =
		(volatile unsigned int *)(CONFIG_SYS_PERIPHERAL_BASE + 0x700);
	*GpioOr &= ~0x00300000;
	return 0;
}

U_BOOT_CMD(ledon, 1, 1, do_led_test_on,
	   "led test light on", "");

U_BOOT_CMD(ledoff, 1, 1, do_led_test_off,
	   "led test light off", "");
#endif
