1/*
2 *  linux/include/asm-arm/arch-ebsa285/time.h
3 *
4 *  Copyright (C) 1998 Russell King.
5 *  Copyright (C) 1998 Phil Blundell
6 *
7 * CATS has a real-time clock, though the evaluation board doesn't.
8 *
9 * Changelog:
10 *  21-Mar-1998	RMK	Created
11 *  27-Aug-1998	PJB	CATS support
12 *  28-Dec-1998	APH	Made leds optional
13 *  20-Jan-1999	RMK	Started merge of EBSA285, CATS and NetWinder
14 *  16-Mar-1999	RMK	More support for EBSA285-like machines with RTCs in
15 */
16
17#define RTC_PORT(x)		(rtc_base+(x))
18#define RTC_ALWAYS_BCD		0
19
20#include <linux/mc146818rtc.h>
21
22#include <asm/hardware/dec21285.h>
23#include <asm/leds.h>
24#include <asm/mach-types.h>
25
26static int rtc_base;
27
28#define mSEC_10_from_14 ((14318180 + 100) / 200)
29
30static unsigned long isa_gettimeoffset(void)
31{
32	int count;
33
34	static int count_p = (mSEC_10_from_14/6);    /* for the first call after boot */
35	static unsigned long jiffies_p = 0;
36
37	/*
38	 * cache volatile jiffies temporarily; we have IRQs turned off.
39	 */
40	unsigned long jiffies_t;
41
42	/* timer count may underflow right here */
43	outb_p(0x00, 0x43);	/* latch the count ASAP */
44
45	count = inb_p(0x40);	/* read the latched count */
46
47	/*
48	 * We do this guaranteed double memory access instead of a _p
49	 * postfix in the previous port access. Wheee, hackady hack
50	 */
51 	jiffies_t = jiffies;
52
53	count |= inb_p(0x40) << 8;
54
55	/* Detect timer underflows.  If we haven't had a timer tick since
56	   the last time we were called, and time is apparently going
57	   backwards, the counter must have wrapped during this routine. */
58	if ((jiffies_t == jiffies_p) && (count > count_p))
59		count -= (mSEC_10_from_14/6);
60	else
61		jiffies_p = jiffies_t;
62
63	count_p = count;
64
65	count = (((mSEC_10_from_14/6)-1) - count) * tick;
66	count = (count + (mSEC_10_from_14/6)/2) / (mSEC_10_from_14/6);
67
68	return count;
69}
70
71static void isa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
72{
73	if (machine_is_netwinder())
74		do_leds();
75
76	do_timer(regs);
77	do_set_rtc();
78	do_profile(regs);
79}
80
81static unsigned long __init get_isa_cmos_time(void)
82{
83	unsigned int year, mon, day, hour, min, sec;
84	int i;
85
86	// check to see if the RTC makes sense.....
87	if ((CMOS_READ(RTC_VALID) & RTC_VRT) == 0)
88		return mktime(1970, 1, 1, 0, 0, 0);
89
90	/* The Linux interpretation of the CMOS clock register contents:
91	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
92	 * RTC registers show the second which has precisely just started.
93	 * Let's hope other operating systems interpret the RTC the same way.
94	 */
95	/* read RTC exactly on falling edge of update flag */
96	for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
97		if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
98			break;
99
100	for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
101		if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
102			break;
103
104	do { /* Isn't this overkill ? UIP above should guarantee consistency */
105		sec  = CMOS_READ(RTC_SECONDS);
106		min  = CMOS_READ(RTC_MINUTES);
107		hour = CMOS_READ(RTC_HOURS);
108		day  = CMOS_READ(RTC_DAY_OF_MONTH);
109		mon  = CMOS_READ(RTC_MONTH);
110		year = CMOS_READ(RTC_YEAR);
111	} while (sec != CMOS_READ(RTC_SECONDS));
112
113	if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
114		BCD_TO_BIN(sec);
115		BCD_TO_BIN(min);
116		BCD_TO_BIN(hour);
117		BCD_TO_BIN(day);
118		BCD_TO_BIN(mon);
119		BCD_TO_BIN(year);
120	}
121	if ((year += 1900) < 1970)
122		year += 100;
123	return mktime(year, mon, day, hour, min, sec);
124}
125
126static int
127set_isa_cmos_time(void)
128{
129	int retval = 0;
130	int real_seconds, real_minutes, cmos_minutes;
131	unsigned char save_control, save_freq_select;
132	unsigned long nowtime = xtime.tv_sec;
133
134	save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
135	CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
136
137	save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
138	CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
139
140	cmos_minutes = CMOS_READ(RTC_MINUTES);
141	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
142		BCD_TO_BIN(cmos_minutes);
143
144	/*
145	 * since we're only adjusting minutes and seconds,
146	 * don't interfere with hour overflow. This avoids
147	 * messing with unknown time zones but requires your
148	 * RTC not to be off by more than 15 minutes
149	 */
150	real_seconds = nowtime % 60;
151	real_minutes = nowtime / 60;
152	if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
153		real_minutes += 30;		/* correct for half hour time zone */
154	real_minutes %= 60;
155
156	if (abs(real_minutes - cmos_minutes) < 30) {
157		if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
158			BIN_TO_BCD(real_seconds);
159			BIN_TO_BCD(real_minutes);
160		}
161		CMOS_WRITE(real_seconds,RTC_SECONDS);
162		CMOS_WRITE(real_minutes,RTC_MINUTES);
163	} else
164		retval = -1;
165
166	/* The following flags have to be released exactly in this order,
167	 * otherwise the DS12887 (popular MC146818A clone with integrated
168	 * battery and quartz) will not reset the oscillator and will not
169	 * update precisely 500 ms later. You won't find this mentioned in
170	 * the Dallas Semiconductor data sheets, but who believes data
171	 * sheets anyway ...                           -- Markus Kuhn
172	 */
173	CMOS_WRITE(save_control, RTC_CONTROL);
174	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
175
176	return retval;
177}
178
179
180
181static unsigned long timer1_gettimeoffset (void)
182{
183	unsigned long value = LATCH - *CSR_TIMER1_VALUE;
184
185	return (tick * value) / LATCH;
186}
187
188static void timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
189{
190	*CSR_TIMER1_CLR = 0;
191
192	/* Do the LEDs things */
193	do_leds();
194	do_timer(regs);
195	do_set_rtc();
196	do_profile(regs);
197}
198
199/*
200 * Set up timer interrupt.
201 */
202static inline void setup_timer(void)
203{
204	int irq;
205
206	if (machine_is_co285() ||
207	    machine_is_personal_server())
208		/*
209		 * Add-in 21285s shouldn't access the RTC
210		 */
211		rtc_base = 0;
212	else
213		rtc_base = 0x70;
214
215	if (rtc_base) {
216		int reg_d, reg_b;
217
218		/*
219		 * Probe for the RTC.
220		 */
221		reg_d = CMOS_READ(RTC_REG_D);
222
223		/*
224		 * make sure the divider is set
225		 */
226		CMOS_WRITE(RTC_REF_CLCK_32KHZ, RTC_REG_A);
227
228		/*
229		 * Set control reg B
230		 *   (24 hour mode, update enabled)
231		 */
232		reg_b = CMOS_READ(RTC_REG_B) & 0x7f;
233		reg_b |= 2;
234		CMOS_WRITE(reg_b, RTC_REG_B);
235
236		if ((CMOS_READ(RTC_REG_A) & 0x7f) == RTC_REF_CLCK_32KHZ &&
237		    CMOS_READ(RTC_REG_B) == reg_b) {
238
239			/*
240			 * We have a RTC.  Check the battery
241			 */
242			if ((reg_d & 0x80) == 0)
243				printk(KERN_WARNING "RTC: *** warning: CMOS battery bad\n");
244
245			xtime.tv_sec = get_isa_cmos_time();
246			set_rtc = set_isa_cmos_time;
247		} else
248			rtc_base = 0;
249	}
250
251	if (machine_is_ebsa285() ||
252	    machine_is_co285() ||
253	    machine_is_personal_server()) {
254		gettimeoffset = timer1_gettimeoffset;
255
256		*CSR_TIMER1_CLR  = 0;
257		*CSR_TIMER1_LOAD = LATCH;
258		*CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16;
259
260		timer_irq.handler = timer1_interrupt;
261		irq = IRQ_TIMER1;
262	} else {
263		/* enable PIT timer */
264		/* set for periodic (4) and LSB/MSB write (0x30) */
265		outb(0x34, 0x43);
266		outb((mSEC_10_from_14/6) & 0xFF, 0x40);
267		outb((mSEC_10_from_14/6) >> 8, 0x40);
268
269		gettimeoffset = isa_gettimeoffset;
270		timer_irq.handler = isa_timer_interrupt;
271		irq = IRQ_ISA_TIMER;
272	}
273	setup_arm_irq(irq, &timer_irq);
274}
275