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