Merge branches 'work.misc' and 'work.dcache' of git://git.kernel.org/pub/scm/linux...
[sfrench/cifs-2.6.git] / arch / powerpc / platforms / powermac / time.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Support for periodic interrupts (100 per second) and for getting
4  * the current time from the RTC on Power Macintoshes.
5  *
6  * We use the decrementer register for our periodic interrupts.
7  *
8  * Paul Mackerras       August 1996.
9  * Copyright (C) 1996 Paul Mackerras.
10  * Copyright (C) 2003-2005 Benjamin Herrenschmidt.
11  *
12  */
13 #include <linux/errno.h>
14 #include <linux/sched.h>
15 #include <linux/kernel.h>
16 #include <linux/param.h>
17 #include <linux/string.h>
18 #include <linux/mm.h>
19 #include <linux/init.h>
20 #include <linux/time.h>
21 #include <linux/adb.h>
22 #include <linux/cuda.h>
23 #include <linux/pmu.h>
24 #include <linux/interrupt.h>
25 #include <linux/hardirq.h>
26 #include <linux/rtc.h>
27
28 #include <asm/sections.h>
29 #include <asm/prom.h>
30 #include <asm/io.h>
31 #include <asm/pgtable.h>
32 #include <asm/machdep.h>
33 #include <asm/time.h>
34 #include <asm/nvram.h>
35 #include <asm/smu.h>
36
37 #undef DEBUG
38
39 #ifdef DEBUG
40 #define DBG(x...) printk(x)
41 #else
42 #define DBG(x...)
43 #endif
44
45 /*
46  * Offset between Unix time (1970-based) and Mac time (1904-based). Cuda and PMU
47  * times wrap in 2040. If we need to handle later times, the read_time functions
48  * need to be changed to interpret wrapped times as post-2040.
49  */
50 #define RTC_OFFSET      2082844800
51
52 /*
53  * Calibrate the decrementer frequency with the VIA timer 1.
54  */
55 #define VIA_TIMER_FREQ_6        4700000 /* time 1 frequency * 6 */
56
57 /* VIA registers */
58 #define RS              0x200           /* skip between registers */
59 #define T1CL            (4*RS)          /* Timer 1 ctr/latch (low 8 bits) */
60 #define T1CH            (5*RS)          /* Timer 1 counter (high 8 bits) */
61 #define T1LL            (6*RS)          /* Timer 1 latch (low 8 bits) */
62 #define T1LH            (7*RS)          /* Timer 1 latch (high 8 bits) */
63 #define ACR             (11*RS)         /* Auxiliary control register */
64 #define IFR             (13*RS)         /* Interrupt flag register */
65
66 /* Bits in ACR */
67 #define T1MODE          0xc0            /* Timer 1 mode */
68 #define T1MODE_CONT     0x40            /*  continuous interrupts */
69
70 /* Bits in IFR and IER */
71 #define T1_INT          0x40            /* Timer 1 interrupt */
72
73 long __init pmac_time_init(void)
74 {
75         s32 delta = 0;
76 #ifdef CONFIG_NVRAM
77         int dst;
78         
79         delta = ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x9)) << 16;
80         delta |= ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xa)) << 8;
81         delta |= pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xb);
82         if (delta & 0x00800000UL)
83                 delta |= 0xFF000000UL;
84         dst = ((pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x8) & 0x80) != 0);
85         printk("GMT Delta read from XPRAM: %d minutes, DST: %s\n", delta/60,
86                 dst ? "on" : "off");
87 #endif
88         return delta;
89 }
90
91 #ifdef CONFIG_ADB_CUDA
92 static time64_t cuda_get_time(void)
93 {
94         struct adb_request req;
95         time64_t now;
96
97         if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0)
98                 return 0;
99         while (!req.complete)
100                 cuda_poll();
101         if (req.reply_len != 7)
102                 printk(KERN_ERR "cuda_get_time: got %d byte reply\n",
103                        req.reply_len);
104         now = (u32)((req.reply[3] << 24) + (req.reply[4] << 16) +
105                     (req.reply[5] << 8) + req.reply[6]);
106         /* it's either after year 2040, or the RTC has gone backwards */
107         WARN_ON(now < RTC_OFFSET);
108
109         return now - RTC_OFFSET;
110 }
111
112 #define cuda_get_rtc_time(tm)   rtc_time64_to_tm(cuda_get_time(), (tm))
113
114 static int cuda_set_rtc_time(struct rtc_time *tm)
115 {
116         u32 nowtime;
117         struct adb_request req;
118
119         nowtime = lower_32_bits(rtc_tm_to_time64(tm) + RTC_OFFSET);
120         if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME,
121                          nowtime >> 24, nowtime >> 16, nowtime >> 8,
122                          nowtime) < 0)
123                 return -ENXIO;
124         while (!req.complete)
125                 cuda_poll();
126         if ((req.reply_len != 3) && (req.reply_len != 7))
127                 printk(KERN_ERR "cuda_set_rtc_time: got %d byte reply\n",
128                        req.reply_len);
129         return 0;
130 }
131
132 #else
133 #define cuda_get_time()         0
134 #define cuda_get_rtc_time(tm)
135 #define cuda_set_rtc_time(tm)   0
136 #endif
137
138 #ifdef CONFIG_ADB_PMU
139 static time64_t pmu_get_time(void)
140 {
141         struct adb_request req;
142         time64_t now;
143
144         if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0)
145                 return 0;
146         pmu_wait_complete(&req);
147         if (req.reply_len != 4)
148                 printk(KERN_ERR "pmu_get_time: got %d byte reply from PMU\n",
149                        req.reply_len);
150         now = (u32)((req.reply[0] << 24) + (req.reply[1] << 16) +
151                     (req.reply[2] << 8) + req.reply[3]);
152
153         /* it's either after year 2040, or the RTC has gone backwards */
154         WARN_ON(now < RTC_OFFSET);
155
156         return now - RTC_OFFSET;
157 }
158
159 #define pmu_get_rtc_time(tm)    rtc_time64_to_tm(pmu_get_time(), (tm))
160
161 static int pmu_set_rtc_time(struct rtc_time *tm)
162 {
163         u32 nowtime;
164         struct adb_request req;
165
166         nowtime = lower_32_bits(rtc_tm_to_time64(tm) + RTC_OFFSET);
167         if (pmu_request(&req, NULL, 5, PMU_SET_RTC, nowtime >> 24,
168                         nowtime >> 16, nowtime >> 8, nowtime) < 0)
169                 return -ENXIO;
170         pmu_wait_complete(&req);
171         if (req.reply_len != 0)
172                 printk(KERN_ERR "pmu_set_rtc_time: %d byte reply from PMU\n",
173                        req.reply_len);
174         return 0;
175 }
176
177 #else
178 #define pmu_get_time()          0
179 #define pmu_get_rtc_time(tm)
180 #define pmu_set_rtc_time(tm)    0
181 #endif
182
183 #ifdef CONFIG_PMAC_SMU
184 static time64_t smu_get_time(void)
185 {
186         struct rtc_time tm;
187
188         if (smu_get_rtc_time(&tm, 1))
189                 return 0;
190         return rtc_tm_to_time64(&tm);
191 }
192
193 #else
194 #define smu_get_time()                  0
195 #define smu_get_rtc_time(tm, spin)
196 #define smu_set_rtc_time(tm, spin)      0
197 #endif
198
199 /* Can't be __init, it's called when suspending and resuming */
200 time64_t pmac_get_boot_time(void)
201 {
202         /* Get the time from the RTC, used only at boot time */
203         switch (sys_ctrler) {
204         case SYS_CTRLER_CUDA:
205                 return cuda_get_time();
206         case SYS_CTRLER_PMU:
207                 return pmu_get_time();
208         case SYS_CTRLER_SMU:
209                 return smu_get_time();
210         default:
211                 return 0;
212         }
213 }
214
215 void pmac_get_rtc_time(struct rtc_time *tm)
216 {
217         /* Get the time from the RTC, used only at boot time */
218         switch (sys_ctrler) {
219         case SYS_CTRLER_CUDA:
220                 cuda_get_rtc_time(tm);
221                 break;
222         case SYS_CTRLER_PMU:
223                 pmu_get_rtc_time(tm);
224                 break;
225         case SYS_CTRLER_SMU:
226                 smu_get_rtc_time(tm, 1);
227                 break;
228         default:
229                 ;
230         }
231 }
232
233 int pmac_set_rtc_time(struct rtc_time *tm)
234 {
235         switch (sys_ctrler) {
236         case SYS_CTRLER_CUDA:
237                 return cuda_set_rtc_time(tm);
238         case SYS_CTRLER_PMU:
239                 return pmu_set_rtc_time(tm);
240         case SYS_CTRLER_SMU:
241                 return smu_set_rtc_time(tm, 1);
242         default:
243                 return -ENODEV;
244         }
245 }
246
247 #ifdef CONFIG_PPC32
248 /*
249  * Calibrate the decrementer register using VIA timer 1.
250  * This is used both on powermacs and CHRP machines.
251  */
252 int __init via_calibrate_decr(void)
253 {
254         struct device_node *vias;
255         volatile unsigned char __iomem *via;
256         int count = VIA_TIMER_FREQ_6 / 100;
257         unsigned int dstart, dend;
258         struct resource rsrc;
259
260         vias = of_find_node_by_name(NULL, "via-cuda");
261         if (vias == NULL)
262                 vias = of_find_node_by_name(NULL, "via-pmu");
263         if (vias == NULL)
264                 vias = of_find_node_by_name(NULL, "via");
265         if (vias == NULL || of_address_to_resource(vias, 0, &rsrc)) {
266                 of_node_put(vias);
267                 return 0;
268         }
269         of_node_put(vias);
270         via = ioremap(rsrc.start, resource_size(&rsrc));
271         if (via == NULL) {
272                 printk(KERN_ERR "Failed to map VIA for timer calibration !\n");
273                 return 0;
274         }
275
276         /* set timer 1 for continuous interrupts */
277         out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT);
278         /* set the counter to a small value */
279         out_8(&via[T1CH], 2);
280         /* set the latch to `count' */
281         out_8(&via[T1LL], count);
282         out_8(&via[T1LH], count >> 8);
283         /* wait until it hits 0 */
284         while ((in_8(&via[IFR]) & T1_INT) == 0)
285                 ;
286         dstart = get_dec();
287         /* clear the interrupt & wait until it hits 0 again */
288         in_8(&via[T1CL]);
289         while ((in_8(&via[IFR]) & T1_INT) == 0)
290                 ;
291         dend = get_dec();
292
293         ppc_tb_freq = (dstart - dend) * 100 / 6;
294
295         iounmap(via);
296
297         return 1;
298 }
299 #endif
300
301 /*
302  * Query the OF and get the decr frequency.
303  */
304 void __init pmac_calibrate_decr(void)
305 {
306         generic_calibrate_decr();
307
308 #ifdef CONFIG_PPC32
309         /* We assume MacRISC2 machines have correct device-tree
310          * calibration. That's better since the VIA itself seems
311          * to be slightly off. --BenH
312          */
313         if (!of_machine_is_compatible("MacRISC2") &&
314             !of_machine_is_compatible("MacRISC3") &&
315             !of_machine_is_compatible("MacRISC4"))
316                 if (via_calibrate_decr())
317                         return;
318
319         /* Special case: QuickSilver G4s seem to have a badly calibrated
320          * timebase-frequency in OF, VIA is much better on these. We should
321          * probably implement calibration based on the KL timer on these
322          * machines anyway... -BenH
323          */
324         if (of_machine_is_compatible("PowerMac3,5"))
325                 if (via_calibrate_decr())
326                         return;
327 #endif
328 }