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