Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* Prom access routines for the sun3x */ |
| 2 | |
| 3 | #include <linux/types.h> |
| 4 | #include <linux/kernel.h> |
| 5 | #include <linux/tty.h> |
| 6 | #include <linux/console.h> |
| 7 | #include <linux/init.h> |
| 8 | #include <linux/mm.h> |
| 9 | #include <linux/string.h> |
| 10 | |
| 11 | #include <asm/page.h> |
| 12 | #include <asm/pgtable.h> |
| 13 | #include <asm/bootinfo.h> |
| 14 | #include <asm/setup.h> |
| 15 | #include <asm/traps.h> |
| 16 | #include <asm/sun3xprom.h> |
| 17 | #include <asm/idprom.h> |
| 18 | #include <asm/segment.h> |
| 19 | #include <asm/sun3ints.h> |
| 20 | #include <asm/openprom.h> |
| 21 | #include <asm/machines.h> |
| 22 | |
| 23 | void (*sun3x_putchar)(int); |
| 24 | int (*sun3x_getchar)(void); |
| 25 | int (*sun3x_mayget)(void); |
| 26 | int (*sun3x_mayput)(int); |
| 27 | void (*sun3x_prom_reboot)(void); |
| 28 | e_vector sun3x_prom_abort; |
| 29 | struct linux_romvec *romvec; |
| 30 | |
| 31 | /* prom vector table */ |
| 32 | e_vector *sun3x_prom_vbr; |
| 33 | |
| 34 | /* Handle returning to the prom */ |
| 35 | void sun3x_halt(void) |
| 36 | { |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame^] | 37 | unsigned long flags; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 38 | |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame^] | 39 | /* Disable interrupts while we mess with things */ |
| 40 | local_irq_save(flags); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 41 | |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame^] | 42 | /* Restore prom vbr */ |
| 43 | asm volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr)); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 44 | |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame^] | 45 | /* Restore prom NMI clock */ |
| 46 | // sun3x_disable_intreg(5); |
| 47 | sun3_enable_irq(7); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 48 | |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame^] | 49 | /* Let 'er rip */ |
| 50 | asm volatile ("trap #14"); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 51 | |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame^] | 52 | /* Restore everything */ |
| 53 | sun3_disable_irq(7); |
| 54 | sun3_enable_irq(5); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 55 | |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame^] | 56 | asm volatile ("movec %0,%%vbr" : : "r" ((void*)vectors)); |
| 57 | local_irq_restore(flags); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 58 | } |
| 59 | |
| 60 | void sun3x_reboot(void) |
| 61 | { |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame^] | 62 | /* This never returns, don't bother saving things */ |
| 63 | local_irq_disable(); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 64 | |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame^] | 65 | /* Restore prom vbr */ |
| 66 | asm volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr)); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 67 | |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame^] | 68 | /* Restore prom NMI clock */ |
| 69 | sun3_disable_irq(5); |
| 70 | sun3_enable_irq(7); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 71 | |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame^] | 72 | /* Let 'er rip */ |
| 73 | (*romvec->pv_reboot)("vmlinux"); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 74 | } |
| 75 | |
| 76 | extern char m68k_debug_device[]; |
| 77 | |
| 78 | static void sun3x_prom_write(struct console *co, const char *s, |
| 79 | unsigned int count) |
| 80 | { |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame^] | 81 | while (count--) { |
| 82 | if (*s == '\n') |
| 83 | sun3x_putchar('\r'); |
| 84 | sun3x_putchar(*s++); |
| 85 | } |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 86 | } |
| 87 | |
| 88 | /* debug console - write-only */ |
| 89 | |
| 90 | static struct console sun3x_debug = { |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame^] | 91 | .name = "debug", |
| 92 | .write = sun3x_prom_write, |
| 93 | .flags = CON_PRINTBUFFER, |
| 94 | .index = -1, |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 95 | }; |
| 96 | |
| 97 | void sun3x_prom_init(void) |
| 98 | { |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame^] | 99 | /* Read the vector table */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 100 | |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame^] | 101 | sun3x_putchar = *(void (**)(int)) (SUN3X_P_PUTCHAR); |
| 102 | sun3x_getchar = *(int (**)(void)) (SUN3X_P_GETCHAR); |
| 103 | sun3x_mayget = *(int (**)(void)) (SUN3X_P_MAYGET); |
| 104 | sun3x_mayput = *(int (**)(int)) (SUN3X_P_MAYPUT); |
| 105 | sun3x_prom_reboot = *(void (**)(void)) (SUN3X_P_REBOOT); |
| 106 | sun3x_prom_abort = *(e_vector *) (SUN3X_P_ABORT); |
| 107 | romvec = (struct linux_romvec *)SUN3X_PROM_BASE; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 108 | |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame^] | 109 | idprom_init(); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 110 | |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame^] | 111 | if (!((idprom->id_machtype & SM_ARCH_MASK) == SM_SUN3X)) { |
| 112 | printk("Warning: machine reports strange type %02x\n", |
| 113 | idprom->id_machtype); |
| 114 | printk("Pretending it's a 3/80, but very afraid...\n"); |
| 115 | idprom->id_machtype = SM_SUN3X | SM_3_80; |
| 116 | } |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 117 | |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame^] | 118 | /* point trap #14 at abort. |
| 119 | * XXX this is futile since we restore the vbr first - oops |
| 120 | */ |
| 121 | vectors[VEC_TRAP14] = sun3x_prom_abort; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 122 | |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame^] | 123 | /* If debug=prom was specified, start the debug console */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 124 | |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame^] | 125 | if (!strcmp(m68k_debug_device, "prom")) |
| 126 | register_console(&sun3x_debug); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 127 | } |
| 128 | |
| 129 | /* some prom functions to export */ |
| 130 | int prom_getintdefault(int node, char *property, int deflt) |
| 131 | { |
| 132 | return deflt; |
| 133 | } |
| 134 | |
| 135 | int prom_getbool (int node, char *prop) |
| 136 | { |
| 137 | return 1; |
| 138 | } |
| 139 | |
| 140 | void prom_printf(char *fmt, ...) |
| 141 | { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 142 | } |
| 143 | |
| 144 | void prom_halt (void) |
| 145 | { |
| 146 | sun3x_halt(); |
| 147 | } |
| 148 | |
| 149 | /* Get the idprom and stuff it into buffer 'idbuf'. Returns the |
| 150 | * format type. 'num_bytes' is the number of bytes that your idbuf |
| 151 | * has space for. Returns 0xff on error. |
| 152 | */ |
| 153 | unsigned char |
| 154 | prom_get_idprom(char *idbuf, int num_bytes) |
| 155 | { |
| 156 | int i; |
| 157 | |
| 158 | /* make a copy of the idprom structure */ |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame^] | 159 | for (i = 0; i < num_bytes; i++) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 160 | idbuf[i] = ((char *)SUN3X_IDPROM)[i]; |
| 161 | |
| 162 | return idbuf[0]; |
| 163 | } |