root/arch/m68k/mac/misc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cuda_pram_read_byte
  2. cuda_pram_write_byte
  3. pmu_pram_read_byte
  4. pmu_pram_write_byte
  5. via_rtc_recv
  6. via_rtc_send
  7. via_rtc_command
  8. via_pram_read_byte
  9. via_pram_write_byte
  10. via_read_time
  11. via_set_rtc_time
  12. via_shutdown
  13. oss_shutdown
  14. cuda_restart
  15. cuda_shutdown
  16. mac_pram_read_byte
  17. mac_pram_write_byte
  18. mac_pram_get_size
  19. mac_poweroff
  20. mac_reset
  21. unmktime
  22. mac_hwclk

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

/* [<][>][^][v][top][bottom][index][help] */