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