diff options
Diffstat (limited to 'rtc')
| -rw-r--r-- | rtc/ds1306.c | 274 | ||||
| -rw-r--r-- | rtc/m41t11.c | 202 | ||||
| -rw-r--r-- | rtc/m48t35ax.c | 166 | ||||
| -rw-r--r-- | rtc/mc146818.c | 172 | ||||
| -rw-r--r-- | rtc/mpc8xx.c | 75 | 
5 files changed, 889 insertions, 0 deletions
| diff --git a/rtc/ds1306.c b/rtc/ds1306.c new file mode 100644 index 000000000..9c11c600d --- /dev/null +++ b/rtc/ds1306.c @@ -0,0 +1,274 @@ +/* + * (C) Copyright 2002 SIXNET, dge@sixnetio.com. + * + * 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 + */ + +/* + * Date & Time support for DS1306 RTC using software SPI + */ + +#include <common.h> +#include <command.h> +#include <rtc.h> + +#if defined(CONFIG_RTC_DS1306) && (CONFIG_COMMANDS & CFG_CMD_DATE) + +static unsigned int bin2bcd(unsigned int n); +static unsigned char bcd2bin(unsigned char c); +static void soft_spi_send(unsigned char n); +static unsigned char soft_spi_read(void); +static void init_spi(void); + +/*----------------------------------------------------------------------- + * Definitions + */ + +#define	PB_SPISCK	0x00000002	/* PB 30 */ +#define PB_SPIMOSI	0x00000004	/* PB 29 */ +#define PB_SPIMISO	0x00000008	/* PB 28 */ +#define PB_SPI_CE	0x00010000	/* PB 15 */ + +/* ------------------------------------------------------------------------- */ + +/* read clock time from DS1306 and return it in *tmp */ +void rtc_get(struct rtc_time *tmp) +{ +    volatile immap_t *immap = (immap_t *)CFG_IMMR; +    unsigned char spi_byte;	/* Data Byte */ + +    init_spi();		/* set port B for software SPI */ + +    /* Now we can enable the DS1306 RTC */ +    immap->im_cpm.cp_pbdat |= PB_SPI_CE; +    udelay(10); + +    /* Shift out the address (0) of the time in the Clock Chip */ +    soft_spi_send(0); + +    /* Put the clock readings into the rtc_time structure */ +    tmp->tm_sec = bcd2bin(soft_spi_read());	/* Read seconds */ +    tmp->tm_min = bcd2bin(soft_spi_read());	/* Read minutes */ + +    /* Hours are trickier */ +    spi_byte = soft_spi_read();	/* Read Hours into temporary value */ +    if (spi_byte & 0x40) { +	/* 12 hour mode bit is set (time is in 1-12 format) */ +	if (spi_byte & 0x20) { +	    /* since PM we add 11 to get 0-23 for hours */ +	    tmp->tm_hour = (bcd2bin(spi_byte & 0x1F)) + 11; +	} +	else { +	    /* since AM we subtract 1 to get 0-23 for hours */ +	    tmp->tm_hour = (bcd2bin(spi_byte & 0x1F)) - 1; +	} +    } +    else { +	/* Otherwise, 0-23 hour format */ +	tmp->tm_hour = (bcd2bin(spi_byte & 0x3F)); +    } + +    soft_spi_read();		/* Read and discard Day of week */ +    tmp->tm_mday = bcd2bin(soft_spi_read());	/* Read Day of the Month */ +    tmp->tm_mon = bcd2bin(soft_spi_read());	/* Read Month */ + +    /* Read Year and convert to this century */ +    tmp->tm_year = bcd2bin(soft_spi_read()) + 2000; + +    /* Now we can disable the DS1306 RTC */ +    immap->im_cpm.cp_pbdat &= ~PB_SPI_CE;	/* Disable DS1306 Chip */ +    udelay(10); + +    GregorianDay(tmp);		/* Determine the day of week */ + +    debug("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); +} + +/* ------------------------------------------------------------------------- */ + +/* set clock time in DS1306 RTC and in MPC8xx RTC */ +void rtc_set(struct rtc_time *tmp) +{ +    volatile immap_t *immap = (immap_t *)CFG_IMMR; + +    init_spi();		/* set port B for software SPI */ + +    /* Now we can enable the DS1306 RTC */ +    immap->im_cpm.cp_pbdat |= PB_SPI_CE;	/* Enable DS1306 Chip */ +    udelay(10); + +    /* First disable write protect in the clock chip control register */ +    soft_spi_send(0x8F);	/* send address of the control register */ +    soft_spi_send(0x00);	/* send control register contents */ + +    /* Now disable the DS1306 to terminate the write */ +    immap->im_cpm.cp_pbdat &= ~PB_SPI_CE; +    udelay(10); + +    /* Now enable the DS1306 to initiate a new write */ +    immap->im_cpm.cp_pbdat |= PB_SPI_CE; +    udelay(10); + +    /* Next, send the address of the clock time write registers */ +    soft_spi_send(0x80);	/* send address of the first time register */ + +    /* Use Burst Mode to send all of the time data to the clock */ +    bin2bcd(tmp->tm_sec); +    soft_spi_send(bin2bcd(tmp->tm_sec));	/* Send Seconds */ +    soft_spi_send(bin2bcd(tmp->tm_min));	/* Send Minutes */ +    soft_spi_send(bin2bcd(tmp->tm_hour));	/* Send Hour */ +    soft_spi_send(bin2bcd(tmp->tm_wday));	/* Send Day of the Week */ +    soft_spi_send(bin2bcd(tmp->tm_mday));	/* Send Day of Month */ +    soft_spi_send(bin2bcd(tmp->tm_mon));	/* Send Month */ +    soft_spi_send(bin2bcd(tmp->tm_year - 2000));	/* Send Year */ + +    /* Now we can disable the Clock chip to terminate the burst write */ +    immap->im_cpm.cp_pbdat &= ~PB_SPI_CE;	/* Disable DS1306 Chip */ +    udelay(10); + +    /* Now we can enable the Clock chip to initiate a new write */ +    immap->im_cpm.cp_pbdat |= PB_SPI_CE;	/* Enable DS1306 Chip */ +    udelay(10); + +    /* First we Enable write protect in the clock chip control register */ +    soft_spi_send(0x8F);	/* send address of the control register */ +    soft_spi_send(0x40);	/* send out Control Register contents */ + +    /* Now disable the DS1306 */ +    immap->im_cpm.cp_pbdat &= ~PB_SPI_CE;	/*  Disable DS1306 Chip */ +    udelay(10); + +    /* Set standard MPC8xx clock to the same time so Linux will +     * see the time even if it doesn't have a DS1306 clock driver. +     * This helps with experimenting with standard kernels. +     */ +    { +	ulong tim; + +	tim = mktime(tmp->tm_year, tmp->tm_mon, tmp->tm_mday, +		     tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + +	immap->im_sitk.sitk_rtck = KAPWR_KEY; +	immap->im_sit.sit_rtc = tim; +    } + +    debug("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); +} + +/* ------------------------------------------------------------------------- */ + +void rtc_reset(void) +{ +    return;			/* nothing to do */ +} + +/* ------------------------------------------------------------------------- */ + +static unsigned char bcd2bin(unsigned char n) +{ +    return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F)); +} + +/* ------------------------------------------------------------------------- */ + +static unsigned int bin2bcd(unsigned int n) +{ +    return (((n / 10) << 4) | (n % 10)); +} + +/* ------------------------------------------------------------------------- */ + +/* Initialize Port B for software SPI */ +static void init_spi(void) { +    volatile immap_t *immap = (immap_t *)CFG_IMMR; + +    /* Force output pins to begin at logic 0 */ +    immap->im_cpm.cp_pbdat &= ~(PB_SPI_CE | PB_SPIMOSI | PB_SPISCK); + +    /* Set these 3 signals as outputs */ +    immap->im_cpm.cp_pbdir |= (PB_SPIMOSI | PB_SPI_CE | PB_SPISCK); + +    immap->im_cpm.cp_pbdir &= ~PB_SPIMISO;	/* Make MISO pin an input */ +    udelay(10); +} + +/* ------------------------------------------------------------------------- */ + +/* NOTE: soft_spi_send() assumes that the I/O lines are configured already */ +static void soft_spi_send(unsigned char n) +{ +    volatile immap_t *immap = (immap_t *)CFG_IMMR; +    unsigned char bitpos;	/* bit position to receive */ +    unsigned char i;		/* Loop Control */ + +    /* bit position to send, start with most significant bit */ +    bitpos = 0x80; + +    /* Send 8 bits to software SPI */ +    for (i = 0; i < 8; i++) {	/* Loop for 8 bits */ +	immap->im_cpm.cp_pbdat |= PB_SPISCK;	/* Raise SCK */ + +	if (n & bitpos) +	    immap->im_cpm.cp_pbdat |= PB_SPIMOSI;	/* Set MOSI to 1 */ +	else +	    immap->im_cpm.cp_pbdat &= ~PB_SPIMOSI;	/* Set MOSI to 0 */ +	udelay(10); + +	immap->im_cpm.cp_pbdat &= ~PB_SPISCK;	/* Lower SCK */ +	udelay(10); + +	bitpos >>= 1;		/* Shift for next bit position */ +    } +} + +/* ------------------------------------------------------------------------- */ + +/* NOTE: soft_spi_read() assumes that the I/O lines are configured already */ +static unsigned char soft_spi_read(void) +{ +    volatile immap_t *immap = (immap_t *)CFG_IMMR; + +    unsigned char spi_byte = 0;	/* Return value, assume success */ +    unsigned char bitpos;	/* bit position to receive */ +    unsigned char i;		/* Loop Control */ + +    /* bit position to receive, start with most significant bit */ +    bitpos = 0x80; + +    /* Read 8 bits here */ +    for (i = 0; i < 8; i++) {	/* Do 8 bits in loop */ +	immap->im_cpm.cp_pbdat |= PB_SPISCK;	/* Raise SCK */ +	udelay(10); +	if (immap->im_cpm.cp_pbdat & PB_SPIMISO)	/* Get a bit of data */ +	    spi_byte |= bitpos;	/* Set data accordingly */ +	immap->im_cpm.cp_pbdat &= ~PB_SPISCK;	/* Lower SCK */ +	udelay(10); +	bitpos >>= 1;		/* Shift for next bit position */ +    } + +    return spi_byte;		/* Return the byte read */ +} + +/* ------------------------------------------------------------------------- */ + +#endif diff --git a/rtc/m41t11.c b/rtc/m41t11.c new file mode 100644 index 000000000..30a101c34 --- /dev/null +++ b/rtc/m41t11.c @@ -0,0 +1,202 @@ +/* + * (C) Copyright 2002 + * Andrew May, Viasat Inc, amay@viasat.com + * + * 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 + */ + +/* + * M41T11 Serial Access Timekeeper(R) SRAM + * can you believe a trademark on that? + */ + +#include <common.h> +#include <command.h> +#include <rtc.h> +#include <i2c.h> + +/* +	I Don't have an example config file but this +	is what should be done. + +#define CONFIG_RTC_M41T11 1 +#define CFG_I2C_RTC_ADDR 0x68 +#if 0 +#define CFG_M41T11_EXT_CENTURY_DATA +#else +#define CFG_M41T11_BASE_YEAR 2000 +#endif +*/ + +#if defined(CONFIG_RTC_M41T11) && defined(CFG_I2C_RTC_ADDR) && (CONFIG_COMMANDS & CFG_CMD_DATE) + +#define DEBUG 1 + +static unsigned bcd2bin (uchar n) +{ +	return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F)); +} + +static unsigned char bin2bcd (unsigned int n) +{ +	return (((n / 10) << 4) | (n % 10)); +} + + +/* ------------------------------------------------------------------------- */ +/* +  these are simple defines for the chip local to here so they aren't too +  verbose +  DAY/DATE aren't nice but that is how they are on the data sheet +*/ +#define RTC_SEC_ADDR       0x0 +#define RTC_MIN_ADDR       0x1 +#define RTC_HOUR_ADDR      0x2 +#define RTC_DAY_ADDR       0x3 +#define RTC_DATE_ADDR      0x4 +#define RTC_MONTH_ADDR     0x5 +#define RTC_YEARS_ADDR     0x6 + +#define RTC_REG_CNT        7 + +#define RTC_CONTROL_ADDR   0x7 + + +#ifndef CFG_M41T11_EXT_CENTURY_DATA + +#define REG_CNT            (RTC_REG_CNT+1) + +/* +  you only get 00-99 for the year we will asume you +  want from the year 2000 if you don't set the config +*/ +#ifndef CFG_M41T11_BASE_YEAR +#define CFG_M41T11_BASE_YEAR 2000 +#endif + +#else +/* we will store extra year info in byte 9*/ +#define M41T11_YEAR_DATA   0x8 +#define M41T11_YEAR_SIZE   1 +#define REG_CNT            (RTC_REG_CNT+1+M41T11_YEAR_SIZE) +#endif + +#define M41T11_STORAGE_SZ  (64-REG_CNT) + +void rtc_get (struct rtc_time *tmp) +{ +        uchar data[RTC_REG_CNT]; + +        i2c_read(CFG_I2C_RTC_ADDR, RTC_SEC_ADDR, 1, data, RTC_REG_CNT); + +        if( data[RTC_SEC_ADDR] & 0x80 ){ +                printf( "m41t11 RTC Clock stopped!!!\n" ); +        } +	tmp->tm_sec  = bcd2bin (data[RTC_SEC_ADDR]  & 0x7F); +	tmp->tm_min  = bcd2bin (data[RTC_MIN_ADDR]  & 0x7F); +	tmp->tm_hour = bcd2bin (data[RTC_HOUR_ADDR] & 0x3F); +	tmp->tm_mday = bcd2bin (data[RTC_DATE_ADDR] & 0x3F); +	tmp->tm_mon  = bcd2bin (data[RTC_MONTH_ADDR]& 0x1F); +#ifndef CFG_M41T11_EXT_CENTURY_DATA +        tmp->tm_year = CFG_M41T11_BASE_YEAR +                + bcd2bin(data[RTC_YEARS_ADDR]) +                + ((data[RTC_HOUR_ADDR]&0x40) ? 100 : 0); +#else +        { +                unsigned char cent; +                i2c_read(CFG_I2C_RTC_ADDR, M41T11_YEAR_DATA, 1, ¢, M41T11_YEAR_SIZE); +                if( !(data[RTC_HOUR_ADDR] & 0x80) ){ +                        printf( "m41t11 RTC: cann't keep track of years without CEB set\n" ); +                } +                if( (cent & 0x1) != ((data[RTC_HOUR_ADDR]&0x40)>>7) ){ +                        /*century flip store off new year*/ +                        cent += 1; +                        i2c_write(CFG_I2C_RTC_ADDR, M41T11_YEAR_DATA, 1, ¢, M41T11_YEAR_SIZE); +                } +                tmp->tm_year =((int)cent*100)+bcd2bin(data[RTC_YEARS_ADDR]); +        } +#endif +	tmp->tm_wday = bcd2bin (data[RTC_DAY_ADDR]  & 0x07); +	tmp->tm_yday = 0; +	tmp->tm_isdst= 0; + +	debug ( "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) +{ +        uchar data[RTC_REG_CNT]; + +	debug ( "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); + +	data[RTC_SEC_ADDR]    = bin2bcd(tmp->tm_sec) &  0x7F;/*just in case*/ +	data[RTC_MIN_ADDR]    = bin2bcd(tmp->tm_min); +	data[RTC_HOUR_ADDR]   = bin2bcd(tmp->tm_hour) & 0x3F;/*handle cent stuff later*/ +	data[RTC_DATE_ADDR]   = bin2bcd(tmp->tm_mday) & 0x3F; +	data[RTC_MONTH_ADDR]  = bin2bcd(tmp->tm_mon); +	data[RTC_DAY_ADDR]    = bin2bcd(tmp->tm_wday) & 0x07; + +        data[RTC_HOUR_ADDR]   |= 0x80;/*we will always use CEB*/ + +        data[RTC_YEARS_ADDR]  = bin2bcd(tmp->tm_year%100);/*same thing either way*/ +#ifndef CFG_M41T11_EXT_CENTURY_DATA +        if( ((tmp->tm_year - CFG_M41T11_BASE_YEAR) > 200) || +            (tmp->tm_year < CFG_M41T11_BASE_YEAR) ){ +                printf( "m41t11 RTC setting year out of range!!need recompile\n" ); +        } +        data[RTC_HOUR_ADDR] |= (tmp->tm_year - CFG_M41T11_BASE_YEAR) > 100 ? 0x40 : 0; +#else +        { +                unsigned char cent; +                cent = tmp->tm_year ? tmp->tm_year / 100 : 0; +                data[RTC_HOUR_ADDR] |= (cent & 0x1) ? 0x40 : 0; +                i2c_write(CFG_I2C_RTC_ADDR, M41T11_YEAR_DATA, 1, ¢, M41T11_YEAR_SIZE); +        } +#endif +        i2c_write(CFG_I2C_RTC_ADDR, RTC_SEC_ADDR, 1, data, RTC_REG_CNT); +} + +void rtc_reset (void) +{ +        unsigned char val; +	/* clear all control & status registers */ +        i2c_read(CFG_I2C_RTC_ADDR, RTC_SEC_ADDR, 1, &val, 1); +        val = val & 0x7F;/*make sure we are running*/ +        i2c_write(CFG_I2C_RTC_ADDR, RTC_SEC_ADDR, 1, &val, RTC_REG_CNT); + +        i2c_read(CFG_I2C_RTC_ADDR, RTC_CONTROL_ADDR, 1, &val, 1); +        val = val & 0x3F;/*turn off freq test keep calibration*/ +        i2c_write(CFG_I2C_RTC_ADDR, RTC_CONTROL_ADDR, 1, &val, 1); +} + +int rtc_store(int addr, unsigned char* data, int size) +{ +        /*don't let things wrap onto the time on a write*/ +        if( (addr+size) >= M41T11_STORAGE_SZ ) +                return 1; +        return i2c_write( CFG_I2C_RTC_ADDR, REG_CNT+addr, 1, data, size ); +} + +int rtc_recall(int addr, unsigned char* data, int size) +{ +        return i2c_read( CFG_I2C_RTC_ADDR, REG_CNT+addr, 1, data, size ); +} + +#endif /* CONFIG_RTC_M41T11 && CFG_I2C_RTC_ADDR && CFG_CMD_DATE */ diff --git a/rtc/m48t35ax.c b/rtc/m48t35ax.c new file mode 100644 index 000000000..6c38a538b --- /dev/null +++ b/rtc/m48t35ax.c @@ -0,0 +1,166 @@ +/* + * (C) Copyright 2001 + * Erik Theisen,  Wave 7 Optics, etheisen@mindspring.com. + * + * 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 + */ + +/* + * Date & Time support for ST Electronics M48T35Ax RTC + */ + +/*#define       DEBUG */ + + +#include <common.h> +#include <command.h> +#include <rtc.h> +#include <config.h> + +#if defined(CONFIG_RTC_M48T35A) && (CONFIG_COMMANDS & CFG_CMD_DATE) + +static uchar rtc_read  (uchar reg); +static void  rtc_write (uchar reg, uchar val); +static uchar bin2bcd   (unsigned int n); +static unsigned bcd2bin(uchar c); + +/* ------------------------------------------------------------------------- */ + +void rtc_get (struct rtc_time *tmp) +{ +	uchar sec, min, hour, cent_day, date, month, year; +	uchar ccr;			/* Clock control register */ + +	/* Lock RTC for read using clock control register */ +	ccr = rtc_read(0); +	ccr = ccr | 0x40; +	rtc_write(0, ccr); + +	sec	= rtc_read (0x1); +	min	= rtc_read (0x2); +	hour	= rtc_read (0x3); +	cent_day= rtc_read (0x4); +	date	= rtc_read (0x5); +	month   = rtc_read (0x6); +	year	= rtc_read (0x7); + +	/* UNLock RTC */ +	ccr = rtc_read(0); +	ccr = ccr & 0xBF; +	rtc_write(0, ccr); + +	debug ( "Get RTC year: %02x month: %02x date: %02x cent_day: %02x " +		"hr: %02x min: %02x sec: %02x\n", +		year, month, date, cent_day, +		hour, min, sec ); + +	tmp->tm_sec  = bcd2bin (sec  & 0x7F); +	tmp->tm_min  = bcd2bin (min  & 0x7F); +	tmp->tm_hour = bcd2bin (hour & 0x3F); +	tmp->tm_mday = bcd2bin (date & 0x3F); +	tmp->tm_mon  = bcd2bin (month & 0x1F); +	tmp->tm_year = bcd2bin (year) + ((cent_day & 0x10) ? 2000 : 1900); +	tmp->tm_wday = bcd2bin (cent_day & 0x07); +	tmp->tm_yday = 0; +	tmp->tm_isdst= 0; + +	debug ( "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) +{ +	uchar ccr;			/* Clock control register */ +	uchar century; + +	debug ( "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); + +	/* Lock RTC for write using clock control register */ +	ccr = rtc_read(0); +	ccr = ccr | 0x80; +	rtc_write(0, ccr); + +	rtc_write (0x07, bin2bcd(tmp->tm_year % 100)); +	rtc_write (0x06, bin2bcd(tmp->tm_mon)); +	rtc_write (0x05, bin2bcd(tmp->tm_mday)); + +	century = ((tmp->tm_year >= 2000) ? 0x10 : 0) | 0x20; +	rtc_write (0x04, bin2bcd(tmp->tm_wday) | century); + +	rtc_write (0x03, bin2bcd(tmp->tm_hour)); +	rtc_write (0x02, bin2bcd(tmp->tm_min )); +	rtc_write (0x01, bin2bcd(tmp->tm_sec )); + +	/* UNLock RTC */ +	ccr = rtc_read(0); +	ccr = ccr & 0x7F; +	rtc_write(0, ccr); +} + +void rtc_reset (void) +{ +	uchar val; + +	/* Clear all clock control registers */ +	rtc_write (0x0, 0x80);		/* No Read Lock or calibration */ + +	/* Clear stop bit */ +	val = rtc_read (0x1); +	val &= 0x7f; +	rtc_write(0x1, val); + +	/* Enable century / disable frequency test */ +	val = rtc_read (0x4); +	val = (val & 0xBF) | 0x20; +	rtc_write(0x4, val); + +	/* Clear write lock */ +	rtc_write(0x0, 0); +} + +/* ------------------------------------------------------------------------- */ + +static uchar rtc_read (uchar reg) +{ +	uchar val; +	val = *(unsigned char *) +		((CFG_NVRAM_BASE_ADDR + CFG_NVRAM_SIZE - 8) + reg); +	return val; +} + +static void rtc_write (uchar reg, uchar val) +{ +	*(unsigned char *) +		((CFG_NVRAM_BASE_ADDR + CFG_NVRAM_SIZE - 8) + reg) = val; +} + +static unsigned bcd2bin (uchar n) +{ +	return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F)); +} + +static unsigned char bin2bcd (unsigned int n) +{ +	return (((n / 10) << 4) | (n % 10)); +} + +#endif	/* CONFIG_RTC_M48T35A && CFG_CMD_DATE */ diff --git a/rtc/mc146818.c b/rtc/mc146818.c new file mode 100644 index 000000000..1d65808f7 --- /dev/null +++ b/rtc/mc146818.c @@ -0,0 +1,172 @@ +/* + * (C) Copyright 2001 + * Denis Peter MPL AG Switzerland. d.peter@mpl.ch + * + * 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 + */ + +/* + * Date & Time support for the MC146818 (PIXX4) RTC + */ + +/*#define	DEBUG*/ + +#include <common.h> +#include <command.h> +#include <rtc.h> + +#if defined(CONFIG_RTC_MC146818) && (CONFIG_COMMANDS & CFG_CMD_DATE) + +static uchar rtc_read  (uchar reg); +static void  rtc_write (uchar reg, uchar val); +static uchar bin2bcd   (unsigned int n); +static unsigned bcd2bin(uchar c); + +#define RTC_PORT_MC146818		CFG_ISA_IO_BASE_ADDRESS +  0x70 +#define RTC_SECONDS       	0x00 +#define RTC_SECONDS_ALARM 	0x01 +#define RTC_MINUTES 				0x02 +#define RTC_MINUTES_ALARM 	0x03 +#define RTC_HOURS 					0x04 +#define RTC_HOURS_ALARM 		0x05 +#define RTC_DAY_OF_WEEK 		0x06 +#define RTC_DATE_OF_MONTH 	0x07 +#define RTC_MONTH 					0x08 +#define RTC_YEAR 						0x09 +#define RTC_CONFIG_A 				0x0A +#define RTC_CONFIG_B 				0x0B +#define RTC_CONFIG_C 				0x0C +#define RTC_CONFIG_D 				0x0D + + +/* ------------------------------------------------------------------------- */ + +void rtc_get (struct rtc_time *tmp) +{ +	uchar sec, min, hour, mday, wday, mon, year; +  /* here check if rtc can be accessed */ +	while((rtc_read(RTC_CONFIG_A)&0x80)==0x80); +	sec		= rtc_read (RTC_SECONDS); +	min		= rtc_read (RTC_MINUTES); +	hour	= rtc_read (RTC_HOURS); +	mday	= rtc_read (RTC_DATE_OF_MONTH); +	wday	= rtc_read (RTC_DAY_OF_WEEK); +	mon		= rtc_read (RTC_MONTH); +	year	= rtc_read (RTC_YEAR); +#ifdef RTC_DEBUG +	printf ( "Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x " +		"hr: %02x min: %02x sec: %02x\n", +		year, mon_cent, mday, wday, +		hour, min, sec ); +	printf ( "Alarms: month: %02x hour: %02x min: %02x sec: %02x\n", +		rtc_read (RTC_CONFIG_D) & 0x3F, +		rtc_read (RTC_HOURS_ALARM), +		rtc_read (RTC_MINUTES_ALARM), +		rtc_read (RTC_SECONDS_ALARM) ); +#endif +	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_year = bcd2bin (year); +	tmp->tm_wday = bcd2bin (wday & 0x07); +	if(tmp->tm_year<70) +		tmp->tm_year+=2000; +	else +		tmp->tm_year+=1900; +	tmp->tm_yday = 0; +	tmp->tm_isdst= 0; +#ifdef RTC_DEBUG +	printf ( "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); +#endif +} + +void rtc_set (struct rtc_time *tmp) +{ +#ifdef RTC_DEBUG +	printf ( "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); +#endif +	rtc_write(RTC_CONFIG_B,0x82); /* disables the RTC to update the regs */ + +	rtc_write (RTC_YEAR, bin2bcd(tmp->tm_year % 100)); +	rtc_write (RTC_MONTH, bin2bcd(tmp->tm_mon)); + +	rtc_write (RTC_DAY_OF_WEEK, bin2bcd(tmp->tm_wday)); +	rtc_write (RTC_DATE_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 )); +	rtc_write(RTC_CONFIG_B,0x02); /* enables the RTC to update the regs */ + +} + +void rtc_reset (void) +{ +	rtc_write(RTC_CONFIG_B,0x82); /* disables the RTC to update the regs */ +	rtc_write(RTC_CONFIG_A,0x20); /* Normal OP */ +	rtc_write(RTC_CONFIG_B,0x00); +	rtc_write(RTC_CONFIG_B,0x00); +	rtc_write(RTC_CONFIG_B,0x02); /* enables the RTC to update the regs */ +} + +/* ------------------------------------------------------------------------- */ + +#ifdef CFG_RTC_REG_BASE_ADDR +/* + * use direct memory access + */ +static uchar rtc_read (uchar reg) +{ +	return(in8(CFG_RTC_REG_BASE_ADDR+reg)); +} + +static void rtc_write (uchar reg, uchar val) +{ +	out8(CFG_RTC_REG_BASE_ADDR+reg, val); +} +#else +static uchar rtc_read (uchar reg) +{ +	out8(RTC_PORT_MC146818,reg); +	return(in8(RTC_PORT_MC146818+1)); +} + +static void rtc_write (uchar reg, uchar val) +{ +	out8(RTC_PORT_MC146818,reg); +	out8(RTC_PORT_MC146818+1,val); +} +#endif + +static unsigned bcd2bin (uchar n) +{ +	return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F)); +} + +static unsigned char bin2bcd (unsigned int n) +{ +	return (((n / 10) << 4) | (n % 10)); +} + +#endif	/* CONFIG_RTC_MC146818 && CFG_CMD_DATE */ diff --git a/rtc/mpc8xx.c b/rtc/mpc8xx.c new file mode 100644 index 000000000..830e56e17 --- /dev/null +++ b/rtc/mpc8xx.c @@ -0,0 +1,75 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.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 + */ + +/* + * Date & Time support for internal RTC of MPC8xx + */ + +/*#define	DEBUG*/ + +#include <common.h> +#include <command.h> +#include <rtc.h> + +#if defined(CONFIG_RTC_MPC8xx) && (CONFIG_COMMANDS & CFG_CMD_DATE) + +/* ------------------------------------------------------------------------- */ + +void rtc_get (struct rtc_time *tmp) +{ +	volatile immap_t *immr = (immap_t *)CFG_IMMR; +	ulong tim; + +	tim = immr->im_sit.sit_rtc; + +	to_tm (tim, tmp); + +	debug ( "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) +{ +	volatile immap_t *immr = (immap_t *)CFG_IMMR; +	ulong tim; + +	debug ( "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); + +	tim = mktime (tmp->tm_year, tmp->tm_mon, tmp->tm_mday, +		      tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + +	immr->im_sitk.sitk_rtck = KAPWR_KEY; +	immr->im_sit.sit_rtc = tim; +} + +void rtc_reset (void) +{ +	return;	/* nothing to do */ +} + +/* ------------------------------------------------------------------------- */ + +#endif	/* CONFIG_RTC_MPC8xx && CFG_CMD_DATE */ |