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