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