mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-04 05:50:17 +00:00 
			
		
		
		
	This is a compatibility step that allows both the older form
and the new form to co-exist for a while until the older can
be removed entirely.
All transformations are of the form:
Before:
    #if (CONFIG_COMMANDS & CFG_CMD_AUTOSCRIPT)
After:
    #if (CONFIG_COMMANDS & CFG_CMD_AUTOSCRIPT) || defined(CONFIG_CMD_AUTOSCRIPT)
Signed-off-by: Jon Loeliger <jdl@freescale.com>
		
	
			
		
			
				
	
	
		
			328 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			328 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * ds1302.c - Support for the Dallas Semiconductor DS1302 Timekeeping Chip
 | 
						|
 *
 | 
						|
 * Rex G. Feany <rfeany@zumanetworks.com>
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#include <common.h>
 | 
						|
#include <command.h>
 | 
						|
#include <rtc.h>
 | 
						|
 | 
						|
#if defined(CONFIG_RTC_DS1302) && ((CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_CMD_DATE))
 | 
						|
 | 
						|
/* GPP Pins */
 | 
						|
#define DATA		0x200
 | 
						|
#define SCLK		0x400
 | 
						|
#define RST		0x800
 | 
						|
 | 
						|
/* Happy Fun Defines(tm) */
 | 
						|
#define RESET		rtc_go_low(RST), rtc_go_low(SCLK)
 | 
						|
#define N_RESET		rtc_go_high(RST), rtc_go_low(SCLK)
 | 
						|
 | 
						|
#define CLOCK_HIGH	rtc_go_high(SCLK)
 | 
						|
#define CLOCK_LOW	rtc_go_low(SCLK)
 | 
						|
 | 
						|
#define DATA_HIGH	rtc_go_high(DATA)
 | 
						|
#define DATA_LOW	rtc_go_low(DATA)
 | 
						|
#define DATA_READ	(GTREGREAD(GPP_VALUE) & DATA)
 | 
						|
 | 
						|
#undef RTC_DEBUG
 | 
						|
 | 
						|
#ifdef RTC_DEBUG
 | 
						|
#  define DPRINTF(x,args...)	printf("ds1302: " x , ##args)
 | 
						|
static inline void DUMP(const char *ptr, int num)
 | 
						|
{
 | 
						|
	while (num--) printf("%x ", *ptr++);
 | 
						|
	printf("]\n");
 | 
						|
}
 | 
						|
#else
 | 
						|
#  define DPRINTF(x,args...)
 | 
						|
#  define DUMP(ptr, num)
 | 
						|
#endif
 | 
						|
 | 
						|
/* time data format for DS1302 */
 | 
						|
struct ds1302_st
 | 
						|
{
 | 
						|
	unsigned char CH:1;		/* clock halt 1=stop 0=start */
 | 
						|
	unsigned char sec10:3;
 | 
						|
	unsigned char sec:4;
 | 
						|
 | 
						|
	unsigned char zero0:1;
 | 
						|
	unsigned char min10:3;
 | 
						|
	unsigned char min:4;
 | 
						|
 | 
						|
	unsigned char fmt:1;		/* 1=12 hour 0=24 hour */
 | 
						|
	unsigned char zero1:1;
 | 
						|
	unsigned char hr10:2;	/* 10 (0-2) or am/pm (am/pm, 0-1) */
 | 
						|
	unsigned char hr:4;
 | 
						|
 | 
						|
	unsigned char zero2:2;
 | 
						|
	unsigned char date10:2;
 | 
						|
	unsigned char date:4;
 | 
						|
 | 
						|
	unsigned char zero3:3;
 | 
						|
	unsigned char month10:1;
 | 
						|
	unsigned char month:4;
 | 
						|
 | 
						|
	unsigned char zero4:5;
 | 
						|
	unsigned char day:3; 		/* day of week */
 | 
						|
 | 
						|
	unsigned char year10:4;
 | 
						|
	unsigned char year:4;
 | 
						|
 | 
						|
	unsigned char WP:1;		/* write protect 1=protect 0=unprot */
 | 
						|
	unsigned char zero5:7;
 | 
						|
};
 | 
						|
 | 
						|
static int ds1302_initted=0;
 | 
						|
 | 
						|
/* Pin control */
 | 
						|
static inline void
 | 
						|
rtc_go_high(unsigned int mask)
 | 
						|
{
 | 
						|
	unsigned int f = GTREGREAD(GPP_VALUE) | mask;
 | 
						|
 | 
						|
	GT_REG_WRITE(GPP_VALUE, f);
 | 
						|
}
 | 
						|
 | 
						|
static inline void
 | 
						|
rtc_go_low(unsigned int mask)
 | 
						|
{
 | 
						|
	unsigned int f = GTREGREAD(GPP_VALUE) & ~mask;
 | 
						|
 | 
						|
	GT_REG_WRITE(GPP_VALUE, f);
 | 
						|
}
 | 
						|
 | 
						|
static inline void
 | 
						|
rtc_go_input(unsigned int mask)
 | 
						|
{
 | 
						|
	unsigned int f = GTREGREAD(GPP_IO_CONTROL) & ~mask;
 | 
						|
 | 
						|
	GT_REG_WRITE(GPP_IO_CONTROL, f);
 | 
						|
}
 | 
						|
 | 
						|
static inline void
 | 
						|
rtc_go_output(unsigned int mask)
 | 
						|
{
 | 
						|
	unsigned int f = GTREGREAD(GPP_IO_CONTROL) | mask;
 | 
						|
 | 
						|
	GT_REG_WRITE(GPP_IO_CONTROL, f);
 | 
						|
}
 | 
						|
 | 
						|
/* Access data in RTC */
 | 
						|
 | 
						|
static void
 | 
						|
write_byte(unsigned char b)
 | 
						|
{
 | 
						|
	int i;
 | 
						|
	unsigned char mask=1;
 | 
						|
 | 
						|
	for(i=0;i<8;i++) {
 | 
						|
		CLOCK_LOW;			/* Lower clock */
 | 
						|
		(b&mask)?DATA_HIGH:DATA_LOW;	/* set data */
 | 
						|
		udelay(1);
 | 
						|
		CLOCK_HIGH;		/* latch data with rising clock */
 | 
						|
		udelay(1);
 | 
						|
		mask=mask<<1;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static unsigned char
 | 
						|
read_byte(void)
 | 
						|
{
 | 
						|
	int i;
 | 
						|
	unsigned char mask=1;
 | 
						|
	unsigned char b=0;
 | 
						|
 | 
						|
	for(i=0;i<8;i++) {
 | 
						|
		CLOCK_LOW;
 | 
						|
		udelay(1);
 | 
						|
		if (DATA_READ) b|=mask;	/* if this bit is high, set in b */
 | 
						|
		CLOCK_HIGH;		/* clock out next bit */
 | 
						|
		udelay(1);
 | 
						|
		mask=mask<<1;
 | 
						|
	}
 | 
						|
	return b;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
read_ser_drv(unsigned char addr, unsigned char *buf, int count)
 | 
						|
{
 | 
						|
	int i;
 | 
						|
#ifdef RTC_DEBUG
 | 
						|
	char *foo = buf;
 | 
						|
#endif
 | 
						|
 | 
						|
	DPRINTF("READ 0x%x bytes @ 0x%x [ ", count, addr);
 | 
						|
 | 
						|
	addr|=1;	/* READ */
 | 
						|
	N_RESET;
 | 
						|
	udelay(4);
 | 
						|
	write_byte(addr);
 | 
						|
	rtc_go_input(DATA); /* Put gpp pin into input mode */
 | 
						|
	udelay(1);
 | 
						|
	for(i=0;i<count;i++) *(buf++)=read_byte();
 | 
						|
	RESET;
 | 
						|
	rtc_go_output(DATA);/* Reset gpp for output */
 | 
						|
	udelay(4);
 | 
						|
 | 
						|
	DUMP(foo, count);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
write_ser_drv(unsigned char addr, unsigned char *buf, int count)
 | 
						|
{
 | 
						|
	int i;
 | 
						|
 | 
						|
	DPRINTF("WRITE 0x%x bytes @ 0x%x [ ", count, addr);
 | 
						|
	DUMP(buf, count);
 | 
						|
 | 
						|
	addr&=~1;	/* WRITE */
 | 
						|
	N_RESET;
 | 
						|
	udelay(4);
 | 
						|
	write_byte(addr);
 | 
						|
	for(i=0;i<count;i++) write_byte(*(buf++));
 | 
						|
	RESET;
 | 
						|
	udelay(4);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
rtc_init(void)
 | 
						|
{
 | 
						|
    	struct ds1302_st bbclk;
 | 
						|
	unsigned char b;
 | 
						|
	int mod;
 | 
						|
 | 
						|
	DPRINTF("init\n");
 | 
						|
 | 
						|
	rtc_go_output(DATA|SCLK|RST);
 | 
						|
 | 
						|
	/* disable write protect */
 | 
						|
	b = 0;
 | 
						|
	write_ser_drv(0x8e,&b,1);
 | 
						|
 | 
						|
	/* enable trickle */
 | 
						|
	b = 0xa5;	/* 1010.0101 */
 | 
						|
	write_ser_drv(0x90,&b,1);
 | 
						|
 | 
						|
	/* read burst */
 | 
						|
	read_ser_drv(0xbe, (unsigned char *)&bbclk, 8);
 | 
						|
 | 
						|
	/* Sanity checks */
 | 
						|
	mod = 0;
 | 
						|
	if (bbclk.CH) {
 | 
						|
		printf("ds1302: Clock was halted, starting clock\n");
 | 
						|
		bbclk.CH=0;
 | 
						|
		mod=1;
 | 
						|
	}
 | 
						|
 | 
						|
	if (bbclk.fmt) {
 | 
						|
		printf("ds1302: Clock was in 12 hour mode, fixing\n");
 | 
						|
		bbclk.fmt=0;
 | 
						|
		mod=1;
 | 
						|
	}
 | 
						|
 | 
						|
	if (bbclk.year>9) {
 | 
						|
		printf("ds1302: Year was corrupted, fixing\n");
 | 
						|
		bbclk.year10=100/10;	/* 2000 - why not? ;) */
 | 
						|
		bbclk.year=0;
 | 
						|
		mod=1;
 | 
						|
	}
 | 
						|
 | 
						|
	/* Write out the changes if needed */
 | 
						|
	if (mod) {
 | 
						|
		/* enable write protect */
 | 
						|
		bbclk.WP = 1;
 | 
						|
		write_ser_drv(0xbe,(unsigned char *)&bbclk,8);
 | 
						|
	} else {
 | 
						|
		/* Else just turn write protect on */
 | 
						|
		b = 0x80;
 | 
						|
		write_ser_drv(0x8e,&b,1);
 | 
						|
	}
 | 
						|
	DPRINTF("init done\n");
 | 
						|
 | 
						|
	ds1302_initted=1;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
rtc_reset(void)
 | 
						|
{
 | 
						|
	if(!ds1302_initted) rtc_init();
 | 
						|
	/* TODO */
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
rtc_get(struct rtc_time *tmp)
 | 
						|
{
 | 
						|
	struct ds1302_st bbclk;
 | 
						|
 | 
						|
	if(!ds1302_initted) rtc_init();
 | 
						|
 | 
						|
	read_ser_drv(0xbe,(unsigned char *)&bbclk, 8);      /* read burst */
 | 
						|
 | 
						|
	if (bbclk.CH) {
 | 
						|
		printf("ds1302: rtc_get: Clock was halted, clock probably "
 | 
						|
			"corrupt\n");
 | 
						|
	}
 | 
						|
 | 
						|
	tmp->tm_sec=10*bbclk.sec10+bbclk.sec;
 | 
						|
	tmp->tm_min=10*bbclk.min10+bbclk.min;
 | 
						|
	tmp->tm_hour=10*bbclk.hr10+bbclk.hr;
 | 
						|
	tmp->tm_wday=bbclk.day;
 | 
						|
	tmp->tm_mday=10*bbclk.date10+bbclk.date;
 | 
						|
	tmp->tm_mon=10*bbclk.month10+bbclk.month;
 | 
						|
	tmp->tm_year=10*bbclk.year10+bbclk.year + 1900;
 | 
						|
 | 
						|
	tmp->tm_yday = 0;
 | 
						|
	tmp->tm_isdst= 0;
 | 
						|
 | 
						|
	DPRINTF("Get DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
 | 
						|
		tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
 | 
						|
		tmp->tm_hour, tmp->tm_min, tmp->tm_sec );
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
rtc_set(struct rtc_time *tmp)
 | 
						|
{
 | 
						|
	struct ds1302_st bbclk;
 | 
						|
	unsigned char b=0;
 | 
						|
 | 
						|
	if(!ds1302_initted) rtc_init();
 | 
						|
 | 
						|
	DPRINTF("Set DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
 | 
						|
		tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
 | 
						|
		tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
 | 
						|
 | 
						|
	memset(&bbclk,0,sizeof(bbclk));
 | 
						|
	bbclk.CH=0; /* dont halt */
 | 
						|
	bbclk.WP=1; /* write protect when we're done */
 | 
						|
 | 
						|
	bbclk.sec10=tmp->tm_sec/10;
 | 
						|
	bbclk.sec=tmp->tm_sec%10;
 | 
						|
 | 
						|
	bbclk.min10=tmp->tm_min/10;
 | 
						|
	bbclk.min=tmp->tm_min%10;
 | 
						|
 | 
						|
	bbclk.hr10=tmp->tm_hour/10;
 | 
						|
	bbclk.hr=tmp->tm_hour%10;
 | 
						|
 | 
						|
	bbclk.day=tmp->tm_wday;
 | 
						|
 | 
						|
	bbclk.date10=tmp->tm_mday/10;
 | 
						|
	bbclk.date=tmp->tm_mday%10;
 | 
						|
 | 
						|
	bbclk.month10=tmp->tm_mon/10;
 | 
						|
	bbclk.month=tmp->tm_mon%10;
 | 
						|
 | 
						|
	tmp->tm_year -= 1900;
 | 
						|
	bbclk.year10=tmp->tm_year/10;
 | 
						|
	bbclk.year=tmp->tm_year%10;
 | 
						|
 | 
						|
	write_ser_drv(0x8e,&b,1);           /* disable write protect */
 | 
						|
	write_ser_drv(0xbe,(unsigned char *)&bbclk, 8);     /* write burst */
 | 
						|
}
 | 
						|
 | 
						|
#endif
 |