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