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