diff -urN --exclude-from=dontdiff uClinux-dist.orig/linux-2.6.x/arch/armnommu/mach-nds/Makefile uClinux-dist/linux-2.6.x/arch/armnommu/mach-nds/Makefile --- uClinux-dist.orig/linux-2.6.x/arch/armnommu/mach-nds/Makefile 2005-06-12 07:15:25.000000000 -0700 +++ uClinux-dist/linux-2.6.x/arch/armnommu/mach-nds/Makefile 2005-11-04 09:28:40.000000000 -0700 @@ -4,21 +4,19 @@ # Object file lists. -obj-y += arch.o irq.o time.o button.o fifo.o +obj-y += arch.o irq.o time.o button.o fifo.o rtc.o obj-$(CONFIG_NDS_TEXT_CONSOLE) += console.o -extra-y += arm7/head.o arm7/main.o arm7.bin +extra-y += arm7/head.o arm7/main.o arm7/time.o arm7.bin $(obj)/arm7.bin: $(obj)/arm7.elf $(OBJCOPY) -O binary $(obj)/arm7.elf $(obj)/arm7.bin rm -f $(obj)/head.o -arm7obj = $(obj)/arm7/head.o $(obj)/arm7/main.o +arm7obj = $(obj)/arm7/head.o $(obj)/arm7/main.o $(obj)/arm7/time.o $(obj)/arm7.elf: $(arm7obj) $(src)/arm7/arm7.lds $(CC) -msoft-float -nostartfiles -nostdlib -o $(obj)/arm7.elf $(arm7obj) -lgcc -T $(src)/arm7/arm7.lds $(obj)/head.o: $(obj)/arm7.bin - - diff -urN --exclude-from=dontdiff uClinux-dist.orig/linux-2.6.x/arch/armnommu/mach-nds/arm7/main.c uClinux-dist/linux-2.6.x/arch/armnommu/mach-nds/arm7/main.c --- uClinux-dist.orig/linux-2.6.x/arch/armnommu/mach-nds/arm7/main.c 2005-10-23 08:24:27.000000000 -0700 +++ uClinux-dist/linux-2.6.x/arch/armnommu/mach-nds/arm7/main.c 2005-11-04 09:48:17.000000000 -0700 @@ -57,6 +57,8 @@ static s16 touch_cal_x1; static s16 touch_cal_y1; +extern u32 nds_get_time7(void); + u16 touchRead(u32 command) { u16 result; @@ -100,13 +102,20 @@ static void recieveFIFOCommand(void) { u32 data; + u32 seconds = 0; - while ( ! ( REG_IPCFIFOCNT & (1<<3) ) ) + while ( ! ( REG_IPCFIFOCNT & (1<<8) ) ) { data = REG_IPCFIFORECV; - /* Currently, poweroff is the only command we handle. */ + if ( data & FIFO_POWER ) poweroff() ; + else if ( data & FIFO_TIME ) + { + seconds = nds_get_time7(); + REG_IPCFIFOSEND = ( FIFO_TIME | FIFO_HIGH_BITS | (seconds>>16) ); + REG_IPCFIFOSEND = ( FIFO_TIME | FIFO_LOW_BITS | (seconds & 0xFFFF) ); + } } } diff -urN --exclude-from=dontdiff uClinux-dist.orig/linux-2.6.x/arch/armnommu/mach-nds/arm7/time.c uClinux-dist/linux-2.6.x/arch/armnommu/mach-nds/arm7/time.c --- uClinux-dist.orig/linux-2.6.x/arch/armnommu/mach-nds/arm7/time.c 1969-12-31 17:00:00.000000000 -0700 +++ uClinux-dist/linux-2.6.x/arch/armnommu/mach-nds/arm7/time.c 2005-11-04 09:45:02.000000000 -0700 @@ -0,0 +1,106 @@ +#define RTC_CR8 (* (volatile u8*) 0x04000138) +#define READ_DATA_REG1 0x65 +#define READ_STATUS_REG1 0x61 +#define RTC_DELAY 48 +#define CS_0 (1<<6) +#define CS_1 ((1<<6) | (1<<2)) +#define SCK_0 (1<<5) +#define SCK_1 ((1<<5) | (1<<1)) +#define SIO_0 (1<<4) +#define SIO_1 ((1<<4) | (1<<0)) +#define SIO_out (1<<4) +#define SIO_in (1) + +#include "asm/types.h" +#include "linux/timex.h" + +extern void swiDelay( u32 duration ); + +static void rtcTransaction(u8 * command, u32 commandLen, u8 * result, u32 resultLen) +{ + u8 bit; + u8 i; + + RTC_CR8 = CS_0 | SCK_1 | SIO_1; + swiDelay(RTC_DELAY); + RTC_CR8 = CS_1 | SCK_1 | SIO_1; + swiDelay(RTC_DELAY); + + for(i=0; i < commandLen; i++){ + for (bit = 0; bit < 8; bit++) { + RTC_CR8 = CS_1 | SCK_0 | SIO_out | (command[i]>>7); + swiDelay(RTC_DELAY); + + RTC_CR8 = CS_1 | SCK_1 | SIO_out | (command[i]>>7); + swiDelay(RTC_DELAY); + + command[i] = command[i] << 1; + } + } + + for(i=0; i < resultLen; i++) { + result[i] = 0; + for (bit = 0; bit < 8; bit++) { + RTC_CR8 = CS_1 | SCK_0; + swiDelay(RTC_DELAY); + + RTC_CR8 = CS_1 | SCK_1; + swiDelay(RTC_DELAY); + + if (RTC_CR8 & SIO_in) result[i] |= (1 << bit); + } + } + + RTC_CR8 = CS_0 | SCK_1; + swiDelay(RTC_DELAY); +} + + +static u8 BCDToInt(u8 data) { + return((data & 0xF) + ((data & 0xF0)>>4)*10); +} + +static u32 get_nds_seconds(u8 * time) +{ + u8 hours = 0; + u8 i; + + for(i = 0; i < 7; i++) { + time[i] = BCDToInt(time[i]); + } + + hours = time[4]; + if (hours >= 52) { + hours -= 52; + } + + return( mktime(time[0]+2000, + time[1], + time[2], + hours, + time[5], + time[6])); + +} + + +u32 nds_get_time7(void) +{ + u8 command; + u8 time[8]; + unsigned int seconds; + + command = READ_DATA_REG1; + rtcTransaction(&command, 1, &(time[1]), 7); + + command = READ_STATUS_REG1; + rtcTransaction(&command, 1, &(time[0]), 1); + + seconds = get_nds_seconds(&(time[1])); + + return seconds; + +} + + + diff -urN --exclude-from=dontdiff uClinux-dist.orig/linux-2.6.x/arch/armnommu/mach-nds/fifo.c uClinux-dist/linux-2.6.x/arch/armnommu/mach-nds/fifo.c --- uClinux-dist.orig/linux-2.6.x/arch/armnommu/mach-nds/fifo.c 2005-10-27 14:20:18.000000000 -0700 +++ uClinux-dist/linux-2.6.x/arch/armnommu/mach-nds/fifo.c 2005-11-04 10:26:35.000000000 -0700 @@ -48,6 +48,9 @@ case FIFO_TOUCH: cb->handler.touch_handler( (data & (1<<16)) >> 16, (data & (0xff<<8)) >> 8, data & 0xff ) ; break; + case FIFO_TIME: + cb->handler.time_handler( data & 0xffffff ) ; + break; default: break; } diff -urN --exclude-from=dontdiff uClinux-dist.orig/linux-2.6.x/arch/armnommu/mach-nds/rtc.c uClinux-dist/linux-2.6.x/arch/armnommu/mach-nds/rtc.c --- uClinux-dist.orig/linux-2.6.x/arch/armnommu/mach-nds/rtc.c 1969-12-31 17:00:00.000000000 -0700 +++ uClinux-dist/linux-2.6.x/arch/armnommu/mach-nds/rtc.c 2005-11-04 09:15:13.000000000 -0700 @@ -0,0 +1,76 @@ +/* + * linux/arch/armnommu/mach-nds/time.c + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + + +#include + +static u32 ndshwtime = 0; +static u8 timeavail = 0; + +static DECLARE_WAIT_QUEUE_HEAD(ndstime_wait); + +static u32 getTimeFromArm7(void) { + timeavail = 0; + + REG_IPCFIFOSEND = FIFO_TIME ; + + wait_event_interruptible(ndstime_wait, timeavail != 0); + + return ndshwtime; +} + +static void ndsupdate_time(u32 seconds) +{ + if(seconds & FIFO_HIGH_BITS) { + timeavail = 0; + ndshwtime = (seconds & 0xffff) << 16; + } else if(seconds & FIFO_LOW_BITS) { + ndshwtime = ndshwtime | (seconds & 0xffff); + timeavail = 1; + wake_up_interruptible(&ndstime_wait); + } +} + +extern void setTimeFromRTC (void) { + xtime.tv_sec = getTimeFromArm7(); +} + +static struct fifo_cb ndstime_fifocb = { + .type = FIFO_TIME, + .handler.time_handler = ndsupdate_time +}; + +static int __init ndsrtc_init(void) +{ + register_fifocb( &ndstime_fifocb ); + setTimeFromRTC(); + + return 0; +} + +static void __exit ndsrtc_exit(void) +{ +} + +module_init(ndsrtc_init); +module_exit(ndsrtc_exit); diff -urN --exclude-from=dontdiff uClinux-dist.orig/linux-2.6.x/include/asm-armnommu/arch-nds/fifo.h uClinux-dist/linux-2.6.x/include/asm-armnommu/arch-nds/fifo.h --- uClinux-dist.orig/linux-2.6.x/include/asm-armnommu/arch-nds/fifo.h 2005-10-27 14:20:18.000000000 -0700 +++ uClinux-dist/linux-2.6.x/include/asm-armnommu/arch-nds/fifo.h 2005-11-04 10:04:34.000000000 -0700 @@ -25,6 +25,10 @@ #define FIFO_WIFI (1<<27) #define FIFO_SOUND (1<<28) #define FIFO_POWER (1<<29) +#define FIFO_TIME (1<<30) + +#define FIFO_HIGH_BITS (1<<16) +#define FIFO_LOW_BITS (1<<17) #define REG_IPCFIFOSEND (*(volatile u32*) 0x04000188) #define REG_IPCFIFORECV (*(volatile u32*) 0x04100000) @@ -37,6 +41,7 @@ { void (*button_handler)( u32 state ) ; void (*touch_handler)( u8 pressed, u8 x, u8 y ) ; + void (*time_handler)( u32 seconds ) ; /* ... */ } handler ; struct fifo_cb *next ;