From: SUGIOKA T. <su...@it...> - 2001-04-23 13:54:39
|
At 15:28 01/04/23 +0900, NIIBE Yutaka wrote: >I know that this is the way of handling SH's RTC in the manual, but we >could implement rtc_is_updating, such as checking R64CNT is near 0 or >not (with some safety). Errr... well, the implementation depends on >architecture, SH-3 or SH-4. OK, I removed the change of drivers/char/rtc.c , and added RTC_UIP (RTC updating) bit emulation as your suggestion. I tested RTC_RD_TIME ioctl function several hundred million times, and found no errors. It seems that RTC_UIP bit works fine on SH7709A. + do { \ + ctrl_outb(rcr1, RCR1); /* clear CF */ \ + r64cnt = ctrl_inb(R64CNT); \ + } while((ctrl_inb(RCR1) & RCR1_CF) && retry++ < 1000);\ This loops about 120 times (maximum) with SH7709A(59MHz). ------------------------------------------------------------------- Changes * config.in: Added CONFIG_RTC. * arch/sh/rtc.c: Moved some definitions to include/asm-sh/rtc.h. * include/asm-sh/rtc.h: Likewise * include/asm-sh/mc146818rtc.h (RTC_PORT, RTC_IRQ, CMOS_READ, CMOS_WRITE, __CMOS_READ, __CMOS_WRITE): Defined. Index: arch/sh/config.in =================================================================== RCS file: /cvsroot/linuxsh/kernel/arch/sh/config.in,v retrieving revision 1.36 diff -u -r1.36 config.in --- arch/sh/config.in 2001/04/20 01:24:03 1.36 +++ arch/sh/config.in 2001/04/23 13:23:19 @@ -255,6 +255,7 @@ dep_tristate 'Support for user-space parallel port device drivers' CONFIG_PPDEV $CONFIG_PARPORT fi bool 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE +tristate 'Enhanced Real Time Clock Support' CONFIG_RTC endmenu if [ "$CONFIG_HOTPLUG" = "y" -a "$CONFIG_PCMCIA" != "n" ]; then Index: arch/sh/kernel/rtc.c =================================================================== RCS file: /cvsroot/linuxsh/kernel/arch/sh/kernel/rtc.c,v retrieving revision 1.7 diff -u -r1.7 rtc.c --- arch/sh/kernel/rtc.c 2001/02/24 07:34:52 1.7 +++ arch/sh/kernel/rtc.c 2001/04/23 13:23:20 @@ -13,62 +13,6 @@ #include <asm/io.h> #include <asm/rtc.h> -/* RCR1 Bits */ -#define RCR1_CF 0x80 /* Carry Flag */ -#define RCR1_CIE 0x10 /* Carry Interrupt Enable */ -#define RCR1_AIE 0x08 /* Alarm Interrupt Enable */ -#define RCR1_AF 0x01 /* Alarm Flag */ - -/* RCR2 Bits */ -#define RCR2_PEF 0x80 /* PEriodic interrupt Flag */ -#define RCR2_PESMASK 0x70 /* Periodic interrupt Set */ -#define RCR2_RTCEN 0x08 /* ENable RTC */ -#define RCR2_ADJ 0x04 /* ADJustment (30-second) */ -#define RCR2_RESET 0x02 /* Reset bit */ -#define RCR2_START 0x01 /* Start bit */ - -#if defined(__sh3__) -/* SH-3 RTC */ -#define R64CNT 0xfffffec0 -#define RSECCNT 0xfffffec2 -#define RMINCNT 0xfffffec4 -#define RHRCNT 0xfffffec6 -#define RWKCNT 0xfffffec8 -#define RDAYCNT 0xfffffeca -#define RMONCNT 0xfffffecc -#define RYRCNT 0xfffffece -#define RSECAR 0xfffffed0 -#define RMINAR 0xfffffed2 -#define RHRAR 0xfffffed4 -#define RWKAR 0xfffffed6 -#define RDAYAR 0xfffffed8 -#define RMONAR 0xfffffeda -#define RCR1 0xfffffedc -#define RCR2 0xfffffede - -#define RTC_BIT_INVERTED 0 /* No bug on SH7708, SH7709A */ -#elif defined(__SH4__) -/* SH-4 RTC */ -#define R64CNT 0xffc80000 -#define RSECCNT 0xffc80004 -#define RMINCNT 0xffc80008 -#define RHRCNT 0xffc8000c -#define RWKCNT 0xffc80010 -#define RDAYCNT 0xffc80014 -#define RMONCNT 0xffc80018 -#define RYRCNT 0xffc8001c /* 16bit */ -#define RSECAR 0xffc80020 -#define RMINAR 0xffc80024 -#define RHRAR 0xffc80028 -#define RWKAR 0xffc8002c -#define RDAYAR 0xffc80030 -#define RMONAR 0xffc80034 -#define RCR1 0xffc80038 -#define RCR2 0xffc8003c - -#define RTC_BIT_INVERTED 0x40 /* bug on SH7750, SH7750S */ -#endif - #ifndef BCD_TO_BIN #define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10) #endif Index: include/asm-sh/mc146818rtc.h =================================================================== RCS file: /cvsroot/linuxsh/kernel/include/asm-sh/mc146818rtc.h,v retrieving revision 1.1 diff -u -r1.1 mc146818rtc.h --- include/asm-sh/mc146818rtc.h 2001/04/18 18:28:35 1.1 +++ include/asm-sh/mc146818rtc.h 2001/04/23 13:23:37 @@ -4,6 +4,156 @@ #ifndef _ASM_MC146818RTC_H #define _ASM_MC146818RTC_H -/* empty include file to satisfy the include in genrtc.c */ +#include <asm/rtc.h> +#define RTC_ALWAYS_BCD 1 + +/* FIXME:RTC Interrupt feature is not implemented yet. */ +#undef RTC_IRQ +#define RTC_IRQ 0 + +#if defined(__sh3__) +#define RTC_PORT(n) (R64CNT+(n)*2) +#define CMOS_READ(addr) __CMOS_READ(addr,b) +#define CMOS_WRITE(val,addr) __CMOS_WRITE(val,addr,b) + +#elif defined(__SH4__) +#define RTC_PORT(n) (R64CNT+(n)*4) +#define CMOS_READ(addr) __CMOS_READ(addr,w) +#define CMOS_WRITE(val,addr) __CMOS_WRITE(val,addr,w) +#endif + +#define __CMOS_READ(addr, s) ({ \ + unsigned char val=0, rcr1, rcr2, r64cnt, retry; \ + switch(addr) { \ + case RTC_SECONDS: \ + val = ctrl_inb(RSECCNT); \ + break; \ + case RTC_SECONDS_ALARM: \ + val = ctrl_inb(RSECAR); \ + break; \ + case RTC_MINUTES: \ + val = ctrl_inb(RMINCNT); \ + break; \ + case RTC_MINUTES_ALARM: \ + val = ctrl_inb(RMINAR); \ + break; \ + case RTC_HOURS: \ + val = ctrl_inb(RHRCNT); \ + break; \ + case RTC_HOURS_ALARM: \ + val = ctrl_inb(RHRAR); \ + break; \ + case RTC_DAY_OF_WEEK: \ + val = ctrl_inb(RWKCNT); \ + break; \ + case RTC_DAY_OF_MONTH: \ + val = ctrl_inb(RDAYCNT); \ + break; \ + case RTC_MONTH: \ + val = ctrl_inb(RMONCNT); \ + break; \ + case RTC_YEAR: \ + val = ctrl_in##s(RYRCNT); \ + break; \ + case RTC_REG_A: /* RTC_FREQ_SELECT */ \ + rcr2 = ctrl_inb(RCR2); \ + val = (rcr2 & RCR2_PESMASK) >> 4; \ + rcr1 = ctrl_inb(RCR1); \ + rcr1 = (rcr1 & (RCR1_CIE | RCR1_AIE)) | RCR1_AF;\ + retry = 0; \ + do { \ + ctrl_outb(rcr1, RCR1); /* clear CF */ \ + r64cnt = ctrl_inb(R64CNT); \ + } while((ctrl_inb(RCR1) & RCR1_CF) && retry++ < 1000);\ + r64cnt ^= RTC_BIT_INVERTED; \ + if(r64cnt == 0x7f || r64cnt == 0) \ + val |= RTC_UIP; \ + break; \ + case RTC_REG_B: /* RTC_CONTROL */ \ + rcr1 = ctrl_inb(RCR1); \ + rcr2 = ctrl_inb(RCR2); \ + if(rcr1 & RCR1_CIE) val |= RTC_UIE; \ + if(rcr1 & RCR1_AIE) val |= RTC_AIE; \ + if(rcr2 & RCR2_PESMASK) val |= RTC_PIE; \ + if(!(rcr2 & RCR2_START))val |= RTC_SET; \ + val |= RTC_24H; \ + break; \ + case RTC_REG_C: /* RTC_INTR_FLAGS */ \ + rcr1 = ctrl_inb(RCR1); \ + rcr1 &= ~(RCR1_CF | RCR1_AF); \ + ctrl_outb(rcr1, RCR1); \ + rcr2 = ctrl_inb(RCR2); \ + rcr2 &= ~RCR2_PEF; \ + ctrl_outb(rcr2, RCR2); \ + break; \ + case RTC_REG_D: /* RTC_VALID */ \ + /* Always valid ... */ \ + val = RTC_VRT; \ + break; \ + default: \ + break; \ + } \ + val; \ +}) + +#define __CMOS_WRITE(val, addr, s) ({ \ + unsigned char rcr1,rcr2; \ + switch(addr) { \ + case RTC_SECONDS: \ + ctrl_outb(val, RSECCNT); \ + break; \ + case RTC_SECONDS_ALARM: \ + ctrl_outb(val, RSECAR); \ + break; \ + case RTC_MINUTES: \ + ctrl_outb(val, RMINCNT); \ + break; \ + case RTC_MINUTES_ALARM: \ + ctrl_outb(val, RMINAR); \ + break; \ + case RTC_HOURS: \ + ctrl_outb(val, RHRCNT); \ + break; \ + case RTC_HOURS_ALARM: \ + ctrl_outb(val, RHRAR); \ + break; \ + case RTC_DAY_OF_WEEK: \ + ctrl_outb(val, RWKCNT); \ + break; \ + case RTC_DAY_OF_MONTH: \ + ctrl_outb(val, RDAYCNT); \ + break; \ + case RTC_MONTH: \ + ctrl_outb(val, RMONCNT); \ + break; \ + case RTC_YEAR: \ + ctrl_out##s((ctrl_in##s(RYRCNT) & 0xff00) | (val & 0xff), RYRCNT);\ + break; \ + case RTC_REG_A: /* RTC_FREQ_SELECT */ \ + rcr2 = ctrl_inb(RCR2); \ + if((val & RTC_DIV_CTL) == RTC_DIV_RESET2) \ + rcr2 |= RCR2_RESET; \ + ctrl_outb(rcr2, RCR2); \ + break; \ + case RTC_REG_B: /* RTC_CONTROL */ \ + rcr1 = (ctrl_inb(RCR1) & 0x99) | RCR1_AF; \ + if(val & RTC_AIE) rcr1 |= RCR1_AIE; \ + else rcr1 &= ~RCR1_AIE; \ + if(val & RTC_UIE) rcr1 |= RCR1_CIE; \ + else rcr1 &= ~RCR1_CIE; \ + ctrl_outb(rcr1, RCR1); \ + rcr2 = ctrl_inb(RCR2); \ + if(val & RTC_SET) rcr2 &= ~RCR2_START; \ + else rcr2 |= RCR2_START; \ + ctrl_outb(rcr2, RCR2); \ + break; \ + case RTC_REG_C: /* RTC_INTR_FLAGS */ \ + break; \ + case RTC_REG_D: /* RTC_VALID */ \ + break; \ + default: \ + break; \ + } \ +}) #endif /* _ASM_MC146818RTC_H */ Index: include/asm-sh/rtc.h =================================================================== RCS file: /cvsroot/linuxsh/kernel/include/asm-sh/rtc.h,v retrieving revision 1.1 diff -u -r1.1 rtc.h --- include/asm-sh/rtc.h 2000/12/26 00:07:14 1.1 +++ include/asm-sh/rtc.h 2001/04/23 13:23:37 @@ -9,4 +9,60 @@ extern void sh_rtc_gettimeofday(struct timeval *tv); extern int sh_rtc_settimeofday(const struct timeval *tv); +/* RCR1 Bits */ +#define RCR1_CF 0x80 /* Carry Flag */ +#define RCR1_CIE 0x10 /* Carry Interrupt Enable */ +#define RCR1_AIE 0x08 /* Alarm Interrupt Enable */ +#define RCR1_AF 0x01 /* Alarm Flag */ + +/* RCR2 Bits */ +#define RCR2_PEF 0x80 /* PEriodic interrupt Flag */ +#define RCR2_PESMASK 0x70 /* Periodic interrupt Set */ +#define RCR2_RTCEN 0x08 /* ENable RTC */ +#define RCR2_ADJ 0x04 /* ADJustment (30-second) */ +#define RCR2_RESET 0x02 /* Reset bit */ +#define RCR2_START 0x01 /* Start bit */ + +#if defined(__sh3__) +/* SH-3 RTC */ +#define R64CNT 0xfffffec0 +#define RSECCNT 0xfffffec2 +#define RMINCNT 0xfffffec4 +#define RHRCNT 0xfffffec6 +#define RWKCNT 0xfffffec8 +#define RDAYCNT 0xfffffeca +#define RMONCNT 0xfffffecc +#define RYRCNT 0xfffffece +#define RSECAR 0xfffffed0 +#define RMINAR 0xfffffed2 +#define RHRAR 0xfffffed4 +#define RWKAR 0xfffffed6 +#define RDAYAR 0xfffffed8 +#define RMONAR 0xfffffeda +#define RCR1 0xfffffedc +#define RCR2 0xfffffede + +#define RTC_BIT_INVERTED 0 /* No bug on SH7708, SH7709A */ +#elif defined(__SH4__) +/* SH-4 RTC */ +#define R64CNT 0xffc80000 +#define RSECCNT 0xffc80004 +#define RMINCNT 0xffc80008 +#define RHRCNT 0xffc8000c +#define RWKCNT 0xffc80010 +#define RDAYCNT 0xffc80014 +#define RMONCNT 0xffc80018 +#define RYRCNT 0xffc8001c /* 16bit */ +#define RSECAR 0xffc80020 +#define RMINAR 0xffc80024 +#define RHRAR 0xffc80028 +#define RWKAR 0xffc8002c +#define RDAYAR 0xffc80030 +#define RMONAR 0xffc80034 +#define RCR1 0xffc80038 +#define RCR2 0xffc8003c + +#define RTC_BIT_INVERTED 0x40 /* bug on SH7750, SH7750S */ +#endif + #endif /* _ASM_RTC_H */ -------------------------------------------------------------------- ---- SUGIOKA Toshinobu |