aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-sh/mc146818rtc.h
blob: 1707cfb2915d04fcccf357035689881ef71d2133 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/*
 * Machine dependent access functions for RTC registers.
 */
#ifndef _ASM_MC146818RTC_H
#define _ASM_MC146818RTC_H

#ifdef CONFIG_SH_MPC1211
#undef  _ASM_MC146818RTC_H
#undef  RTC_IRQ
#include <asm/mpc1211/mc146818rtc.h>
#else

#include <asm/rtc.h>

#define RTC_ALWAYS_BCD	1

/* FIXME:RTC Interrupt feature is not implemented yet. */
#undef  RTC_IRQ
#define RTC_IRQ		0

#if defined(CONFIG_CPU_SH3)
#define RTC_PORT(n)		(R64CNT+(n)*2)
#define CMOS_READ(addr)		__CMOS_READ(addr,b)
#define CMOS_WRITE(val,addr)	__CMOS_WRITE(val,addr,b)

#elif defined(CONFIG_SH_SECUREEDGE5410)
#include <asm/snapgear/io.h>

#define RTC_PORT(n)             SECUREEDGE_IOPORT_ADDR
#define CMOS_READ(addr)         secureedge5410_cmos_read(addr)
#define CMOS_WRITE(val,addr)    secureedge5410_cmos_write(val,addr)
extern unsigned char secureedge5410_cmos_read(int addr);
extern void secureedge5410_cmos_write(unsigned char val, int addr);

#elif defined(CONFIG_CPU_SH4)
#define RTC_PORT(n)		(R64CNT+(n)*4)
#define CMOS_READ(addr)		__CMOS_READ(addr,w)
#define CMOS_WRITE(val,addr)	__CMOS_WRITE(val,addr,w)
#endif

#define __CMOS_READ(addr, s) ({						\
	unsigned char val=0, rcr1, rcr2, r64cnt, retry;			\
	switch(addr) {							\
		case RTC_SECONDS:					\
			val = ctrl_inb(RSECCNT);			\
			break;						\
		case RTC_SECONDS_ALARM:					\
			val = ctrl_inb(RSECAR);				\
			break;						\
		case RTC_MINUTES:					\
			val = ctrl_inb(RMINCNT);			\
			break;						\
		case RTC_MINUTES_ALARM:					\
			val = ctrl_inb(RMINAR);				\
			break;						\
		case RTC_HOURS:						\
			val = ctrl_inb(RHRCNT);				\
			break;						\
		case RTC_HOURS_ALARM:					\
			val = ctrl_inb(RHRAR);				\
			break;						\
		case RTC_DAY_OF_WEEK:					\
			val = ctrl_inb(RWKCNT);				\
			break;						\
		case RTC_DAY_OF_MONTH:					\
			val = ctrl_inb(RDAYCNT);			\
			break;						\
		case RTC_MONTH:						\
			val = ctrl_inb(RMONCNT);			\
			break;						\
		case RTC_YEAR:						\
			val = ctrl_in##s(RYRCNT);			\
			break;						\
		case RTC_REG_A: /* RTC_FREQ_SELECT */			\
			rcr2 = ctrl_inb(RCR2);				\
			val = (rcr2 & RCR2_PESMASK) >> 4;		\
			rcr1 = ctrl_inb(RCR1);				\
			rcr1 = (rcr1 & (RCR1_CIE | RCR1_AIE)) | RCR1_AF;\
			retry = 0;					\
			do {						\
				ctrl_outb(rcr1, RCR1); /* clear CF */	\
				r64cnt = ctrl_inb(R64CNT);		\
			} while((ctrl_inb(RCR1) & RCR1_CF) && retry++ < 1000);\
			r64cnt ^= RTC_BIT_INVERTED;			\
			if(r64cnt == 0x7f || r64cnt == 0)		\
				val |= RTC_UIP;				\
			break;						\
		case RTC_REG_B:	/* RTC_CONTROL */			\
			rcr1 = ctrl_inb(RCR1);				\
			rcr2 = ctrl_inb(RCR2);				\
			if(rcr1 & RCR1_CIE)	val |= RTC_UIE;		\
			if(rcr1 & RCR1_AIE)	val |= RTC_AIE;		\
			if(rcr2 & RCR2_PESMASK)	val |= RTC_PIE;		\
			if(!(rcr2 & RCR2_START))val |= RTC_SET;		\
			val |= RTC_24H;					\
			break;						\
		case RTC_REG_C:	/* RTC_INTR_FLAGS */			\
			rcr1 = ctrl_inb(RCR1);				\
			rcr1 &= ~(RCR1_CF | RCR1_AF);			\
			ctrl_outb(rcr1, RCR1);				\
			rcr2 = ctrl_inb(RCR2);				\
			rcr2 &= ~RCR2_PEF;				\
			ctrl_outb(rcr2, RCR2);				\
			break;						\
		case RTC_REG_D:	/* RTC_VALID */				\
			/* Always valid ... */				\
			val = RTC_VRT;					\
			break;						\
		default:						\
			break;						\
	}								\
	val;								\
})

#define __CMOS_WRITE(val, addr, s) ({					\
	unsigned char rcr1,rcr2;					\
	switch(addr) {							\
		case RTC_SECONDS:					\
			ctrl_outb(val, RSECCNT);			\
			break;						\
		case RTC_SECONDS_ALARM:					\
			ctrl_outb(val, RSECAR);				\
			break;						\
		case RTC_MINUTES:					\
			ctrl_outb(val, RMINCNT);			\
			break;						\
		case RTC_MINUTES_ALARM:					\
			ctrl_outb(val, RMINAR);				\
			break;						\
		case RTC_HOURS:						\
			ctrl_outb(val, RHRCNT);				\
			break;						\
		case RTC_HOURS_ALARM:					\
			ctrl_outb(val, RHRAR);				\
			break;						\
		case RTC_DAY_OF_WEEK:					\
			ctrl_outb(val, RWKCNT);				\
			break;						\
		case RTC_DAY_OF_MONTH:					\
			ctrl_outb(val, RDAYCNT);			\
			break;						\
		case RTC_MONTH:						\
			ctrl_outb(val, RMONCNT);			\
			break;						\
		case RTC_YEAR:						\
			ctrl_out##s((ctrl_in##s(RYRCNT) & 0xff00) | (val & 0xff), RYRCNT);\
			break;						\
		case RTC_REG_A: /* RTC_FREQ_SELECT */			\
			rcr2 = ctrl_inb(RCR2);				\
			if((val & RTC_DIV_CTL) == RTC_DIV_RESET2)	\
				rcr2 |= RCR2_RESET;			\
			ctrl_outb(rcr2, RCR2);				\
			break;						\
		case RTC_REG_B:	/* RTC_CONTROL */			\
			rcr1 = (ctrl_inb(RCR1) & 0x99) | RCR1_AF;	\
			if(val & RTC_AIE) rcr1 |= RCR1_AIE;		\
			else              rcr1 &= ~RCR1_AIE;		\
			if(val & RTC_UIE) rcr1 |= RCR1_CIE;		\
			else              rcr1 &= ~RCR1_CIE;		\
			ctrl_outb(rcr1, RCR1);				\
			rcr2 = ctrl_inb(RCR2);				\
			if(val & RTC_SET) rcr2 &= ~RCR2_START;		\
			else              rcr2 |= RCR2_START;		\
			ctrl_outb(rcr2, RCR2);				\
			break;						\
		case RTC_REG_C:	/* RTC_INTR_FLAGS */			\
			break;						\
		case RTC_REG_D:	/* RTC_VALID */				\
			break;						\
		default:						\
			break;						\
	}								\
})

#endif /* CONFIG_SH_MPC1211 */
#endif /* _ASM_MC146818RTC_H */