diff --git a/Makefile b/Makefile index 9c5a5b0..f2513cb 100644 --- a/Makefile +++ b/Makefile @@ -120,6 +120,7 @@ LIBS += rtc/librtc.a LIBS += dtt/libdtt.a LIBS += drivers/libdrivers.a LIBS += drivers/sk98lin/libsk98lin.a +LIBS += drivers/watchdog/libwd.a LIBS += post/libpost.a post/cpu/libcpu.a LIBS += common/libcommon.a .PHONY : $(LIBS) diff --git a/board/dave/ZefeerEVB/zefeerevb.c b/board/dave/ZefeerEVB/zefeerevb.c index 6b61dc5..1ffd1f7 100644 --- a/board/dave/ZefeerEVB/zefeerevb.c +++ b/board/dave/ZefeerEVB/zefeerevb.c @@ -27,6 +27,7 @@ #include #include "clocks.h" #include #include +#include #define HAL_WRITE_UINT32( _register_, _value_ ) \ (*((volatile unsigned long *)(_register_)) = (_value_)) @@ -108,7 +109,7 @@ #endif /* We have a console */ gd->have_console = 1; - + return 0; } diff --git a/cpu/arm920t/cpu.c b/cpu/arm920t/cpu.c index 6abb3b0..539fb56 100644 --- a/cpu/arm920t/cpu.c +++ b/cpu/arm920t/cpu.c @@ -99,6 +99,11 @@ #ifdef CONFIG_USE_IRQ IRQ_STACK_START = _armboot_start - CFG_MALLOC_LEN - CFG_GBL_DATA_SIZE - 4; FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ; #endif + +#if defined (CONFIG_ZEFEER) && defined(CONFIG_WATCHDOG) + ds1374wd_init(5*1000000); +#endif + return 0; } diff --git a/cpu/arm920t/ep93xx/cpu.c b/cpu/arm920t/ep93xx/cpu.c index 00510a5..22ee7fd 100644 --- a/cpu/arm920t/ep93xx/cpu.c +++ b/cpu/arm920t/ep93xx/cpu.c @@ -132,10 +132,17 @@ extern void upmconfig(unsigned int upm, /* nop */ } - /* We reset the CPU by generating a 1-->0 transition on DeviceCfg bit 31. */ extern void reset_cpu(ulong addr) { + +#if defined(CONFIG_ZEFEER) && defined (CONFIG_RTC_DS1374) && defined (CONFIG_WATCHDOG) + /* If availbale we the DS1374 to reset the whole thing */ + ds1374wd_force_reset(); + printf("Warning! DS1374 system reset failed. Using EP93xx software reset ...\n"); +#endif + + /* This strategy uses the internal reset (reliable???) */ /* Unlock DeviceCfg and write '1' */ SYSCON_SW_UNCLOCK; SysconDEVCFG |= (1 << 31); diff --git a/cpu/arm920t/ep93xx/serial.c b/cpu/arm920t/ep93xx/serial.c index 8eb561a..a9ef654 100644 --- a/cpu/arm920t/ep93xx/serial.c +++ b/cpu/arm920t/ep93xx/serial.c @@ -19,8 +19,10 @@ */ #include +#include #include +int ep93xx_serial_initialized = 0; void serial_setbrg (void) { @@ -54,6 +56,8 @@ int serial_init (void) { serial_setbrg (); + ep93xx_serial_initialized = 1; + return (0); } @@ -65,7 +69,9 @@ int serial_init (void) int serial_getc (void) { - while (!(rUART1_IIR & 0x2)); + while (!(rUART1_IIR & 0x2)) { + WATCHDOG_RESET(); + }; return rUART1_DR & 0xff; } @@ -108,7 +114,9 @@ #endif void serial_putc (const char c) { /* wait for room in the tx FIFO */ - while(rUART1_FR & 0x20); + while(rUART1_FR & 0x20) { + WATCHDOG_RESET(); + }; rUART1_DR = c; /* If \n, also do \r */ diff --git a/drivers/Makefile b/drivers/Makefile index e6176ed..f0fd13d 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -25,6 +25,8 @@ include $(TOPDIR)/config.mk # CFLAGS += -DET_DEBUG -DDEBUG +SUBDIRS := watchdog + LIB = libdrivers.a OBJS = 3c589.o 5701rls.o ali512x.o \ @@ -59,6 +61,8 @@ ######################################## .depend: Makefile $(OBJS:.o=.c) $(CC) -M $(CFLAGS) $(OBJS:.o=.c) > $@ + @for dir in $(SUBDIRS) ; do \ + $(MAKE) -C $$dir $@ ; done sinclude .depend diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile new file mode 100644 index 0000000..ac5f761 --- /dev/null +++ b/drivers/watchdog/Makefile @@ -0,0 +1,16 @@ +include $(TOPDIR)/config.mk + +LIB := libwd.a + +OBJS := ds1374wd.o +all: $(LIB) + +$(LIB): $(OBJS) + $(AR) crv $@ $(OBJS) + +######################################################################### + +.depend: Makefile $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(OBJS:.o=.c) > $@ + +sinclude .depend diff --git a/drivers/watchdog/ds1374wd.c b/drivers/watchdog/ds1374wd.c new file mode 100644 index 0000000..28286b7 --- /dev/null +++ b/drivers/watchdog/ds1374wd.c @@ -0,0 +1,96 @@ +/* + * (C) Copyright 2006 + * DAVE Srl + * + * 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 + */ + +/* + * Watchdog support for Dallas Semiconductor (now Maxim) DS1374 + */ + +#include +#include +#include +#include + +#if (defined(CONFIG_RTC_DS1374)) && defined(CONFIG_WATCHDOG) + +#ifdef CONFIG_ZEFEER +extern int ep93xx_serial_initialized; +#endif + +/* This will be invoked to retrigger counter */ +void watchdog_reset (void) +{ + ds1374_read(RTC_WD_ALM_CNT_BYTE0_ADDR); +} + +/* Initialize and start watchdog */ +void ds1374wd_init(u32 timeout) +{ + DECLARE_GLOBAL_DATA_PTR; + uchar tmp; + u32 ticks = (timeout / DS1374WD_MIN_TICK_US); + + tmp = 0; + ds1374_write_raw(RTC_CTL_ADDR, tmp); + + /* timeout programming */ + ds1374_write_raw(RTC_WD_ALM_CNT_BYTE2_ADDR, (u8)((ticks & 0x00FF0000) >> 16)); + ds1374_write_raw(RTC_WD_ALM_CNT_BYTE1_ADDR, (u8)((ticks & 0x0000FF00) >> 8)); + ds1374_write_raw(RTC_WD_ALM_CNT_BYTE0_ADDR, (u8)((ticks & 0x000000FF) >> 0)); + + +#ifdef CONFIG_ZEFEER + if (ep93xx_serial_initialized) { + debug("RTC_WD_ALM_CNT_BYTE2_ADDR = 0x%02X\n", ds1374_read(RTC_WD_ALM_CNT_BYTE2_ADDR)); + debug("RTC_WD_ALM_CNT_BYTE1_ADDR = 0x%02X\n", ds1374_read(RTC_WD_ALM_CNT_BYTE1_ADDR)); + debug("RTC_WD_ALM_CNT_BYTE0_ADDR = 0x%02X\n", ds1374_read(RTC_WD_ALM_CNT_BYTE0_ADDR)); + } +#endif + + /* + Control.WD/nALM = 1 + Control.WDSTR = 0 + Control.WACE = 1 + */ + tmp = 0; + tmp |= (RTC_CTL_BIT_WD_ALM | RTC_CTL_BIT_WACE); + tmp &= ~RTC_CTL_BIT_WDSTR; + ds1374_write_raw(RTC_CTL_ADDR, tmp); +#ifdef CONFIG_ZEFEER + if (ep93xx_serial_initialized) + debug("RTC_CTL_ADDR = 0x%02X\n", ds1374_read(RTC_CTL_ADDR)); +#endif +} + +/* Enables watchdog with shortest possible timeout and makes it expire */ +int ds1374wd_force_reset() +{ + /* Set minimal timeout */ + ds1374wd_init(1000000); + + /* We should die here ... */ + udelay(1000000 * 2); + + /* If we get here it did not work! */ + return -1; +} +#endif /* (CONFIG_RTC_DS1374) && (CONFIG_WATCHDOG) */ diff --git a/include/configs/ZefeerEVB.h b/include/configs/ZefeerEVB.h index f0d201f..a63e042 100644 --- a/include/configs/ZefeerEVB.h +++ b/include/configs/ZefeerEVB.h @@ -100,8 +100,6 @@ #define I2C_SCL(bit) GPIO_PGDDR |= GPIOG else GPIO_PGDR &= ~GPIOG_EECLK #define I2C_DELAY udelay(50) /* 1/4 I2C clock duration */ -#define CONFIG_RTC_DS1337 -#define CFG_I2C_RTC_ADDR 0x68 #endif /* CONFIG_SOFT_I2C */ @@ -133,6 +131,7 @@ #if defined(CONFIG_ZEFEER_DZN) || define CFG_CMD_NET | \ CFG_CMD_SPI | \ CFG_CMD_I2C | \ + CFG_CMD_DATE | \ CFG_CMD_BIN) #else #define CONFIG_COMMANDS (CONFIG_CMD_DFL | \ @@ -150,11 +149,13 @@ #else CFG_CMD_NET | \ CFG_CMD_SPI | \ CFG_CMD_I2C | \ + CFG_CMD_DATE | \ CFG_CMD_PING) #else #define CONFIG_COMMANDS (CONFIG_CMD_DFL | \ CFG_CMD_MII | \ CFG_CMD_NET | \ + CFG_CMD_DATE | \ CFG_CMD_PING) #endif #endif @@ -266,7 +267,6 @@ #define CFG_PBSIZE (CFG_CBSIZE+sizeof(CF #define CFG_MAXARGS 16 /* max number of command args */ #define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ #define CFG_AUTO_COMPLETE -#undef CONFIG_WATCHDOG /* watchdog disabled */ #define CFG_MEMTEST_START 0x00000000 /* memtest works on */ #define CFG_MEMTEST_END 0x00f00000 /* MB in DRAM */ @@ -387,4 +387,10 @@ #define CFG_ENV_SECT_SIZE 0x20000 /* 128 #define CFG_ENV_ADDR_REDUND (CFG_ENV_ADDR + 0x20000) #define CFG_ENV_SIZE_REDUND 0x20000 +/*----------------------------------------------------------------------- + * WDT/RTC + */ +#define CONFIG_RTC_DS1374 +#define CONFIG_WATCHDOG + #endif /* __CONFIG_H */ diff --git a/include/ds1374.h b/include/ds1374.h new file mode 100644 index 0000000..3436e0a --- /dev/null +++ b/include/ds1374.h @@ -0,0 +1,84 @@ +/* + * (C) Copyright 2001, 2002, 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * Keith Outwater, keith_outwater@mvis.com` + * Steven Scholz, steven.scholz@imc-berlin.de + * (C) Copyright 2006 + * DAVE Srl + * + * 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 + */ + +/* + * Common stuff dor DS1374 drivers + */ + +#ifndef _DS1374_H_ +#define _DS1374_H_ + +#ifndef CFG_I2C_RTC_ADDR +# define CFG_I2C_RTC_ADDR 0x68 +#endif + +#if defined(CONFIG_RTC_DS1374) && (CFG_I2C_SPEED > 400000) +# error The DS1374 is specified up to 400kHz in fast mode! +#endif + +/* + * RTC register addresses + */ +#define RTC_TOD_CNT_BYTE0_ADDR 0x00 /* TimeOfDay */ +#define RTC_TOD_CNT_BYTE1_ADDR 0x01 +#define RTC_TOD_CNT_BYTE2_ADDR 0x02 +#define RTC_TOD_CNT_BYTE3_ADDR 0x03 + +#define RTC_WD_ALM_CNT_BYTE0_ADDR 0x04 +#define RTC_WD_ALM_CNT_BYTE1_ADDR 0x05 +#define RTC_WD_ALM_CNT_BYTE2_ADDR 0x06 + +#define RTC_CTL_ADDR 0x07 /* RTC-CoNTrol-register */ +#define RTC_SR_ADDR 0x08 /* RTC-StatusRegister */ +#define RTC_TCS_DS_ADDR 0x09 /* RTC-TrickleChargeSelect DiodeSelect-register */ + +#define RTC_CTL_BIT_AIE (1<<0) /* Bit 0 - Alarm Interrupt enable */ +#define RTC_CTL_BIT_RS1 (1<<1) /* Bit 1/2 - Rate Select square wave output */ +#define RTC_CTL_BIT_RS2 (1<<2) /* Bit 2/2 - Rate Select square wave output */ +#define RTC_CTL_BIT_WDSTR (1<<3) /* Bit 3 - Watchdog Reset Steering */ +#define RTC_CTL_BIT_BBSQW (1<<4) /* Bit 4 - Battery-Backed Square-Wave */ +#define RTC_CTL_BIT_WD_ALM (1<<5) /* Bit 5 - Watchdoc/Alarm Counter Select */ +#define RTC_CTL_BIT_WACE (1<<6) /* Bit 6 - Watchdog/Alarm Counter Enable WACE*/ +#define RTC_CTL_BIT_EN_OSC (1<<7) /* Bit 7 - Enable Oscilator */ + +#define RTC_SR_BIT_AF 0x01 /* Bit 0 = Alarm Flag */ +#define RTC_SR_BIT_OSF 0x80 /* Bit 7 - Osc Stop Flag */ + +typedef unsigned char boolean_t; + +uchar ds1374_read (uchar reg); +void ds1374_write (uchar reg, uchar val, boolean_t set); +void ds1374_write_raw (uchar reg, uchar val); + +#ifdef CONFIG_WATCHDOG +/* Minimal watchdog tick */ +#define DS1374WD_MIN_TICK_US 244 +void ds1374wd_init(u32); +int ds1374wd_force_reset(); +#endif + +#endif /* _DS1374_H_ */ diff --git a/rtc/Makefile b/rtc/Makefile index 4ceac76..72a6ea9 100644 --- a/rtc/Makefile +++ b/rtc/Makefile @@ -28,8 +28,8 @@ #CFLAGS += -DDEBUG LIB = librtc.a OBJS = date.o \ - ds12887.o ds1302.o ds1306.o ds1307.o ds1337.o \ - ds1556.o ds164x.o ds174x.o \ + ds12887.o ds1302.o ds1306.o ds1307.o \ + ds1337.o ds1374.o ds1556.o ds164x.o ds174x.o \ m41t11.o max6900.o m48t35ax.o mc146818.o mk48t59.o \ mpc5xxx.o mpc8xx.o pcf8563.o s3c24x0_rtc.o rs5c372.o diff --git a/rtc/ds1374.c b/rtc/ds1374.c new file mode 100644 index 0000000..99e8646 --- /dev/null +++ b/rtc/ds1374.c @@ -0,0 +1,216 @@ +/* + * (C) Copyright 2001, 2002, 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * Keith Outwater, keith_outwater@mvis.com` + * Steven Scholz, steven.scholz@imc-berlin.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 (no alarms) for Dallas Semiconductor (now Maxim) + * DS1374 Real Time Clock (RTC). + * + * based on ds1337.c + */ + +#include +#include +#include +#include +#include + +#if defined(CONFIG_RTC_DS1374) + +/*---------------------------------------------------------------------*/ +#undef DEBUG_RTC +#define DEBUG_RTC + +#ifdef DEBUG_RTC +#define DEBUGR(fmt,args...) printf(fmt ,##args) +#else +#define DEBUGR(fmt,args...) +#endif +/*---------------------------------------------------------------------*/ + + +#ifndef TRUE +#define TRUE ((boolean_t)(0==0)) +#endif +#ifndef FALSE +#define FALSE (!TRUE) +#endif + +const char RtcTodAddr[] = { + RTC_TOD_CNT_BYTE0_ADDR, + RTC_TOD_CNT_BYTE1_ADDR, + RTC_TOD_CNT_BYTE2_ADDR, + RTC_TOD_CNT_BYTE3_ADDR +}; + +/* + * Helper functions + */ +uchar ds1374_read (uchar reg) +{ + return (i2c_reg_read (CFG_I2C_RTC_ADDR, reg)); +} + +void ds1374_write (uchar reg, uchar val, boolean_t set) +{ + if (set == TRUE) { + val |= i2c_reg_read (CFG_I2C_RTC_ADDR, reg); + i2c_reg_write (CFG_I2C_RTC_ADDR, reg, val); + } else { + val = i2c_reg_read (CFG_I2C_RTC_ADDR, reg) & ~val; + i2c_reg_write (CFG_I2C_RTC_ADDR, reg, val); + } +} + +void ds1374_write_raw (uchar reg, uchar val) +{ + i2c_reg_write (CFG_I2C_RTC_ADDR, reg, val); +} +#if (CONFIG_COMMANDS & CFG_CMD_DATE) + +/* + * Get the current time from the RTC + */ +void rtc_get (struct rtc_time *tm){ + + unsigned long time1, time2; + unsigned int limit; + unsigned char tmp; + unsigned int i; + + /* + * Since the reads are being performed one byte at a time, + * there is a chance that a carry will occur during the read. + * To detect this, 2 reads are performed and compared. + */ + limit = 10; + do { + i = 4; + time1 = 0; + while (i--) { + tmp = ds1374_read(RtcTodAddr[i]); + time1 = (time1 << 8) | (tmp & 0xff); + } + + i = 4; + time2 = 0; + while (i--) { + tmp = ds1374_read(RtcTodAddr[i]); + time2 = (time2 << 8) | (tmp & 0xff); + } + } while ((time1 != time2) && limit--); + + if (time1 != time2) { + printf("can't get consistent time from rtc chip\n"); + } + + DEBUGR ("Get RTC s since 1.1.1970: %d\n", time1); + + to_tm(time1, tm); /* To Gregorian Date */ + + if (ds1374_read(RTC_SR_ADDR) & RTC_SR_BIT_OSF) + printf ("### Warning: RTC oscillator has stopped\n"); + + DEBUGR ("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday, + tm->tm_hour, tm->tm_min, tm->tm_sec); +} + +/* + * Set the RTC + */ +void rtc_set (struct rtc_time *tmp){ + + unsigned long time; + unsigned i; + + DEBUGR ("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); + + if (tmp->tm_year < 1970 || tmp->tm_year > 2069) + printf("WARNING: year should be between 1970 and 2069!\n"); + + time = mktime(tmp->tm_year, tmp->tm_mon, + tmp->tm_mday, tmp->tm_hour, + tmp->tm_min, tmp->tm_sec); + + DEBUGR ("Set RTC s since 1.1.1970: %d (0x%02x)\n", time, time); + + /* write to RTC_TOD_CNT_BYTEn_ADDR */ + for (i = 0; i <= 3; i++) { + ds1374_write_raw(RtcTodAddr[i], (unsigned char)(time & 0xff)); + time = time >> 8; + } + + /* Start clock */ + ds1374_write(RTC_CTL_ADDR, RTC_CTL_BIT_EN_OSC, FALSE); +} + +/* + * Reset the RTC. We setting the date back to 1970-01-01. + * We also enable the oscillator output on the SQW/OUT pin and program + * it for 32,768 Hz output. Note that according to the datasheet, turning + * on the square wave output increases the current drain on the backup + * battery to something between 480nA and 800nA. + */ +void rtc_reset (void){ + + struct rtc_time tmp; + + /* clear status flags */ + ds1374_write (RTC_SR_ADDR, (RTC_SR_BIT_AF|RTC_SR_BIT_OSF), FALSE); /* clearing OSF and AF */ + + /* Initialise DS1374 oriented to MPC8349E-ADS */ + ds1374_write (RTC_CTL_ADDR, (RTC_CTL_BIT_EN_OSC + |RTC_CTL_BIT_WACE + |RTC_CTL_BIT_AIE), FALSE);/* start osc, disable WACE, clear AIE + - set to 0 */ + ds1374_write (RTC_CTL_ADDR, (RTC_CTL_BIT_WD_ALM + |RTC_CTL_BIT_WDSTR + |RTC_CTL_BIT_RS1 + |RTC_CTL_BIT_RS2 + |RTC_CTL_BIT_BBSQW), TRUE);/* disable WD/ALM, WDSTR set to INT-pin, + set BBSQW and SQW to 32k + - set to 1 */ + tmp.tm_year = 1970; + tmp.tm_mon = 1; + tmp.tm_mday= 1; + tmp.tm_hour = 0; + tmp.tm_min = 0; + tmp.tm_sec = 0; + + rtc_set(&tmp); + + printf("RTC: %4d-%02d-%02d %2d:%02d:%02d UTC\n", + tmp.tm_year, tmp.tm_mon, tmp.tm_mday, + tmp.tm_hour, tmp.tm_min, tmp.tm_sec); + + ds1374_write(RTC_WD_ALM_CNT_BYTE2_ADDR,0xAC, TRUE); + ds1374_write(RTC_WD_ALM_CNT_BYTE1_ADDR,0xDE, TRUE); + ds1374_write(RTC_WD_ALM_CNT_BYTE2_ADDR,0xAD, TRUE); +} + +#endif /* (CFG_COMMANDS & CFG_CMD_DATE) */ +#endif /* (CONFIG_RTC_DS1374) */