Subject: Patch to fix writes to MCS1850 RTC
To: None <port-next68k@netbsd.org>
From: Cory Bajus <cbajus@mts.net>
List: port-next68k
Date: 04/21/2006 18:20:10
--yrj/dFKFPuw6o+aM
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Attached are patches to use 'burst mode' when writing to the MCS1850 RTC
chip.  Please test if you get a chance and let me know if there are any
problems.

Thanks,
Cory.

--yrj/dFKFPuw6o+aM
Content-Type: text/x-chdr; charset=us-ascii
Content-Disposition: attachment; filename="diff-rtc.h"

Index: rtc.h
===================================================================
RCS file: /cvsroot/src/sys/arch/next68k/next68k/rtc.h,v
retrieving revision 1.3
diff -u -r1.3 rtc.h
--- rtc.h	19 Jan 2005 01:58:21 -0000	1.3
+++ rtc.h	21 Apr 2006 17:09:20 -0000
@@ -37,7 +37,9 @@
 void poweroff(void);
 void rtc_init(void);
 u_char rtc_read(u_char);
+u_int rtc_read_burst(u_char);
 void rtc_write(u_char, u_char);
+void rtc_write_burst(u_char, u_int);
 void rtc_print(void);
 time_t getsecs(void);
 void setsecs(time_t);

--yrj/dFKFPuw6o+aM
Content-Type: text/x-csrc; charset=us-ascii
Content-Disposition: attachment; filename="diff-rtc.c"

Index: rtc.c
===================================================================
RCS file: /cvsroot/src/sys/arch/next68k/next68k/rtc.c,v
retrieving revision 1.13
diff -u -r1.13 rtc.c
--- rtc.c	15 Mar 2006 15:39:26 -0000	1.13
+++ rtc.c	21 Apr 2006 17:17:14 -0000
@@ -162,6 +162,51 @@
 	return val;
 }
 
+u_int
+rtc_read_burst(u_char reg)
+{
+	int i;
+	u_int tmp, val;
+
+	*scr2 = (*scr2 & ~(SCR2_RTDATA | SCR2_RTCLK)) | SCR2_RTCE;
+	DELAY(1);
+
+	for (i=0; i<8; i++) {
+		tmp = *scr2 & ~(SCR2_RTDATA | SCR2_RTCLK);
+		if (reg & 0x80)
+			tmp |= SCR2_RTDATA;
+
+		*scr2 = tmp;
+		DELAY(1);
+		*scr2 = tmp | SCR2_RTCLK;
+		DELAY(1);
+		*scr2 = tmp;
+		DELAY(1);
+
+		reg <<= 1;
+	}
+
+	val = 0;			/* should be anyway */
+	for (i=0; i<32; i++) {
+		val <<= 1;
+	
+		tmp = *scr2 & ~(SCR2_RTDATA | SCR2_RTCLK);
+
+		*scr2 = tmp | SCR2_RTCLK;
+		DELAY(1);
+		*scr2 = tmp;
+		DELAY(1);
+
+		if (*scr2 & SCR2_RTDATA)
+			val |= 1;
+	}
+
+	*scr2 &= ~(SCR2_RTDATA|SCR2_RTCLK|SCR2_RTCE);
+	DELAY(1);
+
+	return val;
+}
+
 void
 rtc_write(u_char reg, u_char v)
 {
@@ -211,6 +256,53 @@
 }
 
 void
+rtc_write_burst(u_char reg, u_int v)
+{
+	int i;
+	u_int tmp;
+
+	*scr2 = (*scr2 & ~(SCR2_RTDATA | SCR2_RTCLK)) | SCR2_RTCE;
+	DELAY(1);
+
+	reg |= RTC_WRITE;
+
+	for (i=0; i<8; i++) {
+		tmp = *scr2 & ~(SCR2_RTDATA | SCR2_RTCLK);
+		if (reg & 0x80)
+			tmp |= SCR2_RTDATA;
+
+		*scr2 = tmp;
+		DELAY(1);
+		*scr2 = tmp | SCR2_RTCLK;
+		DELAY(1);
+		*scr2 = tmp;
+		DELAY(1);
+
+		reg <<= 1;
+	}
+
+	DELAY(1);
+
+	for (i=0; i<32; i++) {
+		tmp = *scr2 & ~(SCR2_RTDATA | SCR2_RTCLK);
+		if (v & 0x80000000)
+			tmp |= SCR2_RTDATA;
+
+		*scr2 = tmp;
+		DELAY(1);
+		*scr2 = tmp | SCR2_RTCLK;
+		DELAY(1);
+		*scr2 = tmp;
+		DELAY(1);
+
+		v <<= 1;
+	}
+
+	*scr2 &= ~(SCR2_RTDATA|SCR2_RTCLK|SCR2_RTCE);
+	DELAY(1);
+}
+
+void
 poweroff(void)
 {
 	int reg, t;
@@ -247,10 +339,7 @@
 	u_int secs = 0;
 	
 	if (new_clock) {
-		secs = rtc_read(RTC_CNTR0) << 24 |
-				rtc_read(RTC_CNTR1) << 16 |
-				rtc_read(RTC_CNTR2) << 8	 |
-				rtc_read(RTC_CNTR3);
+		secs = rtc_read_burst(RTC_CNTR0);
 	} else {
 		struct clock_ymdhms val;
 		{
@@ -296,16 +385,12 @@
 	rtc_write(RTC_CONTROL,rtc_read(RTC_CONTROL) & ~RTC_START);
 
 #ifdef RTC_DEBUG
-	printf("Setting RTC to 0x%08x.  Regs before:\n",secs);
+	printf("Setting RTC to 0x%08x.  Regs before:\n", (u_int)secs);
 	rtc_print();
 #endif
 
 	if (new_clock) {
-		rtc_write(RTC_CNTR0, (secs >> 24) & 0xff);
-		rtc_write(RTC_CNTR1, (secs >> 16) & 0xff);
-		rtc_write(RTC_CNTR2, (secs >> 8) & 0xff);
-		rtc_write(RTC_CNTR3, (secs) & 0xff);
-
+		rtc_write_burst(RTC_CNTR0, (u_int)secs);
 	} else {
 		struct clock_ymdhms val;
 		clock_secs_to_ymdhms(secs,&val);
@@ -335,7 +420,7 @@
 	}
 
 #ifdef RTC_DEBUG
-	printf("Regs after:\n",secs);
+	printf("Regs after:\n");
 	rtc_print();
 #endif
 

--yrj/dFKFPuw6o+aM--