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