fix to allow usb modules to compile
[linux-2.4.21-pre4.git] / arch / ppc / platforms / prep_time.c
1 /*
2  * BK Id: SCCS/s.prep_time.c 1.14 08/13/02 21:52:55 paulus
3  */
4 /*
5  *  arch/ppc/platforms/prep_time.c
6  *
7  *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
8  *
9  * Adapted for PowerPC (PReP) by Gary Thomas
10  * Modified by Cort Dougan (cort@cs.nmt.edu).
11  * Copied and modified from arch/i386/kernel/time.c
12  */
13
14 #include <linux/errno.h>
15 #include <linux/sched.h>
16 #include <linux/kernel.h>
17 #include <linux/param.h>
18 #include <linux/string.h>
19 #include <linux/mm.h>
20 #include <linux/interrupt.h>
21 #include <linux/time.h>
22 #include <linux/timex.h>
23 #include <linux/kernel_stat.h>
24 #include <linux/init.h>
25
26 #include <asm/sections.h>
27 #include <asm/segment.h>
28 #include <asm/io.h>
29 #include <asm/processor.h>
30 #include <asm/machdep.h>
31 #include <asm/prep_nvram.h>
32 #include <asm/mk48t59.h>
33
34 #include <asm/time.h>
35
36 extern spinlock_t rtc_lock;
37
38 /*
39  * The motorola uses the m48t18 rtc (includes DS1643) whose registers
40  * are at a higher end of nvram (1ff8-1fff) than the ibm mc146818
41  * rtc (ds1386) which has regs at addr 0-d).  The intel gets
42  * past this because the bios emulates the mc146818.
43  *
44  * Why in the world did they have to use different clocks?
45  *
46  * Right now things are hacked to check which machine we're on then
47  * use the appropriate macro.  This is very very ugly and I should
48  * probably have a function that checks which machine we're on then
49  * does things correctly transparently or a function pointer which
50  * is setup at boot time to use the correct addresses.
51  * -- Cort
52  */
53
54 /*
55  * Set the hardware clock. -- Cort
56  */
57 __prep
58 int mc146818_set_rtc_time(unsigned long nowtime)
59 {
60         unsigned char save_control, save_freq_select;
61         struct rtc_time tm;
62
63         spin_lock(&rtc_lock);
64         to_tm(nowtime, &tm);
65
66         /* tell the clock it's being set */
67         save_control = CMOS_READ(RTC_CONTROL);
68
69         CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
70
71         /* stop and reset prescaler */
72         save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
73
74         CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
75
76         tm.tm_year = (tm.tm_year - 1900) % 100;
77         if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
78                 BIN_TO_BCD(tm.tm_sec);
79                 BIN_TO_BCD(tm.tm_min);
80                 BIN_TO_BCD(tm.tm_hour);
81                 BIN_TO_BCD(tm.tm_mon);
82                 BIN_TO_BCD(tm.tm_mday);
83                 BIN_TO_BCD(tm.tm_year);
84         }
85         CMOS_WRITE(tm.tm_sec,  RTC_SECONDS);
86         CMOS_WRITE(tm.tm_min,  RTC_MINUTES);
87         CMOS_WRITE(tm.tm_hour, RTC_HOURS);
88         CMOS_WRITE(tm.tm_mon,  RTC_MONTH);
89         CMOS_WRITE(tm.tm_mday, RTC_DAY_OF_MONTH);
90         CMOS_WRITE(tm.tm_year, RTC_YEAR);
91
92         /* The following flags have to be released exactly in this order,
93          * otherwise the DS12887 (popular MC146818A clone with integrated
94          * battery and quartz) will not reset the oscillator and will not
95          * update precisely 500 ms later. You won't find this mentioned in
96          * the Dallas Semiconductor data sheets, but who believes data
97          * sheets anyway ...                           -- Markus Kuhn
98          */
99         CMOS_WRITE(save_control,     RTC_CONTROL);
100         CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
101         spin_unlock(&rtc_lock);
102
103         return 0;
104 }
105
106 __prep
107 unsigned long mc146818_get_rtc_time(void)
108 {
109         unsigned int year, mon, day, hour, min, sec;
110         int uip, i;
111
112         /* The Linux interpretation of the CMOS clock register contents:
113          * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
114          * RTC registers show the second which has precisely just started.
115          * Let's hope other operating systems interpret the RTC the same way.
116          */
117
118         /* Since the UIP flag is set for about 2.2 ms and the clock
119          * is typically written with a precision of 1 jiffy, trying
120          * to obtain a precision better than a few milliseconds is 
121          * an illusion. Only consistency is interesting, this also
122          * allows to use the routine for /dev/rtc without a potential
123          * 1 second kernel busy loop triggered by any reader of /dev/rtc. 
124          */
125
126         for ( i = 0; i<1000000; i++) {
127                 uip = CMOS_READ(RTC_FREQ_SELECT);
128                 sec = CMOS_READ(RTC_SECONDS);
129                 min = CMOS_READ(RTC_MINUTES);
130                 hour = CMOS_READ(RTC_HOURS);
131                 day = CMOS_READ(RTC_DAY_OF_MONTH);
132                 mon = CMOS_READ(RTC_MONTH);
133                 year = CMOS_READ(RTC_YEAR);
134                 uip |= CMOS_READ(RTC_FREQ_SELECT);
135                 if ((uip & RTC_UIP)==0) break;
136         }
137
138         if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
139             || RTC_ALWAYS_BCD)
140         {
141                 BCD_TO_BIN(sec);
142                 BCD_TO_BIN(min);
143                 BCD_TO_BIN(hour);
144                 BCD_TO_BIN(day);
145                 BCD_TO_BIN(mon);
146                 BCD_TO_BIN(year);
147         }
148         if ((year += 1900) < 1970)
149                 year += 100;
150         return mktime(year, mon, day, hour, min, sec);
151 }
152
153 __prep
154 int mk48t59_set_rtc_time(unsigned long nowtime)
155 {
156         unsigned char save_control;
157         struct rtc_time tm;
158
159         spin_lock(&rtc_lock);
160         to_tm(nowtime, &tm);
161
162         /* tell the clock it's being written */
163         save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
164
165         ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
166                              (save_control | MK48T59_RTC_CA_WRITE));
167
168         tm.tm_year = (tm.tm_year - 1900) % 100;
169         BIN_TO_BCD(tm.tm_sec);
170         BIN_TO_BCD(tm.tm_min);
171         BIN_TO_BCD(tm.tm_hour);
172         BIN_TO_BCD(tm.tm_mon);
173         BIN_TO_BCD(tm.tm_mday);
174         BIN_TO_BCD(tm.tm_year);
175
176         ppc_md.nvram_write_val(MK48T59_RTC_SECONDS,      tm.tm_sec);
177         ppc_md.nvram_write_val(MK48T59_RTC_MINUTES,      tm.tm_min);
178         ppc_md.nvram_write_val(MK48T59_RTC_HOURS,        tm.tm_hour);
179         ppc_md.nvram_write_val(MK48T59_RTC_MONTH,        tm.tm_mon);
180         ppc_md.nvram_write_val(MK48T59_RTC_DAY_OF_MONTH, tm.tm_mday);
181         ppc_md.nvram_write_val(MK48T59_RTC_YEAR,         tm.tm_year);
182
183         /* Turn off the write bit. */
184         ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
185         spin_unlock(&rtc_lock);
186
187         return 0;
188 }
189
190 __prep
191 unsigned long mk48t59_get_rtc_time(void)
192 {
193         unsigned char save_control;
194         unsigned int year, mon, day, hour, min, sec;
195
196         /* Simple: freeze the clock, read it and allow updates again */
197         save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
198         save_control &= ~MK48T59_RTC_CA_READ;
199         ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
200
201         /* Set the register to read the value. */
202         ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
203                              (save_control | MK48T59_RTC_CA_READ));
204
205         sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
206         min = ppc_md.nvram_read_val(MK48T59_RTC_MINUTES);
207         hour = ppc_md.nvram_read_val(MK48T59_RTC_HOURS);
208         day = ppc_md.nvram_read_val(MK48T59_RTC_DAY_OF_MONTH);
209         mon = ppc_md.nvram_read_val(MK48T59_RTC_MONTH);
210         year = ppc_md.nvram_read_val(MK48T59_RTC_YEAR);
211
212         /* Let the time values change again. */
213         ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
214
215         BCD_TO_BIN(sec);
216         BCD_TO_BIN(min);
217         BCD_TO_BIN(hour);
218         BCD_TO_BIN(day);
219         BCD_TO_BIN(mon);
220         BCD_TO_BIN(year);
221
222         year = year + 1900;
223         if (year < 1970) {
224                 year += 100;
225         }
226
227         return mktime(year, mon, day, hour, min, sec);
228 }