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