/* * Machine dependent access functions for RTC registers. */ #ifndef _ASM_MC146818RTC_H #define _ASM_MC146818RTC_H #ifdef CONFIG_SH_MPC1211 #undef _ASM_MC146818RTC_H #undef RTC_IRQ #include #else #include #define RTC_ALWAYS_BCD 1 /* FIXME:RTC Interrupt feature is not implemented yet. */ #undef RTC_IRQ #define RTC_IRQ 0 #if defined(CONFIG_CPU_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(CONFIG_SH_SECUREEDGE5410) #include #define RTC_PORT(n) SECUREEDGE_IOPORT_ADDR #define CMOS_READ(addr) secureedge5410_cmos_read(addr) #define CMOS_WRITE(val,addr) secureedge5410_cmos_write(val,addr) extern unsigned char secureedge5410_cmos_read(int addr); extern void secureedge5410_cmos_write(unsigned char val, int addr); #elif defined(CONFIG_CPU_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 /* CONFIG_SH_MPC1211 */ #endif /* _ASM_MC146818RTC_H */