1 /* 2 * Machine dependent access functions for RTC registers. 3 */ 4 #ifndef _ASM_MC146818RTC_H 5 #define _ASM_MC146818RTC_H 6 7 #include <asm/rtc.h> 8 9 #define RTC_ALWAYS_BCD 1 10 11 /* FIXME:RTC Interrupt feature is not implemented yet. */ 12 #undef RTC_IRQ 13 #define RTC_IRQ 0 14 15 #if defined(__sh3__) 16 #define RTC_PORT(n) (R64CNT+(n)*2) 17 #define CMOS_READ(addr) __CMOS_READ(addr,b) 18 #define CMOS_WRITE(val,addr) __CMOS_WRITE(val,addr,b) 19 20 #elif defined(CONFIG_SH_SECUREEDGE5410) 21 #include <asm/io.h> 22 23 #define RTC_PORT(n) SECUREEDGE_IOPORT_ADDR 24 #define CMOS_READ(addr) secureedge5410_cmos_read(addr) 25 #define CMOS_WRITE(val,addr) secureedge5410_cmos_write(val,addr) 26 extern unsigned char secureedge5410_cmos_read(int addr); 27 extern void secureedge5410_cmos_write(unsigned char val, int addr); 28 29 #elif defined(__SH4__) 30 #define RTC_PORT(n) (R64CNT+(n)*4) 31 #define CMOS_READ(addr) __CMOS_READ(addr,w) 32 #define CMOS_WRITE(val,addr) __CMOS_WRITE(val,addr,w) 33 #endif 34 35 #define __CMOS_READ(addr, s) ({ \ 36 unsigned char val=0, rcr1, rcr2, r64cnt, retry; \ 37 switch(addr) { \ 38 case RTC_SECONDS: \ 39 val = ctrl_inb(RSECCNT); \ 40 break; \ 41 case RTC_SECONDS_ALARM: \ 42 val = ctrl_inb(RSECAR); \ 43 break; \ 44 case RTC_MINUTES: \ 45 val = ctrl_inb(RMINCNT); \ 46 break; \ 47 case RTC_MINUTES_ALARM: \ 48 val = ctrl_inb(RMINAR); \ 49 break; \ 50 case RTC_HOURS: \ 51 val = ctrl_inb(RHRCNT); \ 52 break; \ 53 case RTC_HOURS_ALARM: \ 54 val = ctrl_inb(RHRAR); \ 55 break; \ 56 case RTC_DAY_OF_WEEK: \ 57 val = ctrl_inb(RWKCNT); \ 58 break; \ 59 case RTC_DAY_OF_MONTH: \ 60 val = ctrl_inb(RDAYCNT); \ 61 break; \ 62 case RTC_MONTH: \ 63 val = ctrl_inb(RMONCNT); \ 64 break; \ 65 case RTC_YEAR: \ 66 val = ctrl_in##s(RYRCNT); \ 67 break; \ 68 case RTC_REG_A: /* RTC_FREQ_SELECT */ \ 69 rcr2 = ctrl_inb(RCR2); \ 70 val = (rcr2 & RCR2_PESMASK) >> 4; \ 71 rcr1 = ctrl_inb(RCR1); \ 72 rcr1 = (rcr1 & (RCR1_CIE | RCR1_AIE)) | RCR1_AF;\ 73 retry = 0; \ 74 do { \ 75 ctrl_outb(rcr1, RCR1); /* clear CF */ \ 76 r64cnt = ctrl_inb(R64CNT); \ 77 } while((ctrl_inb(RCR1) & RCR1_CF) && retry++ < 1000);\ 78 r64cnt ^= RTC_BIT_INVERTED; \ 79 if(r64cnt == 0x7f || r64cnt == 0) \ 80 val |= RTC_UIP; \ 81 break; \ 82 case RTC_REG_B: /* RTC_CONTROL */ \ 83 rcr1 = ctrl_inb(RCR1); \ 84 rcr2 = ctrl_inb(RCR2); \ 85 if(rcr1 & RCR1_CIE) val |= RTC_UIE; \ 86 if(rcr1 & RCR1_AIE) val |= RTC_AIE; \ 87 if(rcr2 & RCR2_PESMASK) val |= RTC_PIE; \ 88 if(!(rcr2 & RCR2_START))val |= RTC_SET; \ 89 val |= RTC_24H; \ 90 break; \ 91 case RTC_REG_C: /* RTC_INTR_FLAGS */ \ 92 rcr1 = ctrl_inb(RCR1); \ 93 rcr1 &= ~(RCR1_CF | RCR1_AF); \ 94 ctrl_outb(rcr1, RCR1); \ 95 rcr2 = ctrl_inb(RCR2); \ 96 rcr2 &= ~RCR2_PEF; \ 97 ctrl_outb(rcr2, RCR2); \ 98 break; \ 99 case RTC_REG_D: /* RTC_VALID */ \ 100 /* Always valid ... */ \ 101 val = RTC_VRT; \ 102 break; \ 103 default: \ 104 break; \ 105 } \ 106 val; \ 107 }) 108 109 #define __CMOS_WRITE(val, addr, s) ({ \ 110 unsigned char rcr1,rcr2; \ 111 switch(addr) { \ 112 case RTC_SECONDS: \ 113 ctrl_outb(val, RSECCNT); \ 114 break; \ 115 case RTC_SECONDS_ALARM: \ 116 ctrl_outb(val, RSECAR); \ 117 break; \ 118 case RTC_MINUTES: \ 119 ctrl_outb(val, RMINCNT); \ 120 break; \ 121 case RTC_MINUTES_ALARM: \ 122 ctrl_outb(val, RMINAR); \ 123 break; \ 124 case RTC_HOURS: \ 125 ctrl_outb(val, RHRCNT); \ 126 break; \ 127 case RTC_HOURS_ALARM: \ 128 ctrl_outb(val, RHRAR); \ 129 break; \ 130 case RTC_DAY_OF_WEEK: \ 131 ctrl_outb(val, RWKCNT); \ 132 break; \ 133 case RTC_DAY_OF_MONTH: \ 134 ctrl_outb(val, RDAYCNT); \ 135 break; \ 136 case RTC_MONTH: \ 137 ctrl_outb(val, RMONCNT); \ 138 break; \ 139 case RTC_YEAR: \ 140 ctrl_out##s((ctrl_in##s(RYRCNT) & 0xff00) | (val & 0xff), RYRCNT);\ 141 break; \ 142 case RTC_REG_A: /* RTC_FREQ_SELECT */ \ 143 rcr2 = ctrl_inb(RCR2); \ 144 if((val & RTC_DIV_CTL) == RTC_DIV_RESET2) \ 145 rcr2 |= RCR2_RESET; \ 146 ctrl_outb(rcr2, RCR2); \ 147 break; \ 148 case RTC_REG_B: /* RTC_CONTROL */ \ 149 rcr1 = (ctrl_inb(RCR1) & 0x99) | RCR1_AF; \ 150 if(val & RTC_AIE) rcr1 |= RCR1_AIE; \ 151 else rcr1 &= ~RCR1_AIE; \ 152 if(val & RTC_UIE) rcr1 |= RCR1_CIE; \ 153 else rcr1 &= ~RCR1_CIE; \ 154 ctrl_outb(rcr1, RCR1); \ 155 rcr2 = ctrl_inb(RCR2); \ 156 if(val & RTC_SET) rcr2 &= ~RCR2_START; \ 157 else rcr2 |= RCR2_START; \ 158 ctrl_outb(rcr2, RCR2); \ 159 break; \ 160 case RTC_REG_C: /* RTC_INTR_FLAGS */ \ 161 break; \ 162 case RTC_REG_D: /* RTC_VALID */ \ 163 break; \ 164 default: \ 165 break; \ 166 } \ 167 }) 168 #endif /* _ASM_MC146818RTC_H */ 169