/*
 * board/eva/phantom.c
 *
 * Phantom RTC device driver for EVA
 *
 * Author: Sangmoon Kim
 *         dogoil@etinsys.com
 *
 * Copyright 2002 Etinsys Inc.
 *
 * 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.
 */

#include <common.h>
#include <command.h>
#include <rtc.h>

#if (CONFIG_COMMANDS & CFG_CMD_DATE)

#define RTC_BASE (CFG_NVRAM_BASE_ADDR + 0x7fff8)

#define RTC_YEAR                ( RTC_BASE + 7 )
#define RTC_MONTH               ( RTC_BASE + 6 )
#define RTC_DAY_OF_MONTH        ( RTC_BASE + 5 )
#define RTC_DAY_OF_WEEK         ( RTC_BASE + 4 )
#define RTC_HOURS               ( RTC_BASE + 3 )
#define RTC_MINUTES             ( RTC_BASE + 2 )
#define RTC_SECONDS             ( RTC_BASE + 1 )
#define RTC_CENTURY             ( RTC_BASE + 0 )

#define RTC_CONTROLA            RTC_CENTURY
#define RTC_CONTROLB            RTC_SECONDS
#define RTC_CONTROLC            RTC_DAY_OF_WEEK

#define RTC_CA_WRITE            0x80
#define RTC_CA_READ             0x40

#define RTC_CB_OSC_DISABLE      0x80

#define RTC_CC_BATTERY_FLAG     0x80
#define RTC_CC_FREQ_TEST        0x40


static int phantom_flag = -1;
static int century_flag = -1;

static uchar rtc_read(unsigned int addr)
{
	return *(volatile unsigned char *)(addr);
}

static void rtc_write(unsigned int addr, uchar val)
{
	*(volatile unsigned char *)(addr) = val;
}

static unsigned char phantom_rtc_sequence[] = {
	0xc5, 0x3a, 0xa3, 0x5c, 0xc5, 0x3a, 0xa3, 0x5c
};

static unsigned char* phantom_rtc_read(int addr, unsigned char rtc[8])
{
	int i, j;
	unsigned char v;
	unsigned char save = rtc_read(addr);

	for (j = 0; j < 8; j++) {
		v = phantom_rtc_sequence[j];
		for (i = 0; i < 8; i++) {
			rtc_write(addr, v & 1);
			v >>= 1;
		}
	}
	for (j = 0; j < 8; j++) {
		v = 0;
		for (i = 0; i < 8; i++) {
			if(rtc_read(addr) & 1)
				v |= 1 << i;
		}
		rtc[j] = v;
	}
	rtc_write(addr, save);
	return rtc;
}

static void phantom_rtc_write(int addr, unsigned char rtc[8])
{
	int i, j;
	unsigned char v;
	unsigned char save = rtc_read(addr);
	for (j = 0; j < 8; j++) {
		v = phantom_rtc_sequence[j];
		for (i = 0; i < 8; i++) {
			rtc_write(addr, v & 1);
			v >>= 1;
		}
	}
	for (j = 0; j < 8; j++) {
		v = rtc[j];
		for (i = 0; i < 8; i++) {
			rtc_write(addr, v & 1);
			v >>= 1;
		}
	}
	rtc_write(addr, save);
}

static int get_phantom_flag(void)
{
	int i;
	unsigned char rtc[8];

	phantom_rtc_read(RTC_BASE, rtc);

	for(i = 1; i < 8; i++) {
		if (rtc[i] != rtc[0])
			return 1;
	}
	return 0;
}

void rtc_reset(void)
{
	if (phantom_flag < 0)
		phantom_flag = get_phantom_flag();

	if (phantom_flag) {
		unsigned char rtc[8];
		phantom_rtc_read(RTC_BASE, rtc);
		if(rtc[4] & 0x30) {
			printf( "real-time-clock was stopped. Now starting...\n" );
			rtc[4] &= 0x07;
			phantom_rtc_write(RTC_BASE, rtc);
		}
	} else {
		uchar reg_a, reg_b, reg_c;
		reg_a = rtc_read( RTC_CONTROLA );
		reg_b = rtc_read( RTC_CONTROLB );

		if ( reg_b & RTC_CB_OSC_DISABLE )
		{
			printf( "real-time-clock was stopped. Now starting...\n" );
			reg_a |= RTC_CA_WRITE;
			reg_b &= ~RTC_CB_OSC_DISABLE;
			rtc_write( RTC_CONTROLA, reg_a );
			rtc_write( RTC_CONTROLB, reg_b );
		}

		/* make sure read/write clock register bits are cleared */
		reg_a &= ~( RTC_CA_WRITE | RTC_CA_READ );
		rtc_write( RTC_CONTROLA, reg_a );

		reg_c = rtc_read( RTC_CONTROLC );
		if (( reg_c & RTC_CC_BATTERY_FLAG ) == 0 )
			printf( "RTC battery low. Clock setting may not be reliable.\n");
	}
}

inline unsigned bcd2bin (uchar n)
{
	return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
}

inline unsigned char bin2bcd (unsigned int n)
{
	return (((n / 10) << 4) | (n % 10));
}

static int get_century_flag(void)
{
	int flag = 0;
	int bcd, century;
	bcd = rtc_read( RTC_CENTURY );
	century = bcd2bin( bcd & 0x3F );
	rtc_write( RTC_CENTURY, bin2bcd(century+1));
	if (bcd == rtc_read( RTC_CENTURY ))
		flag = 1;
	rtc_write( RTC_CENTURY, bcd);
	return flag;
}

void rtc_get( struct rtc_time *tmp)
{
	if (phantom_flag < 0)
		phantom_flag = get_phantom_flag();

	if (phantom_flag)
	{
		unsigned char rtc[8];

		phantom_rtc_read(RTC_BASE, rtc);

		tmp->tm_sec	= bcd2bin(rtc[1] & 0x7f);
		tmp->tm_min	= bcd2bin(rtc[2] & 0x7f);
		tmp->tm_hour	= bcd2bin(rtc[3] & 0x1f);
		tmp->tm_wday	= bcd2bin(rtc[4] & 0x7);
		tmp->tm_mday	= bcd2bin(rtc[5] & 0x3f);
		tmp->tm_mon	= bcd2bin(rtc[6] & 0x1f);
		tmp->tm_year	= bcd2bin(rtc[7]) + 1900;
		tmp->tm_yday = 0;
		tmp->tm_isdst = 0;

		if( (rtc[3] & 0x80)  && (rtc[3] & 0x40) ) tmp->tm_hour += 12;
		if (tmp->tm_year < 1970) tmp->tm_year += 100;
	} else {
		uchar sec, min, hour;
		uchar mday, wday, mon, year;

		int century;

		uchar reg_a;

		if (century_flag < 0)
			century_flag = get_century_flag();

		reg_a = rtc_read( RTC_CONTROLA );
		/* lock clock registers for read */
		rtc_write( RTC_CONTROLA, ( reg_a | RTC_CA_READ ));

		sec     = rtc_read( RTC_SECONDS );
		min     = rtc_read( RTC_MINUTES );
		hour    = rtc_read( RTC_HOURS );
		mday    = rtc_read( RTC_DAY_OF_MONTH );
		wday    = rtc_read( RTC_DAY_OF_WEEK );
		mon     = rtc_read( RTC_MONTH );
		year    = rtc_read( RTC_YEAR );
		century = rtc_read( RTC_CENTURY );

		/* unlock clock registers after read */
		rtc_write( RTC_CONTROLA, ( reg_a & ~RTC_CA_READ ));

		tmp->tm_sec  = bcd2bin( sec  & 0x7F );
		tmp->tm_min  = bcd2bin( min  & 0x7F );
		tmp->tm_hour = bcd2bin( hour & 0x3F );
		tmp->tm_mday = bcd2bin( mday & 0x3F );
		tmp->tm_mon  = bcd2bin( mon & 0x1F );
		tmp->tm_wday = bcd2bin( wday & 0x07 );

		if (century_flag) {
			tmp->tm_year = bcd2bin( year ) +
				( bcd2bin( century & 0x3F ) * 100 );
		} else {
			tmp->tm_year = bcd2bin( year ) + 1900;
			if (tmp->tm_year < 1970) tmp->tm_year += 100;
		}

		tmp->tm_yday = 0;
		tmp->tm_isdst= 0;
	}
}

void rtc_set( struct rtc_time *tmp )
{
	if (phantom_flag < 0)
		phantom_flag = get_phantom_flag();

	if (phantom_flag) {
		uint year;
		unsigned char rtc[8];

		year = tmp->tm_year;
		year -= (year < 2000) ? 1900 : 2000;

		rtc[0] = bin2bcd(0);
		rtc[1] = bin2bcd(tmp->tm_sec);
		rtc[2] = bin2bcd(tmp->tm_min);
		rtc[3] = bin2bcd(tmp->tm_hour);
		rtc[4] = bin2bcd(tmp->tm_wday);
		rtc[5] = bin2bcd(tmp->tm_mday);
		rtc[6] = bin2bcd(tmp->tm_mon);
		rtc[7] = bin2bcd(year);

		phantom_rtc_write(RTC_BASE, rtc);
	} else {
		uchar reg_a;
		if (century_flag < 0)
			century_flag = get_century_flag();

		/* lock clock registers for write */
		reg_a = rtc_read( RTC_CONTROLA );
		rtc_write( RTC_CONTROLA, ( reg_a | RTC_CA_WRITE ));

		rtc_write( RTC_MONTH, bin2bcd( tmp->tm_mon ));

		rtc_write( RTC_DAY_OF_WEEK, bin2bcd( tmp->tm_wday ));
		rtc_write( RTC_DAY_OF_MONTH, bin2bcd( tmp->tm_mday ));
		rtc_write( RTC_HOURS, bin2bcd( tmp->tm_hour ));
		rtc_write( RTC_MINUTES, bin2bcd( tmp->tm_min ));
		rtc_write( RTC_SECONDS, bin2bcd( tmp->tm_sec ));

		/* break year up into century and year in century */
		if (century_flag) {
			rtc_write( RTC_YEAR, bin2bcd( tmp->tm_year % 100 ));
			rtc_write( RTC_CENTURY, bin2bcd( tmp->tm_year / 100 ));
			reg_a &= 0xc0;
			reg_a |= bin2bcd( tmp->tm_year / 100 );
		} else {
			rtc_write(RTC_YEAR, bin2bcd(tmp->tm_year -
				((tmp->tm_year < 2000) ? 1900 : 2000)));
		}

		/* unlock clock registers after read */
		rtc_write( RTC_CONTROLA, ( reg_a  & ~RTC_CA_WRITE ));
	}
}

#endif
