From: SUGIOKA T. <su...@it...> - 2001-04-23 06:06:16
|
Hi All. This patch implements 'Enhanced RTC Support' by emulating MC146868 with CMOS_READ/CMOS_WRITE macros. However, drivers/char/rtc.c should be modified slightly, since emulation is incomplete. 'hwclock' command now works on my board(SH7709A) with this patch. How do you think about this approach ? ------------------------------------------------------------------- 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. * drivers/char/rtc.c: Added SH specific 'read RTC' operation. 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 04:59:10 @@ -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 04:59:10 @@ -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: drivers/char/rtc.c =================================================================== RCS file: /cvsroot/linuxsh/kernel/drivers/char/rtc.c,v retrieving revision 1.8 diff -u -r1.8 rtc.c --- drivers/char/rtc.c 2001/01/06 02:52:41 1.8 +++ drivers/char/rtc.c 2001/04/23 04:59:14 @@ -40,9 +40,10 @@ * 1.10b Andrew Morton: SMP lock fix * 1.10c Cesar Barros: SMP locking fixes and cleanup * 1.10d Paul Gortmaker: delete paranoia check in rtc_exit + * 1.10e Sugioka Toshinobu: SuperH version. */ -#define RTC_VERSION "1.10d" +#define RTC_VERSION "1.10e" #define RTC_IO_EXTENT 0x10 /* Only really two ports, but... */ @@ -902,9 +903,14 @@ * Once the read clears, read the RTC time (again via ioctl). Easy. */ +#ifdef __sh__ + do { + ctrl_outb((ctrl_inb(RCR1) & (RCR1_CIE | RCR1_AIE)) | RCR1_AF, RCR1); /* Clear CF */ +#else if (rtc_is_updating() != 0) while (jiffies - uip_watchdog < 2*HZ/100) barrier(); +#endif /* * Only the values that we read from the RTC are set. We leave @@ -921,6 +927,9 @@ rtc_tm->tm_year = CMOS_READ(RTC_YEAR); ctrl = CMOS_READ(RTC_CONTROL); spin_unlock_irq(&rtc_lock); +#ifdef __sh__ + } while((ctrl_inb(RCR1) & RCR1_CF) != 0 && jiffies - uip_watchdog < 2*HZ/100); +#endif if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { 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 04:59:37 @@ -4,6 +4,148 @@ #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; \ + 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 */ \ + rcr1 = ctrl_inb(RCR1); \ + rcr2 = ctrl_inb(RCR2); \ + val = (rcr2 & RCR2_PESMASK) >> 4; \ + 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 04:59: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 |