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 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 76 | static void sun3x_prom_write(struct console *co, const char *s, |
| 77 | unsigned int count) |
| 78 | { |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame] | 79 | while (count--) { |
| 80 | if (*s == '\n') |
| 81 | sun3x_putchar('\r'); |
| 82 | sun3x_putchar(*s++); |
| 83 | } |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 84 | } |
| 85 | |
| 86 | /* debug console - write-only */ |
| 87 | |
| 88 | static struct console sun3x_debug = { |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame] | 89 | .name = "debug", |
| 90 | .write = sun3x_prom_write, |
| 91 | .flags = CON_PRINTBUFFER, |
| 92 | .index = -1, |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 93 | }; |
| 94 | |
Al Viro | 66a3f82 | 2007-07-20 04:33:28 +0100 | [diff] [blame] | 95 | void __init sun3x_prom_init(void) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 96 | { |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame] | 97 | /* Read the vector table */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 98 | |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame] | 99 | sun3x_putchar = *(void (**)(int)) (SUN3X_P_PUTCHAR); |
| 100 | sun3x_getchar = *(int (**)(void)) (SUN3X_P_GETCHAR); |
| 101 | sun3x_mayget = *(int (**)(void)) (SUN3X_P_MAYGET); |
| 102 | sun3x_mayput = *(int (**)(int)) (SUN3X_P_MAYPUT); |
| 103 | sun3x_prom_reboot = *(void (**)(void)) (SUN3X_P_REBOOT); |
| 104 | sun3x_prom_abort = *(e_vector *) (SUN3X_P_ABORT); |
| 105 | romvec = (struct linux_romvec *)SUN3X_PROM_BASE; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 106 | |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame] | 107 | idprom_init(); |
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 | if (!((idprom->id_machtype & SM_ARCH_MASK) == SM_SUN3X)) { |
| 110 | printk("Warning: machine reports strange type %02x\n", |
| 111 | idprom->id_machtype); |
| 112 | printk("Pretending it's a 3/80, but very afraid...\n"); |
| 113 | idprom->id_machtype = SM_SUN3X | SM_3_80; |
| 114 | } |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 115 | |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame] | 116 | /* point trap #14 at abort. |
| 117 | * XXX this is futile since we restore the vbr first - oops |
| 118 | */ |
| 119 | vectors[VEC_TRAP14] = sun3x_prom_abort; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 120 | } |
| 121 | |
Roman Zippel | d6713b4 | 2007-05-01 22:32:45 +0200 | [diff] [blame] | 122 | static int __init sun3x_debug_setup(char *arg) |
| 123 | { |
| 124 | /* If debug=prom was specified, start the debug console */ |
| 125 | if (MACH_IS_SUN3X && !strcmp(arg, "prom")) |
| 126 | register_console(&sun3x_debug); |
| 127 | return 0; |
| 128 | } |
| 129 | |
| 130 | early_param("debug", sun3x_debug_setup); |
| 131 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 132 | /* some prom functions to export */ |
| 133 | int prom_getintdefault(int node, char *property, int deflt) |
| 134 | { |
| 135 | return deflt; |
| 136 | } |
| 137 | |
| 138 | int prom_getbool (int node, char *prop) |
| 139 | { |
| 140 | return 1; |
| 141 | } |
| 142 | |
| 143 | void prom_printf(char *fmt, ...) |
| 144 | { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 145 | } |
| 146 | |
| 147 | void prom_halt (void) |
| 148 | { |
| 149 | sun3x_halt(); |
| 150 | } |
| 151 | |
| 152 | /* Get the idprom and stuff it into buffer 'idbuf'. Returns the |
| 153 | * format type. 'num_bytes' is the number of bytes that your idbuf |
| 154 | * has space for. Returns 0xff on error. |
| 155 | */ |
| 156 | unsigned char |
| 157 | prom_get_idprom(char *idbuf, int num_bytes) |
| 158 | { |
| 159 | int i; |
| 160 | |
| 161 | /* make a copy of the idprom structure */ |
Roman Zippel | 6ff5801 | 2007-05-01 22:32:43 +0200 | [diff] [blame] | 162 | for (i = 0; i < num_bytes; i++) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 163 | idbuf[i] = ((char *)SUN3X_IDPROM)[i]; |
| 164 | |
| 165 | return idbuf[0]; |
| 166 | } |