misc.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. /*
  2. * Miscellaneous Mac68K-specific stuff
  3. */
  4. #include <linux/config.h>
  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/slab.h>
  12. #include <linux/time.h>
  13. #include <linux/rtc.h>
  14. #include <linux/mm.h>
  15. #include <linux/adb.h>
  16. #include <linux/cuda.h>
  17. #include <linux/pmu.h>
  18. #include <asm/uaccess.h>
  19. #include <asm/io.h>
  20. #include <asm/rtc.h>
  21. #include <asm/system.h>
  22. #include <asm/segment.h>
  23. #include <asm/setup.h>
  24. #include <asm/macintosh.h>
  25. #include <asm/mac_via.h>
  26. #include <asm/mac_oss.h>
  27. #define BOOTINFO_COMPAT_1_0
  28. #include <asm/bootinfo.h>
  29. #include <asm/machdep.h>
  30. /* Offset between Unix time (1970-based) and Mac time (1904-based) */
  31. #define RTC_OFFSET 2082844800
  32. extern struct mac_booter_data mac_bi_data;
  33. static void (*rom_reset)(void);
  34. #ifdef CONFIG_ADB
  35. /*
  36. * Return the current time as the number of seconds since January 1, 1904.
  37. */
  38. static long adb_read_time(void)
  39. {
  40. volatile struct adb_request req;
  41. long time;
  42. adb_request((struct adb_request *) &req, NULL,
  43. ADBREQ_RAW|ADBREQ_SYNC,
  44. 2, CUDA_PACKET, CUDA_GET_TIME);
  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. * Set the current system time
  51. */
  52. static void adb_write_time(long data)
  53. {
  54. volatile struct adb_request req;
  55. data += RTC_OFFSET;
  56. adb_request((struct adb_request *) &req, NULL,
  57. ADBREQ_RAW|ADBREQ_SYNC,
  58. 6, CUDA_PACKET, CUDA_SET_TIME,
  59. (data >> 24) & 0xFF, (data >> 16) & 0xFF,
  60. (data >> 8) & 0xFF, data & 0xFF);
  61. }
  62. /*
  63. * Get a byte from the NVRAM
  64. */
  65. static __u8 adb_read_pram(int offset)
  66. {
  67. volatile struct adb_request req;
  68. adb_request((struct adb_request *) &req, NULL,
  69. ADBREQ_RAW|ADBREQ_SYNC,
  70. 4, CUDA_PACKET, CUDA_GET_PRAM,
  71. (offset >> 8) & 0xFF, offset & 0xFF);
  72. return req.reply[3];
  73. }
  74. /*
  75. * Write a byte to the NVRAM
  76. */
  77. static void adb_write_pram(int offset, __u8 data)
  78. {
  79. volatile struct adb_request req;
  80. adb_request((struct adb_request *) &req, NULL,
  81. ADBREQ_RAW|ADBREQ_SYNC,
  82. 5, CUDA_PACKET, CUDA_SET_PRAM,
  83. (offset >> 8) & 0xFF, offset & 0xFF,
  84. data);
  85. }
  86. #endif /* CONFIG_ADB */
  87. /*
  88. * VIA PRAM/RTC access routines
  89. *
  90. * Must be called with interrupts disabled and
  91. * the RTC should be enabled.
  92. */
  93. static __u8 via_pram_readbyte(void)
  94. {
  95. int i,reg;
  96. __u8 data;
  97. reg = via1[vBufB] & ~VIA1B_vRTCClk;
  98. /* Set the RTC data line to be an input. */
  99. via1[vDirB] &= ~VIA1B_vRTCData;
  100. /* The bits of the byte come out in MSB order */
  101. data = 0;
  102. for (i = 0 ; i < 8 ; i++) {
  103. via1[vBufB] = reg;
  104. via1[vBufB] = reg | VIA1B_vRTCClk;
  105. data = (data << 1) | (via1[vBufB] & VIA1B_vRTCData);
  106. }
  107. /* Return RTC data line to output state */
  108. via1[vDirB] |= VIA1B_vRTCData;
  109. return data;
  110. }
  111. static void via_pram_writebyte(__u8 data)
  112. {
  113. int i,reg,bit;
  114. reg = via1[vBufB] & ~(VIA1B_vRTCClk | VIA1B_vRTCData);
  115. /* The bits of the byte go in in MSB order */
  116. for (i = 0 ; i < 8 ; i++) {
  117. bit = data & 0x80? 1 : 0;
  118. data <<= 1;
  119. via1[vBufB] = reg | bit;
  120. via1[vBufB] = reg | bit | VIA1B_vRTCClk;
  121. }
  122. }
  123. /*
  124. * Execute a VIA PRAM/RTC command. For read commands
  125. * data should point to a one-byte buffer for the
  126. * resulting data. For write commands it should point
  127. * to the data byte to for the command.
  128. *
  129. * This function disables all interrupts while running.
  130. */
  131. static void via_pram_command(int command, __u8 *data)
  132. {
  133. unsigned long flags;
  134. int is_read;
  135. local_irq_save(flags);
  136. /* Enable the RTC and make sure the strobe line is high */
  137. via1[vBufB] = (via1[vBufB] | VIA1B_vRTCClk) & ~VIA1B_vRTCEnb;
  138. if (command & 0xFF00) { /* extended (two-byte) command */
  139. via_pram_writebyte((command & 0xFF00) >> 8);
  140. via_pram_writebyte(command & 0xFF);
  141. is_read = command & 0x8000;
  142. } else { /* one-byte command */
  143. via_pram_writebyte(command);
  144. is_read = command & 0x80;
  145. }
  146. if (is_read) {
  147. *data = via_pram_readbyte();
  148. } else {
  149. via_pram_writebyte(*data);
  150. }
  151. /* All done, disable the RTC */
  152. via1[vBufB] |= VIA1B_vRTCEnb;
  153. local_irq_restore(flags);
  154. }
  155. static __u8 via_read_pram(int offset)
  156. {
  157. return 0;
  158. }
  159. static void via_write_pram(int offset, __u8 data)
  160. {
  161. }
  162. /*
  163. * Return the current time in seconds since January 1, 1904.
  164. *
  165. * This only works on machines with the VIA-based PRAM/RTC, which
  166. * is basically any machine with Mac II-style ADB.
  167. */
  168. static long via_read_time(void)
  169. {
  170. union {
  171. __u8 cdata[4];
  172. long idata;
  173. } result, last_result;
  174. int ct;
  175. /*
  176. * The NetBSD guys say to loop until you get the same reading
  177. * twice in a row.
  178. */
  179. ct = 0;
  180. do {
  181. if (++ct > 10) {
  182. printk("via_read_time: couldn't get valid time, "
  183. "last read = 0x%08lx and 0x%08lx\n",
  184. last_result.idata, result.idata);
  185. break;
  186. }
  187. last_result.idata = result.idata;
  188. result.idata = 0;
  189. via_pram_command(0x81, &result.cdata[3]);
  190. via_pram_command(0x85, &result.cdata[2]);
  191. via_pram_command(0x89, &result.cdata[1]);
  192. via_pram_command(0x8D, &result.cdata[0]);
  193. } while (result.idata != last_result.idata);
  194. return result.idata - RTC_OFFSET;
  195. }
  196. /*
  197. * Set the current time to a number of seconds since January 1, 1904.
  198. *
  199. * This only works on machines with the VIA-based PRAM/RTC, which
  200. * is basically any machine with Mac II-style ADB.
  201. */
  202. static void via_write_time(long time)
  203. {
  204. union {
  205. __u8 cdata[4];
  206. long idata;
  207. } data;
  208. __u8 temp;
  209. /* Clear the write protect bit */
  210. temp = 0x55;
  211. via_pram_command(0x35, &temp);
  212. data.idata = time + RTC_OFFSET;
  213. via_pram_command(0x01, &data.cdata[3]);
  214. via_pram_command(0x05, &data.cdata[2]);
  215. via_pram_command(0x09, &data.cdata[1]);
  216. via_pram_command(0x0D, &data.cdata[0]);
  217. /* Set the write protect bit */
  218. temp = 0xD5;
  219. via_pram_command(0x35, &temp);
  220. }
  221. static void via_shutdown(void)
  222. {
  223. if (rbv_present) {
  224. via2[rBufB] &= ~0x04;
  225. } else {
  226. /* Direction of vDirB is output */
  227. via2[vDirB] |= 0x04;
  228. /* Send a value of 0 on that line */
  229. via2[vBufB] &= ~0x04;
  230. mdelay(1000);
  231. }
  232. }
  233. /*
  234. * FIXME: not sure how this is supposed to work exactly...
  235. */
  236. static void oss_shutdown(void)
  237. {
  238. oss->rom_ctrl = OSS_POWEROFF;
  239. }
  240. #ifdef CONFIG_ADB_CUDA
  241. static void cuda_restart(void)
  242. {
  243. adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
  244. 2, CUDA_PACKET, CUDA_RESET_SYSTEM);
  245. }
  246. static void cuda_shutdown(void)
  247. {
  248. adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
  249. 2, CUDA_PACKET, CUDA_POWERDOWN);
  250. }
  251. #endif /* CONFIG_ADB_CUDA */
  252. #ifdef CONFIG_ADB_PMU
  253. void pmu_restart(void)
  254. {
  255. adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
  256. 3, PMU_PACKET, PMU_SET_INTR_MASK,
  257. PMU_INT_ADB|PMU_INT_TICK);
  258. adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
  259. 2, PMU_PACKET, PMU_RESET);
  260. }
  261. void pmu_shutdown(void)
  262. {
  263. adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
  264. 3, PMU_PACKET, PMU_SET_INTR_MASK,
  265. PMU_INT_ADB|PMU_INT_TICK);
  266. adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
  267. 6, PMU_PACKET, PMU_SHUTDOWN,
  268. 'M', 'A', 'T', 'T');
  269. }
  270. #endif /* CONFIG_ADB_PMU */
  271. /*
  272. *-------------------------------------------------------------------
  273. * Below this point are the generic routines; they'll dispatch to the
  274. * correct routine for the hardware on which we're running.
  275. *-------------------------------------------------------------------
  276. */
  277. void mac_pram_read(int offset, __u8 *buffer, int len)
  278. {
  279. __u8 (*func)(int) = NULL;
  280. int i;
  281. if (macintosh_config->adb_type == MAC_ADB_IISI ||
  282. macintosh_config->adb_type == MAC_ADB_PB1 ||
  283. macintosh_config->adb_type == MAC_ADB_PB2 ||
  284. macintosh_config->adb_type == MAC_ADB_CUDA) {
  285. #ifdef CONFIG_ADB
  286. func = adb_read_pram;
  287. #else
  288. return;
  289. #endif
  290. } else {
  291. func = via_read_pram;
  292. }
  293. for (i = 0 ; i < len ; i++) {
  294. buffer[i] = (*func)(offset++);
  295. }
  296. }
  297. void mac_pram_write(int offset, __u8 *buffer, int len)
  298. {
  299. void (*func)(int, __u8) = NULL;
  300. int i;
  301. if (macintosh_config->adb_type == MAC_ADB_IISI ||
  302. macintosh_config->adb_type == MAC_ADB_PB1 ||
  303. macintosh_config->adb_type == MAC_ADB_PB2 ||
  304. macintosh_config->adb_type == MAC_ADB_CUDA) {
  305. #ifdef CONFIG_ADB
  306. func = adb_write_pram;
  307. #else
  308. return;
  309. #endif
  310. } else {
  311. func = via_write_pram;
  312. }
  313. for (i = 0 ; i < len ; i++) {
  314. (*func)(offset++, buffer[i]);
  315. }
  316. }
  317. void mac_poweroff(void)
  318. {
  319. /*
  320. * MAC_ADB_IISI may need to be moved up here if it doesn't actually
  321. * work using the ADB packet method. --David Kilzer
  322. */
  323. if (oss_present) {
  324. oss_shutdown();
  325. } else if (macintosh_config->adb_type == MAC_ADB_II) {
  326. via_shutdown();
  327. #ifdef CONFIG_ADB_CUDA
  328. } else if (macintosh_config->adb_type == MAC_ADB_CUDA) {
  329. cuda_shutdown();
  330. #endif
  331. #ifdef CONFIG_ADB_PMU
  332. } else if (macintosh_config->adb_type == MAC_ADB_PB1
  333. || macintosh_config->adb_type == MAC_ADB_PB2) {
  334. pmu_shutdown();
  335. #endif
  336. }
  337. local_irq_enable();
  338. printk("It is now safe to turn off your Macintosh.\n");
  339. while(1);
  340. }
  341. void mac_reset(void)
  342. {
  343. if (macintosh_config->adb_type == MAC_ADB_II) {
  344. unsigned long flags;
  345. /* need ROMBASE in booter */
  346. /* indeed, plus need to MAP THE ROM !! */
  347. if (mac_bi_data.rombase == 0)
  348. mac_bi_data.rombase = 0x40800000;
  349. /* works on some */
  350. rom_reset = (void *) (mac_bi_data.rombase + 0xa);
  351. if (macintosh_config->ident == MAC_MODEL_SE30) {
  352. /*
  353. * MSch: Machines known to crash on ROM reset ...
  354. */
  355. } else {
  356. local_irq_save(flags);
  357. rom_reset();
  358. local_irq_restore(flags);
  359. }
  360. #ifdef CONFIG_ADB_CUDA
  361. } else if (macintosh_config->adb_type == MAC_ADB_CUDA) {
  362. cuda_restart();
  363. #endif
  364. #ifdef CONFIG_ADB_PMU
  365. } else if (macintosh_config->adb_type == MAC_ADB_PB1
  366. || macintosh_config->adb_type == MAC_ADB_PB2) {
  367. pmu_restart();
  368. #endif
  369. } else if (CPU_IS_030) {
  370. /* 030-specific reset routine. The idea is general, but the
  371. * specific registers to reset are '030-specific. Until I
  372. * have a non-030 machine, I can't test anything else.
  373. * -- C. Scott Ananian <cananian@alumni.princeton.edu>
  374. */
  375. unsigned long rombase = 0x40000000;
  376. /* make a 1-to-1 mapping, using the transparent tran. reg. */
  377. unsigned long virt = (unsigned long) mac_reset;
  378. unsigned long phys = virt_to_phys(mac_reset);
  379. unsigned long offset = phys-virt;
  380. local_irq_disable(); /* lets not screw this up, ok? */
  381. __asm__ __volatile__(".chip 68030\n\t"
  382. "pmove %0,%/tt0\n\t"
  383. ".chip 68k"
  384. : : "m" ((phys&0xFF000000)|0x8777));
  385. /* Now jump to physical address so we can disable MMU */
  386. __asm__ __volatile__(
  387. ".chip 68030\n\t"
  388. "lea %/pc@(1f),%/a0\n\t"
  389. "addl %0,%/a0\n\t"/* fixup target address and stack ptr */
  390. "addl %0,%/sp\n\t"
  391. "pflusha\n\t"
  392. "jmp %/a0@\n\t" /* jump into physical memory */
  393. "0:.long 0\n\t" /* a constant zero. */
  394. /* OK. Now reset everything and jump to reset vector. */
  395. "1:\n\t"
  396. "lea %/pc@(0b),%/a0\n\t"
  397. "pmove %/a0@, %/tc\n\t" /* disable mmu */
  398. "pmove %/a0@, %/tt0\n\t" /* disable tt0 */
  399. "pmove %/a0@, %/tt1\n\t" /* disable tt1 */
  400. "movel #0, %/a0\n\t"
  401. "movec %/a0, %/vbr\n\t" /* clear vector base register */
  402. "movec %/a0, %/cacr\n\t" /* disable caches */
  403. "movel #0x0808,%/a0\n\t"
  404. "movec %/a0, %/cacr\n\t" /* flush i&d caches */
  405. "movew #0x2700,%/sr\n\t" /* set up status register */
  406. "movel %1@(0x0),%/a0\n\t"/* load interrupt stack pointer */
  407. "movec %/a0, %/isp\n\t"
  408. "movel %1@(0x4),%/a0\n\t" /* load reset vector */
  409. "reset\n\t" /* reset external devices */
  410. "jmp %/a0@\n\t" /* jump to the reset vector */
  411. ".chip 68k"
  412. : : "r" (offset), "a" (rombase) : "a0");
  413. }
  414. /* should never get here */
  415. local_irq_enable();
  416. printk ("Restart failed. Please restart manually.\n");
  417. while(1);
  418. }
  419. /*
  420. * This function translates seconds since 1970 into a proper date.
  421. *
  422. * Algorithm cribbed from glibc2.1, __offtime().
  423. */
  424. #define SECS_PER_MINUTE (60)
  425. #define SECS_PER_HOUR (SECS_PER_MINUTE * 60)
  426. #define SECS_PER_DAY (SECS_PER_HOUR * 24)
  427. static void unmktime(unsigned long time, long offset,
  428. int *yearp, int *monp, int *dayp,
  429. int *hourp, int *minp, int *secp)
  430. {
  431. /* How many days come before each month (0-12). */
  432. static const unsigned short int __mon_yday[2][13] =
  433. {
  434. /* Normal years. */
  435. { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
  436. /* Leap years. */
  437. { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
  438. };
  439. long int days, rem, y, wday, yday;
  440. const unsigned short int *ip;
  441. days = time / SECS_PER_DAY;
  442. rem = time % SECS_PER_DAY;
  443. rem += offset;
  444. while (rem < 0) {
  445. rem += SECS_PER_DAY;
  446. --days;
  447. }
  448. while (rem >= SECS_PER_DAY) {
  449. rem -= SECS_PER_DAY;
  450. ++days;
  451. }
  452. *hourp = rem / SECS_PER_HOUR;
  453. rem %= SECS_PER_HOUR;
  454. *minp = rem / SECS_PER_MINUTE;
  455. *secp = rem % SECS_PER_MINUTE;
  456. /* January 1, 1970 was a Thursday. */
  457. wday = (4 + days) % 7; /* Day in the week. Not currently used */
  458. if (wday < 0) wday += 7;
  459. y = 1970;
  460. #define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
  461. #define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
  462. #define __isleap(year) \
  463. ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
  464. while (days < 0 || days >= (__isleap (y) ? 366 : 365))
  465. {
  466. /* Guess a corrected year, assuming 365 days per year. */
  467. long int yg = y + days / 365 - (days % 365 < 0);
  468. /* Adjust DAYS and Y to match the guessed year. */
  469. days -= ((yg - y) * 365
  470. + LEAPS_THRU_END_OF (yg - 1)
  471. - LEAPS_THRU_END_OF (y - 1));
  472. y = yg;
  473. }
  474. *yearp = y - 1900;
  475. yday = days; /* day in the year. Not currently used. */
  476. ip = __mon_yday[__isleap(y)];
  477. for (y = 11; days < (long int) ip[y]; --y)
  478. continue;
  479. days -= ip[y];
  480. *monp = y;
  481. *dayp = days + 1; /* day in the month */
  482. return;
  483. }
  484. /*
  485. * Read/write the hardware clock.
  486. */
  487. int mac_hwclk(int op, struct rtc_time *t)
  488. {
  489. unsigned long now;
  490. if (!op) { /* read */
  491. if (macintosh_config->adb_type == MAC_ADB_II) {
  492. now = via_read_time();
  493. } else
  494. #ifdef CONFIG_ADB
  495. if ((macintosh_config->adb_type == MAC_ADB_IISI) ||
  496. (macintosh_config->adb_type == MAC_ADB_PB1) ||
  497. (macintosh_config->adb_type == MAC_ADB_PB2) ||
  498. (macintosh_config->adb_type == MAC_ADB_CUDA)) {
  499. now = adb_read_time();
  500. } else
  501. #endif
  502. if (macintosh_config->adb_type == MAC_ADB_IOP) {
  503. now = via_read_time();
  504. } else {
  505. now = 0;
  506. }
  507. t->tm_wday = 0;
  508. unmktime(now, 0,
  509. &t->tm_year, &t->tm_mon, &t->tm_mday,
  510. &t->tm_hour, &t->tm_min, &t->tm_sec);
  511. printk("mac_hwclk: read %04d-%02d-%-2d %02d:%02d:%02d\n",
  512. t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
  513. } else { /* write */
  514. printk("mac_hwclk: tried to write %04d-%02d-%-2d %02d:%02d:%02d\n",
  515. t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
  516. #if 0 /* it trashes my rtc */
  517. now = mktime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
  518. t->tm_hour, t->tm_min, t->tm_sec);
  519. if (macintosh_config->adb_type == MAC_ADB_II) {
  520. via_write_time(now);
  521. } else if ((macintosh_config->adb_type == MAC_ADB_IISI) ||
  522. (macintosh_config->adb_type == MAC_ADB_PB1) ||
  523. (macintosh_config->adb_type == MAC_ADB_PB2) ||
  524. (macintosh_config->adb_type == MAC_ADB_CUDA)) {
  525. adb_write_time(now);
  526. } else if (macintosh_config->adb_type == MAC_ADB_IOP) {
  527. via_write_time(now);
  528. }
  529. #endif
  530. }
  531. return 0;
  532. }
  533. /*
  534. * Set minutes/seconds in the hardware clock
  535. */
  536. int mac_set_clock_mmss (unsigned long nowtime)
  537. {
  538. struct rtc_time now;
  539. mac_hwclk(0, &now);
  540. now.tm_sec = nowtime % 60;
  541. now.tm_min = (nowtime / 60) % 60;
  542. mac_hwclk(1, &now);
  543. return 0;
  544. }