Merge tag 'nfsd-4.14' of git://linux-nfs.org/~bfields/linux
[sfrench/cifs-2.6.git] / arch / m68k / mac / misc.c
1 /*
2  * Miscellaneous Mac68K-specific stuff
3  */
4
5 #include <linux/types.h>
6 #include <linux/errno.h>
7 #include <linux/kernel.h>
8 #include <linux/delay.h>
9 #include <linux/sched.h>
10 #include <linux/time.h>
11 #include <linux/rtc.h>
12 #include <linux/mm.h>
13
14 #include <linux/adb.h>
15 #include <linux/cuda.h>
16 #include <linux/pmu.h>
17
18 #include <linux/uaccess.h>
19 #include <asm/io.h>
20 #include <asm/segment.h>
21 #include <asm/setup.h>
22 #include <asm/macintosh.h>
23 #include <asm/mac_via.h>
24 #include <asm/mac_oss.h>
25
26 #include <asm/machdep.h>
27
28 /* Offset between Unix time (1970-based) and Mac time (1904-based) */
29
30 #define RTC_OFFSET 2082844800
31
32 static void (*rom_reset)(void);
33
34 #ifdef CONFIG_ADB_CUDA
35 static long cuda_read_time(void)
36 {
37         struct adb_request req;
38         long time;
39
40         if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0)
41                 return 0;
42         while (!req.complete)
43                 cuda_poll();
44
45         time = (req.reply[3] << 24) | (req.reply[4] << 16)
46                 | (req.reply[5] << 8) | req.reply[6];
47         return time - RTC_OFFSET;
48 }
49
50 static void cuda_write_time(long data)
51 {
52         struct adb_request req;
53         data += RTC_OFFSET;
54         if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME,
55                         (data >> 24) & 0xFF, (data >> 16) & 0xFF,
56                         (data >> 8) & 0xFF, data & 0xFF) < 0)
57                 return;
58         while (!req.complete)
59                 cuda_poll();
60 }
61
62 static __u8 cuda_read_pram(int offset)
63 {
64         struct adb_request req;
65         if (cuda_request(&req, NULL, 4, CUDA_PACKET, CUDA_GET_PRAM,
66                         (offset >> 8) & 0xFF, offset & 0xFF) < 0)
67                 return 0;
68         while (!req.complete)
69                 cuda_poll();
70         return req.reply[3];
71 }
72
73 static void cuda_write_pram(int offset, __u8 data)
74 {
75         struct adb_request req;
76         if (cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_SET_PRAM,
77                         (offset >> 8) & 0xFF, offset & 0xFF, data) < 0)
78                 return;
79         while (!req.complete)
80                 cuda_poll();
81 }
82 #else
83 #define cuda_read_time() 0
84 #define cuda_write_time(n)
85 #define cuda_read_pram NULL
86 #define cuda_write_pram NULL
87 #endif
88
89 #ifdef CONFIG_ADB_PMU68K
90 static long pmu_read_time(void)
91 {
92         struct adb_request req;
93         long time;
94
95         if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0)
96                 return 0;
97         while (!req.complete)
98                 pmu_poll();
99
100         time = (req.reply[1] << 24) | (req.reply[2] << 16)
101                 | (req.reply[3] << 8) | req.reply[4];
102         return time - RTC_OFFSET;
103 }
104
105 static void pmu_write_time(long data)
106 {
107         struct adb_request req;
108         data += RTC_OFFSET;
109         if (pmu_request(&req, NULL, 5, PMU_SET_RTC,
110                         (data >> 24) & 0xFF, (data >> 16) & 0xFF,
111                         (data >> 8) & 0xFF, data & 0xFF) < 0)
112                 return;
113         while (!req.complete)
114                 pmu_poll();
115 }
116
117 static __u8 pmu_read_pram(int offset)
118 {
119         struct adb_request req;
120         if (pmu_request(&req, NULL, 3, PMU_READ_NVRAM,
121                         (offset >> 8) & 0xFF, offset & 0xFF) < 0)
122                 return 0;
123         while (!req.complete)
124                 pmu_poll();
125         return req.reply[3];
126 }
127
128 static void pmu_write_pram(int offset, __u8 data)
129 {
130         struct adb_request req;
131         if (pmu_request(&req, NULL, 4, PMU_WRITE_NVRAM,
132                         (offset >> 8) & 0xFF, offset & 0xFF, data) < 0)
133                 return;
134         while (!req.complete)
135                 pmu_poll();
136 }
137 #else
138 #define pmu_read_time() 0
139 #define pmu_write_time(n)
140 #define pmu_read_pram NULL
141 #define pmu_write_pram NULL
142 #endif
143
144 /*
145  * VIA PRAM/RTC access routines
146  *
147  * Must be called with interrupts disabled and
148  * the RTC should be enabled.
149  */
150
151 static __u8 via_pram_readbyte(void)
152 {
153         int     i,reg;
154         __u8    data;
155
156         reg = via1[vBufB] & ~VIA1B_vRTCClk;
157
158         /* Set the RTC data line to be an input. */
159
160         via1[vDirB] &= ~VIA1B_vRTCData;
161
162         /* The bits of the byte come out in MSB order */
163
164         data = 0;
165         for (i = 0 ; i < 8 ; i++) {
166                 via1[vBufB] = reg;
167                 via1[vBufB] = reg | VIA1B_vRTCClk;
168                 data = (data << 1) | (via1[vBufB] & VIA1B_vRTCData);
169         }
170
171         /* Return RTC data line to output state */
172
173         via1[vDirB] |= VIA1B_vRTCData;
174
175         return data;
176 }
177
178 static void via_pram_writebyte(__u8 data)
179 {
180         int     i,reg,bit;
181
182         reg = via1[vBufB] & ~(VIA1B_vRTCClk | VIA1B_vRTCData);
183
184         /* The bits of the byte go in in MSB order */
185
186         for (i = 0 ; i < 8 ; i++) {
187                 bit = data & 0x80? 1 : 0;
188                 data <<= 1;
189                 via1[vBufB] = reg | bit;
190                 via1[vBufB] = reg | bit | VIA1B_vRTCClk;
191         }
192 }
193
194 /*
195  * Execute a VIA PRAM/RTC command. For read commands
196  * data should point to a one-byte buffer for the
197  * resulting data. For write commands it should point
198  * to the data byte to for the command.
199  *
200  * This function disables all interrupts while running.
201  */
202
203 static void via_pram_command(int command, __u8 *data)
204 {
205         unsigned long flags;
206         int     is_read;
207
208         local_irq_save(flags);
209
210         /* Enable the RTC and make sure the strobe line is high */
211
212         via1[vBufB] = (via1[vBufB] | VIA1B_vRTCClk) & ~VIA1B_vRTCEnb;
213
214         if (command & 0xFF00) {         /* extended (two-byte) command */
215                 via_pram_writebyte((command & 0xFF00) >> 8);
216                 via_pram_writebyte(command & 0xFF);
217                 is_read = command & 0x8000;
218         } else {                        /* one-byte command */
219                 via_pram_writebyte(command);
220                 is_read = command & 0x80;
221         }
222         if (is_read) {
223                 *data = via_pram_readbyte();
224         } else {
225                 via_pram_writebyte(*data);
226         }
227
228         /* All done, disable the RTC */
229
230         via1[vBufB] |= VIA1B_vRTCEnb;
231
232         local_irq_restore(flags);
233 }
234
235 static __u8 via_read_pram(int offset)
236 {
237         return 0;
238 }
239
240 static void via_write_pram(int offset, __u8 data)
241 {
242 }
243
244 /*
245  * Return the current time in seconds since January 1, 1904.
246  *
247  * This only works on machines with the VIA-based PRAM/RTC, which
248  * is basically any machine with Mac II-style ADB.
249  */
250
251 static long via_read_time(void)
252 {
253         union {
254                 __u8 cdata[4];
255                 long idata;
256         } result, last_result;
257         int count = 1;
258
259         via_pram_command(0x81, &last_result.cdata[3]);
260         via_pram_command(0x85, &last_result.cdata[2]);
261         via_pram_command(0x89, &last_result.cdata[1]);
262         via_pram_command(0x8D, &last_result.cdata[0]);
263
264         /*
265          * The NetBSD guys say to loop until you get the same reading
266          * twice in a row.
267          */
268
269         while (1) {
270                 via_pram_command(0x81, &result.cdata[3]);
271                 via_pram_command(0x85, &result.cdata[2]);
272                 via_pram_command(0x89, &result.cdata[1]);
273                 via_pram_command(0x8D, &result.cdata[0]);
274
275                 if (result.idata == last_result.idata)
276                         return result.idata - RTC_OFFSET;
277
278                 if (++count > 10)
279                         break;
280
281                 last_result.idata = result.idata;
282         }
283
284         pr_err("via_read_time: failed to read a stable value; got 0x%08lx then 0x%08lx\n",
285                last_result.idata, result.idata);
286
287         return 0;
288 }
289
290 /*
291  * Set the current time to a number of seconds since January 1, 1904.
292  *
293  * This only works on machines with the VIA-based PRAM/RTC, which
294  * is basically any machine with Mac II-style ADB.
295  */
296
297 static void via_write_time(long time)
298 {
299         union {
300                 __u8  cdata[4];
301                 long  idata;
302         } data;
303         __u8    temp;
304
305         /* Clear the write protect bit */
306
307         temp = 0x55;
308         via_pram_command(0x35, &temp);
309
310         data.idata = time + RTC_OFFSET;
311         via_pram_command(0x01, &data.cdata[3]);
312         via_pram_command(0x05, &data.cdata[2]);
313         via_pram_command(0x09, &data.cdata[1]);
314         via_pram_command(0x0D, &data.cdata[0]);
315
316         /* Set the write protect bit */
317
318         temp = 0xD5;
319         via_pram_command(0x35, &temp);
320 }
321
322 static void via_shutdown(void)
323 {
324         if (rbv_present) {
325                 via2[rBufB] &= ~0x04;
326         } else {
327                 /* Direction of vDirB is output */
328                 via2[vDirB] |= 0x04;
329                 /* Send a value of 0 on that line */
330                 via2[vBufB] &= ~0x04;
331                 mdelay(1000);
332         }
333 }
334
335 /*
336  * FIXME: not sure how this is supposed to work exactly...
337  */
338
339 static void oss_shutdown(void)
340 {
341         oss->rom_ctrl = OSS_POWEROFF;
342 }
343
344 #ifdef CONFIG_ADB_CUDA
345
346 static void cuda_restart(void)
347 {
348         struct adb_request req;
349         if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_RESET_SYSTEM) < 0)
350                 return;
351         while (!req.complete)
352                 cuda_poll();
353 }
354
355 static void cuda_shutdown(void)
356 {
357         struct adb_request req;
358         if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_POWERDOWN) < 0)
359                 return;
360
361         /* Avoid infinite polling loop when PSU is not under Cuda control */
362         switch (macintosh_config->ident) {
363         case MAC_MODEL_C660:
364         case MAC_MODEL_Q605:
365         case MAC_MODEL_Q605_ACC:
366         case MAC_MODEL_P475:
367         case MAC_MODEL_P475F:
368                 return;
369         }
370
371         while (!req.complete)
372                 cuda_poll();
373 }
374
375 #endif /* CONFIG_ADB_CUDA */
376
377 #ifdef CONFIG_ADB_PMU68K
378
379 void pmu_restart(void)
380 {
381         struct adb_request req;
382         if (pmu_request(&req, NULL,
383                         2, PMU_SET_INTR_MASK, PMU_INT_ADB|PMU_INT_TICK) < 0)
384                 return;
385         while (!req.complete)
386                 pmu_poll();
387         if (pmu_request(&req, NULL, 1, PMU_RESET) < 0)
388                 return;
389         while (!req.complete)
390                 pmu_poll();
391 }
392
393 void pmu_shutdown(void)
394 {
395         struct adb_request req;
396         if (pmu_request(&req, NULL,
397                         2, PMU_SET_INTR_MASK, PMU_INT_ADB|PMU_INT_TICK) < 0)
398                 return;
399         while (!req.complete)
400                 pmu_poll();
401         if (pmu_request(&req, NULL, 5, PMU_SHUTDOWN, 'M', 'A', 'T', 'T') < 0)
402                 return;
403         while (!req.complete)
404                 pmu_poll();
405 }
406
407 #endif
408
409 /*
410  *-------------------------------------------------------------------
411  * Below this point are the generic routines; they'll dispatch to the
412  * correct routine for the hardware on which we're running.
413  *-------------------------------------------------------------------
414  */
415
416 void mac_pram_read(int offset, __u8 *buffer, int len)
417 {
418         __u8 (*func)(int);
419         int i;
420
421         switch(macintosh_config->adb_type) {
422         case MAC_ADB_PB1:
423         case MAC_ADB_PB2:
424                 func = pmu_read_pram; break;
425         case MAC_ADB_EGRET:
426         case MAC_ADB_CUDA:
427                 func = cuda_read_pram; break;
428         default:
429                 func = via_read_pram;
430         }
431         if (!func)
432                 return;
433         for (i = 0 ; i < len ; i++) {
434                 buffer[i] = (*func)(offset++);
435         }
436 }
437
438 void mac_pram_write(int offset, __u8 *buffer, int len)
439 {
440         void (*func)(int, __u8);
441         int i;
442
443         switch(macintosh_config->adb_type) {
444         case MAC_ADB_PB1:
445         case MAC_ADB_PB2:
446                 func = pmu_write_pram; break;
447         case MAC_ADB_EGRET:
448         case MAC_ADB_CUDA:
449                 func = cuda_write_pram; break;
450         default:
451                 func = via_write_pram;
452         }
453         if (!func)
454                 return;
455         for (i = 0 ; i < len ; i++) {
456                 (*func)(offset++, buffer[i]);
457         }
458 }
459
460 void mac_poweroff(void)
461 {
462         if (oss_present) {
463                 oss_shutdown();
464         } else if (macintosh_config->adb_type == MAC_ADB_II) {
465                 via_shutdown();
466 #ifdef CONFIG_ADB_CUDA
467         } else if (macintosh_config->adb_type == MAC_ADB_EGRET ||
468                    macintosh_config->adb_type == MAC_ADB_CUDA) {
469                 cuda_shutdown();
470 #endif
471 #ifdef CONFIG_ADB_PMU68K
472         } else if (macintosh_config->adb_type == MAC_ADB_PB1
473                 || macintosh_config->adb_type == MAC_ADB_PB2) {
474                 pmu_shutdown();
475 #endif
476         }
477
478         pr_crit("It is now safe to turn off your Macintosh.\n");
479         local_irq_disable();
480         while(1);
481 }
482
483 void mac_reset(void)
484 {
485         if (macintosh_config->adb_type == MAC_ADB_II) {
486                 unsigned long flags;
487
488                 /* need ROMBASE in booter */
489                 /* indeed, plus need to MAP THE ROM !! */
490
491                 if (mac_bi_data.rombase == 0)
492                         mac_bi_data.rombase = 0x40800000;
493
494                 /* works on some */
495                 rom_reset = (void *) (mac_bi_data.rombase + 0xa);
496
497                 if (macintosh_config->ident == MAC_MODEL_SE30) {
498                         /*
499                          * MSch: Machines known to crash on ROM reset ...
500                          */
501                 } else {
502                         local_irq_save(flags);
503
504                         rom_reset();
505
506                         local_irq_restore(flags);
507                 }
508 #ifdef CONFIG_ADB_CUDA
509         } else if (macintosh_config->adb_type == MAC_ADB_EGRET ||
510                    macintosh_config->adb_type == MAC_ADB_CUDA) {
511                 cuda_restart();
512 #endif
513 #ifdef CONFIG_ADB_PMU68K
514         } else if (macintosh_config->adb_type == MAC_ADB_PB1
515                 || macintosh_config->adb_type == MAC_ADB_PB2) {
516                 pmu_restart();
517 #endif
518         } else if (CPU_IS_030) {
519
520                 /* 030-specific reset routine.  The idea is general, but the
521                  * specific registers to reset are '030-specific.  Until I
522                  * have a non-030 machine, I can't test anything else.
523                  *  -- C. Scott Ananian <cananian@alumni.princeton.edu>
524                  */
525
526                 unsigned long rombase = 0x40000000;
527
528                 /* make a 1-to-1 mapping, using the transparent tran. reg. */
529                 unsigned long virt = (unsigned long) mac_reset;
530                 unsigned long phys = virt_to_phys(mac_reset);
531                 unsigned long addr = (phys&0xFF000000)|0x8777;
532                 unsigned long offset = phys-virt;
533                 local_irq_disable(); /* lets not screw this up, ok? */
534                 __asm__ __volatile__(".chip 68030\n\t"
535                                      "pmove %0,%/tt0\n\t"
536                                      ".chip 68k"
537                                      : : "m" (addr));
538                 /* Now jump to physical address so we can disable MMU */
539                 __asm__ __volatile__(
540                     ".chip 68030\n\t"
541                     "lea %/pc@(1f),%/a0\n\t"
542                     "addl %0,%/a0\n\t"/* fixup target address and stack ptr */
543                     "addl %0,%/sp\n\t"
544                     "pflusha\n\t"
545                     "jmp %/a0@\n\t" /* jump into physical memory */
546                     "0:.long 0\n\t" /* a constant zero. */
547                     /* OK.  Now reset everything and jump to reset vector. */
548                     "1:\n\t"
549                     "lea %/pc@(0b),%/a0\n\t"
550                     "pmove %/a0@, %/tc\n\t" /* disable mmu */
551                     "pmove %/a0@, %/tt0\n\t" /* disable tt0 */
552                     "pmove %/a0@, %/tt1\n\t" /* disable tt1 */
553                     "movel #0, %/a0\n\t"
554                     "movec %/a0, %/vbr\n\t" /* clear vector base register */
555                     "movec %/a0, %/cacr\n\t" /* disable caches */
556                     "movel #0x0808,%/a0\n\t"
557                     "movec %/a0, %/cacr\n\t" /* flush i&d caches */
558                     "movew #0x2700,%/sr\n\t" /* set up status register */
559                     "movel %1@(0x0),%/a0\n\t"/* load interrupt stack pointer */
560                     "movec %/a0, %/isp\n\t"
561                     "movel %1@(0x4),%/a0\n\t" /* load reset vector */
562                     "reset\n\t" /* reset external devices */
563                     "jmp %/a0@\n\t" /* jump to the reset vector */
564                     ".chip 68k"
565                     : : "r" (offset), "a" (rombase) : "a0");
566         }
567
568         /* should never get here */
569         pr_crit("Restart failed. Please restart manually.\n");
570         local_irq_disable();
571         while(1);
572 }
573
574 /*
575  * This function translates seconds since 1970 into a proper date.
576  *
577  * Algorithm cribbed from glibc2.1, __offtime().
578  */
579 #define SECS_PER_MINUTE (60)
580 #define SECS_PER_HOUR  (SECS_PER_MINUTE * 60)
581 #define SECS_PER_DAY   (SECS_PER_HOUR * 24)
582
583 static void unmktime(unsigned long time, long offset,
584                      int *yearp, int *monp, int *dayp,
585                      int *hourp, int *minp, int *secp)
586 {
587         /* How many days come before each month (0-12).  */
588         static const unsigned short int __mon_yday[2][13] =
589         {
590                 /* Normal years.  */
591                 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
592                 /* Leap years.  */
593                 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
594         };
595         long int days, rem, y, wday, yday;
596         const unsigned short int *ip;
597
598         days = time / SECS_PER_DAY;
599         rem = time % SECS_PER_DAY;
600         rem += offset;
601         while (rem < 0) {
602                 rem += SECS_PER_DAY;
603                 --days;
604         }
605         while (rem >= SECS_PER_DAY) {
606                 rem -= SECS_PER_DAY;
607                 ++days;
608         }
609         *hourp = rem / SECS_PER_HOUR;
610         rem %= SECS_PER_HOUR;
611         *minp = rem / SECS_PER_MINUTE;
612         *secp = rem % SECS_PER_MINUTE;
613         /* January 1, 1970 was a Thursday. */
614         wday = (4 + days) % 7; /* Day in the week. Not currently used */
615         if (wday < 0) wday += 7;
616         y = 1970;
617
618 #define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
619 #define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
620 #define __isleap(year)  \
621   ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
622
623         while (days < 0 || days >= (__isleap (y) ? 366 : 365))
624         {
625                 /* Guess a corrected year, assuming 365 days per year.  */
626                 long int yg = y + days / 365 - (days % 365 < 0);
627
628                 /* Adjust DAYS and Y to match the guessed year.  */
629                 days -= ((yg - y) * 365
630                          + LEAPS_THRU_END_OF (yg - 1)
631                          - LEAPS_THRU_END_OF (y - 1));
632                 y = yg;
633         }
634         *yearp = y - 1900;
635         yday = days; /* day in the year.  Not currently used. */
636         ip = __mon_yday[__isleap(y)];
637         for (y = 11; days < (long int) ip[y]; --y)
638                 continue;
639         days -= ip[y];
640         *monp = y;
641         *dayp = days + 1; /* day in the month */
642         return;
643 }
644
645 /*
646  * Read/write the hardware clock.
647  */
648
649 int mac_hwclk(int op, struct rtc_time *t)
650 {
651         unsigned long now;
652
653         if (!op) { /* read */
654                 switch (macintosh_config->adb_type) {
655                 case MAC_ADB_II:
656                 case MAC_ADB_IOP:
657                         now = via_read_time();
658                         break;
659                 case MAC_ADB_PB1:
660                 case MAC_ADB_PB2:
661                         now = pmu_read_time();
662                         break;
663                 case MAC_ADB_EGRET:
664                 case MAC_ADB_CUDA:
665                         now = cuda_read_time();
666                         break;
667                 default:
668                         now = 0;
669                 }
670
671                 t->tm_wday = 0;
672                 unmktime(now, 0,
673                          &t->tm_year, &t->tm_mon, &t->tm_mday,
674                          &t->tm_hour, &t->tm_min, &t->tm_sec);
675                 pr_debug("%s: read %04d-%02d-%-2d %02d:%02d:%02d\n",
676                          __func__, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
677                          t->tm_hour, t->tm_min, t->tm_sec);
678         } else { /* write */
679                 pr_debug("%s: tried to write %04d-%02d-%-2d %02d:%02d:%02d\n",
680                          __func__, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
681                          t->tm_hour, t->tm_min, t->tm_sec);
682
683                 now = mktime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
684                              t->tm_hour, t->tm_min, t->tm_sec);
685
686                 switch (macintosh_config->adb_type) {
687                 case MAC_ADB_II:
688                 case MAC_ADB_IOP:
689                         via_write_time(now);
690                         break;
691                 case MAC_ADB_EGRET:
692                 case MAC_ADB_CUDA:
693                         cuda_write_time(now);
694                         break;
695                 case MAC_ADB_PB1:
696                 case MAC_ADB_PB2:
697                         pmu_write_time(now);
698                         break;
699                 }
700         }
701         return 0;
702 }
703
704 /*
705  * Set minutes/seconds in the hardware clock
706  */
707
708 int mac_set_clock_mmss (unsigned long nowtime)
709 {
710         struct rtc_time now;
711
712         mac_hwclk(0, &now);
713         now.tm_sec = nowtime % 60;
714         now.tm_min = (nowtime / 60) % 60;
715         mac_hwclk(1, &now);
716
717         return 0;
718 }